13
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								package.json
									
									
									
									
									
								
							@@ -11,6 +11,7 @@
 | 
			
		||||
    "stylelint": "stylelint resources/assets/sass/**/*"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/jquery": "^3.3.29",
 | 
			
		||||
    "bootstrap": "^4.3.1",
 | 
			
		||||
    "cal-heatmap": "^3.3.10",
 | 
			
		||||
    "chart.js": "^2.7.1",
 | 
			
		||||
@@ -28,7 +29,12 @@
 | 
			
		||||
    "sass-loader": "^7.1.0",
 | 
			
		||||
    "stylelint": "^9.10.1",
 | 
			
		||||
    "stylelint-config-recess-order": "^2.0.1",
 | 
			
		||||
    "vue-template-compiler": "^2.6.6"
 | 
			
		||||
    "ts-loader": "^6.0.1",
 | 
			
		||||
    "typescript": "^3.4.5",
 | 
			
		||||
    "vue": "^2.6.10",
 | 
			
		||||
    "vue-class-component": "^7.1.0",
 | 
			
		||||
    "vue-property-decorator": "^8.1.1",
 | 
			
		||||
    "vue-template-compiler": "^2.6.10"
 | 
			
		||||
  },
 | 
			
		||||
  "stylelint": {
 | 
			
		||||
    "extends": "stylelint-config-recess-order"
 | 
			
		||||
@@ -39,6 +45,9 @@
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "lint-staged": {
 | 
			
		||||
    "*.{css,scss}": ["stylelint --fix", "git add"]
 | 
			
		||||
    "*.{css,scss}": [
 | 
			
		||||
      "stylelint --fix",
 | 
			
		||||
      "git add"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								resources/assets/js/checkin.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								resources/assets/js/checkin.js
									
									
									
									
										vendored
									
									
								
							@@ -1,58 +0,0 @@
 | 
			
		||||
function updateTags() {
 | 
			
		||||
    $('input[name=tags]').val(
 | 
			
		||||
        $('#tags')
 | 
			
		||||
            .find('li')
 | 
			
		||||
            .map(function () {
 | 
			
		||||
                return $(this).data('value');
 | 
			
		||||
            })
 | 
			
		||||
            .get()
 | 
			
		||||
            .join(' ')
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function insertTag(value) {
 | 
			
		||||
    $('<li class="list-inline-item badge badge-primary" style="cursor: pointer;"><span class="oi oi-tag"></span> <span></span> | x</li>')
 | 
			
		||||
        .data('value', value)
 | 
			
		||||
        .children(':last-child')
 | 
			
		||||
            .text(value)
 | 
			
		||||
            .end()
 | 
			
		||||
        .appendTo('#tags');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var initTags = $('input[name=tags]').val();
 | 
			
		||||
if (initTags.trim() !== '') {
 | 
			
		||||
    initTags.split(' ').forEach(function (value) {
 | 
			
		||||
        insertTag(value);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$('#tagInput').on('keydown', function (ev) {
 | 
			
		||||
    var $this = $(this);
 | 
			
		||||
    if ($this.val().trim() !== '') {
 | 
			
		||||
        switch (ev.key) {
 | 
			
		||||
            case 'Tab':
 | 
			
		||||
            case 'Enter':
 | 
			
		||||
            case ' ':
 | 
			
		||||
                if (ev.originalEvent.isComposing !== true) {
 | 
			
		||||
                    insertTag($this.val().trim());
 | 
			
		||||
                    $this.val('');
 | 
			
		||||
                    updateTags();
 | 
			
		||||
                }
 | 
			
		||||
                ev.preventDefault();
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (ev.key === 'Enter') {
 | 
			
		||||
        // 誤爆防止
 | 
			
		||||
        ev.preventDefault();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
$('#tags')
 | 
			
		||||
    .on('click', 'li', function (ev) {
 | 
			
		||||
        $(this).remove();
 | 
			
		||||
        updateTags();
 | 
			
		||||
    })
 | 
			
		||||
    .parent()
 | 
			
		||||
    .on('click', function (ev) {
 | 
			
		||||
        $('#tagInput').focus();
 | 
			
		||||
    });
 | 
			
		||||
							
								
								
									
										9
									
								
								resources/assets/js/checkin.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								resources/assets/js/checkin.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import TagInput from "./components/TagInput.vue";
 | 
			
		||||
 | 
			
		||||
new Vue({
 | 
			
		||||
    el: '#app',
 | 
			
		||||
    components: {
 | 
			
		||||
        TagInput
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										77
									
								
								resources/assets/js/components/TagInput.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								resources/assets/js/components/TagInput.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div :class="containerClass" @click="$refs.input.focus()">
 | 
			
		||||
        <input :name="name" type="hidden" :value="tagValue">
 | 
			
		||||
        <ul class="list-inline d-inline">
 | 
			
		||||
            <li v-for="(tag, i) in tags"
 | 
			
		||||
                class="list-inline-item badge badge-primary tag-item"
 | 
			
		||||
                @click="removeTag(i)"><span class="oi oi-tag"></span> {{ tag }} | x</li>
 | 
			
		||||
        </ul>
 | 
			
		||||
        <input :id="id"
 | 
			
		||||
               ref="input"
 | 
			
		||||
               type="text"
 | 
			
		||||
               class="tag-input"
 | 
			
		||||
               v-model="buffer"
 | 
			
		||||
               @keydown="onKeyDown">
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import {Vue, Component, Prop} from "vue-property-decorator";
 | 
			
		||||
 | 
			
		||||
    @Component
 | 
			
		||||
    export default class TagInput extends Vue {
 | 
			
		||||
        @Prop(String) readonly id!: string;
 | 
			
		||||
        @Prop(String) readonly name!: string;
 | 
			
		||||
        @Prop(String) readonly value!: string;
 | 
			
		||||
        @Prop(Boolean) readonly isInvalid!: boolean;
 | 
			
		||||
 | 
			
		||||
        tags: string[] = this.value.trim() !== "" ? this.value.trim().split(" ") : [];
 | 
			
		||||
        buffer: string = "";
 | 
			
		||||
 | 
			
		||||
        onKeyDown(event: KeyboardEvent) {
 | 
			
		||||
            if (this.buffer.trim() !== "") {
 | 
			
		||||
                switch (event.key) {
 | 
			
		||||
                    case 'Tab':
 | 
			
		||||
                    case 'Enter':
 | 
			
		||||
                    case ' ':
 | 
			
		||||
                        if ((event as any).isComposing !== true) {
 | 
			
		||||
                            this.tags.push(this.buffer);
 | 
			
		||||
                            this.buffer = "";
 | 
			
		||||
                        }
 | 
			
		||||
                        event.preventDefault();
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            } else if (event.key === "Enter") {
 | 
			
		||||
                // 誤爆防止
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        removeTag(index: number) {
 | 
			
		||||
            this.tags.splice(index, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get containerClass(): object {
 | 
			
		||||
            return {
 | 
			
		||||
                "form-control": true,
 | 
			
		||||
                "h-auto": true,
 | 
			
		||||
                "is-invalid": this.isInvalid
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get tagValue(): string {
 | 
			
		||||
            return this.tags.join(" ");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
    .tag-item {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .tag-input {
 | 
			
		||||
        border: 0;
 | 
			
		||||
        outline: 0;
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										4
									
								
								resources/assets/js/vue-shims.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								resources/assets/js/vue-shims.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
declare module "*.vue" {
 | 
			
		||||
    import Vue from "vue";
 | 
			
		||||
    export default Vue;
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
@section('title', 'チェックイン')
 | 
			
		||||
 | 
			
		||||
@section('content')
 | 
			
		||||
<div class="container">
 | 
			
		||||
<div id="app" class="container">
 | 
			
		||||
    <h2>今致してる?</h2>
 | 
			
		||||
    <hr>
 | 
			
		||||
    <div class="row justify-content-center mt-5">
 | 
			
		||||
@@ -38,12 +38,8 @@
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-row">
 | 
			
		||||
                    <div class="form-group col-sm-12">
 | 
			
		||||
                        <input name="tags" type="hidden" value="{{ old('tags') ?? $defaults['tags'] }}">
 | 
			
		||||
                        <label for="tagInput"><span class="oi oi-tags"></span> タグ</label>
 | 
			
		||||
                        <div class="form-control h-auto {{ $errors->has('tags') ? ' is-invalid' : '' }}">
 | 
			
		||||
                            <ul id="tags" class="list-inline d-inline"></ul>
 | 
			
		||||
                            <input id="tagInput" type="text" style="outline: 0; border: 0;">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <tag-input id="tagInput" name="tags" value="{{ old('tags') ?? $defaults['tags'] }}" :is-invalid="{{ $errors->has('tags') ? 'true' : 'false' }}"></tag-input>
 | 
			
		||||
                        <small class="form-text text-muted">
 | 
			
		||||
                            Tab, Enter, 半角スペースのいずれかで入力確定します。
 | 
			
		||||
                        </small>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
@section('title', 'チェックインの修正')
 | 
			
		||||
 | 
			
		||||
@section('content')
 | 
			
		||||
<div class="container">
 | 
			
		||||
<div id="app" class="container">
 | 
			
		||||
    <h2>チェックインの修正</h2>
 | 
			
		||||
    <hr>
 | 
			
		||||
    <div class="row justify-content-center mt-5">
 | 
			
		||||
@@ -39,12 +39,8 @@
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-row">
 | 
			
		||||
                    <div class="form-group col-sm-12">
 | 
			
		||||
                        <input name="tags" type="hidden" value="{{ old('tags') ?? $ejaculation->textTags() }}">
 | 
			
		||||
                        <label for="tagInput"><span class="oi oi-tags"></span> タグ</label>
 | 
			
		||||
                        <div class="form-control h-auto {{ $errors->has('tags') ? ' is-invalid' : '' }}">
 | 
			
		||||
                            <ul id="tags" class="list-inline d-inline"></ul>
 | 
			
		||||
                            <input id="tagInput" type="text" style="outline: 0; border: 0;">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <tag-input id="tagInput" name="tags" value="{{ old('tags') ?? $ejaculation->textTags() }}" :is-invalid="{{ $errors->has('tags') ? 'true' : 'false' }}"></tag-input>
 | 
			
		||||
                        <small class="form-text text-muted">
 | 
			
		||||
                            Tab, Enter, 半角スペースのいずれかで入力確定します。
 | 
			
		||||
                        </small>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "sourceMap": true,
 | 
			
		||||
    "target": "es5",
 | 
			
		||||
    "module": "es2015",
 | 
			
		||||
    "moduleResolution": "node",
 | 
			
		||||
    "strict": true,
 | 
			
		||||
    "experimentalDecorators": true
 | 
			
		||||
  },
 | 
			
		||||
  "include": [
 | 
			
		||||
    "resources/assets/js/**/*"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								webpack.mix.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								webpack.mix.js
									
									
									
									
										vendored
									
									
								
							@@ -16,7 +16,7 @@ mix.js('resources/assets/js/app.js', 'public/js')
 | 
			
		||||
    .js('resources/assets/js/home.js', 'public/js')
 | 
			
		||||
    .js('resources/assets/js/user/stats.js', 'public/js/user')
 | 
			
		||||
    .js('resources/assets/js/setting/privacy.js', 'public/js/setting')
 | 
			
		||||
    .js('resources/assets/js/checkin.js', 'public/js')
 | 
			
		||||
    .ts('resources/assets/js/checkin.ts', 'public/js')
 | 
			
		||||
    .sass('resources/assets/sass/app.scss', 'public/css')
 | 
			
		||||
    .autoload({
 | 
			
		||||
        'jquery': ['$', 'jQuery', 'window.jQuery']
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								yarn.lock
									
									
									
									
									
								
							@@ -7830,6 +7830,11 @@ vm-browserify@0.0.4:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    indexof "0.0.1"
 | 
			
		||||
 | 
			
		||||
vue-class-component@^7.0.1, vue-class-component@^7.1.0:
 | 
			
		||||
  version "7.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-7.1.0.tgz#b33efcb10e17236d684f70b1e96f1946ec793e87"
 | 
			
		||||
  integrity sha512-G9152NzUkz0i0xTfhk0Afc8vzdXxDR1pfN4dTwE72cskkgJtdXfrKBkMfGvDuxUh35U500g5Ve4xL8PEGdWeHg==
 | 
			
		||||
 | 
			
		||||
vue-hot-reload-api@^2.3.0:
 | 
			
		||||
  version "2.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.2.tgz#1fcc1495effe08a790909b46bf7b5c4cfeb6f21b"
 | 
			
		||||
@@ -7846,6 +7851,13 @@ vue-loader@^15.4.2:
 | 
			
		||||
    vue-hot-reload-api "^2.3.0"
 | 
			
		||||
    vue-style-loader "^4.1.0"
 | 
			
		||||
 | 
			
		||||
vue-property-decorator@^8.1.1:
 | 
			
		||||
  version "8.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-8.1.1.tgz#80dadbe5ffa0e7eb6a0ba0a07036365471a7d5ee"
 | 
			
		||||
  integrity sha512-K+PUT17ZEMWyhrKZnl4Fc9qMyFpMcjVbZJBwx4BpA8BXfaspaTeFdoHuk1aywC/+4G86sxIr/5n4IQUQLecSWw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    vue-class-component "^7.0.1"
 | 
			
		||||
 | 
			
		||||
vue-style-loader@^4.1.0:
 | 
			
		||||
  version "4.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8"
 | 
			
		||||
@@ -7854,10 +7866,10 @@ vue-style-loader@^4.1.0:
 | 
			
		||||
    hash-sum "^1.0.2"
 | 
			
		||||
    loader-utils "^1.0.2"
 | 
			
		||||
 | 
			
		||||
vue-template-compiler@^2.6.6:
 | 
			
		||||
  version "2.6.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.6.tgz#a807acbf3d51971d3721d75ecb1b927b517c1a02"
 | 
			
		||||
  integrity sha512-OakxDGyrmMQViCjkakQFbDZlG0NibiOzpLauOfyCUVRQc9yPmTqpiz9nF0VeA+dFkXegetw0E5x65BFhhLXO0A==
 | 
			
		||||
vue-template-compiler@^2.6.10:
 | 
			
		||||
  version "2.6.10"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc"
 | 
			
		||||
  integrity sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    de-indent "^1.0.2"
 | 
			
		||||
    he "^1.1.0"
 | 
			
		||||
@@ -7867,6 +7879,11 @@ vue-template-es2015-compiler@^1.8.2:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz#dd73e80ba58bb65dd7a8aa2aeef6089cf6116f2a"
 | 
			
		||||
  integrity sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA==
 | 
			
		||||
 | 
			
		||||
vue@^2.6.10:
 | 
			
		||||
  version "2.6.10"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
 | 
			
		||||
  integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
 | 
			
		||||
 | 
			
		||||
watchpack@^1.5.0:
 | 
			
		||||
  version "1.6.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user