From a4fdd220ba259a3444c5fc3569454b50b4d7ddfa Mon Sep 17 00:00:00 2001 From: shibafu Date: Thu, 6 Aug 2020 01:09:25 +0900 Subject: [PATCH 01/26] =?UTF-8?q?pageSelector=E3=82=92Vanilla=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/@types/jquery-tissue.d.ts | 1 - resources/assets/js/app.ts | 3 ++- resources/assets/js/tissue.ts | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/resources/assets/js/@types/jquery-tissue.d.ts b/resources/assets/js/@types/jquery-tissue.d.ts index 3938ccb..5d49f3c 100644 --- a/resources/assets/js/@types/jquery-tissue.d.ts +++ b/resources/assets/js/@types/jquery-tissue.d.ts @@ -7,6 +7,5 @@ declare namespace JQueryTissue { interface JQuery { linkCard: (options?: JQueryTissue.LinkCardOptions) => this; - pageSelector: () => this; deleteCheckinModal: () => this; } diff --git a/resources/assets/js/app.ts b/resources/assets/js/app.ts index 1196678..6975556 100644 --- a/resources/assets/js/app.ts +++ b/resources/assets/js/app.ts @@ -1,5 +1,6 @@ import * as Cookies from 'js-cookie'; import { fetchPostJson, fetchDeleteJson, ResponseError } from './fetch'; +import { pageSelector } from './tissue'; require('./bootstrap'); @@ -20,7 +21,7 @@ $(() => { } $('[data-toggle="tooltip"]').tooltip(); $('.alert').alert(); - $('.tis-page-selector').pageSelector(); + document.querySelectorAll('.tis-page-selector').forEach(pageSelector); $('.link-card').linkCard(); const $deleteCheckinModal = $('#deleteCheckinModal').deleteCheckinModal(); diff --git a/resources/assets/js/tissue.ts b/resources/assets/js/tissue.ts index e059c75..6e12259 100644 --- a/resources/assets/js/tissue.ts +++ b/resources/assets/js/tissue.ts @@ -1,5 +1,12 @@ import { fetchGet } from './fetch'; +export function pageSelector(el: Element) { + if (!(el instanceof HTMLSelectElement)) return; + el.addEventListener('change', function () { + location.href = this.options[this.selectedIndex].dataset.href as string; + }); +} + (function ($) { $.fn.linkCard = function (options) { const settings = $.extend( @@ -52,12 +59,6 @@ import { fetchGet } from './fetch'; }); }; - $.fn.pageSelector = function () { - return this.on('change', function () { - location.href = $(this).find(':selected').data('href'); - }); - }; - $.fn.deleteCheckinModal = function () { return this.each(function () { $(this) From 8a0a29feefc6114008a3b951215d720210746054 Mon Sep 17 00:00:00 2001 From: shibafu Date: Fri, 7 Aug 2020 00:25:43 +0900 Subject: [PATCH 02/26] =?UTF-8?q?linkCard=E3=82=92Vanilla=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/@types/jquery-tissue.d.ts | 6 -- resources/assets/js/app.ts | 4 +- resources/assets/js/tissue.ts | 98 +++++++++---------- 3 files changed, 49 insertions(+), 59 deletions(-) diff --git a/resources/assets/js/@types/jquery-tissue.d.ts b/resources/assets/js/@types/jquery-tissue.d.ts index 5d49f3c..0494a7b 100644 --- a/resources/assets/js/@types/jquery-tissue.d.ts +++ b/resources/assets/js/@types/jquery-tissue.d.ts @@ -1,11 +1,5 @@ // tissue.ts で定義されているjQuery Pluginの型定義 -declare namespace JQueryTissue { - interface LinkCardOptions { - endpoint: string; - } -} interface JQuery { - linkCard: (options?: JQueryTissue.LinkCardOptions) => this; deleteCheckinModal: () => this; } diff --git a/resources/assets/js/app.ts b/resources/assets/js/app.ts index 6975556..fda7cbf 100644 --- a/resources/assets/js/app.ts +++ b/resources/assets/js/app.ts @@ -1,6 +1,6 @@ import * as Cookies from 'js-cookie'; import { fetchPostJson, fetchDeleteJson, ResponseError } from './fetch'; -import { pageSelector } from './tissue'; +import { linkCard, pageSelector } from './tissue'; require('./bootstrap'); @@ -23,7 +23,7 @@ $(() => { $('.alert').alert(); document.querySelectorAll('.tis-page-selector').forEach(pageSelector); - $('.link-card').linkCard(); + document.querySelectorAll('.link-card').forEach(linkCard); const $deleteCheckinModal = $('#deleteCheckinModal').deleteCheckinModal(); $(document).on('click', '[data-target="#deleteCheckinModal"]', function (event) { event.preventDefault(); diff --git a/resources/assets/js/tissue.ts b/resources/assets/js/tissue.ts index 6e12259..0e0b945 100644 --- a/resources/assets/js/tissue.ts +++ b/resources/assets/js/tissue.ts @@ -1,5 +1,52 @@ import { fetchGet } from './fetch'; +function suicide(e: T) { + return function (): never { + throw e; + }; +} + +export function linkCard(el: Element) { + const url = el.querySelector('a')?.href; + if (!url) { + return; + } + + fetchGet('/api/checkin/card', { url }) + .then((response) => response.json()) + .then((data) => { + const die = suicide('Element not found!'); + const metaColumn = el.querySelector('.col-12:last-of-type') || die(); + const imageColumn = el.querySelector('.col-12:first-of-type') || die(); + const title = el.querySelector('.card-title') || die(); + const desc = el.querySelector('.card-text') || die(); + const image = imageColumn.querySelector('img') || die(); + + if (data.title === '') { + title.style.display = 'none'; + } else { + title.textContent = data.title; + } + + if (data.description === '') { + desc.style.display = 'none'; + } else { + desc.textContent = data.description; + } + + if (data.image === '') { + imageColumn.style.display = 'none'; + metaColumn.classList.remove('col-md-6'); + } else { + image.src = data.image; + } + + if (data.title !== '' || data.description !== '' || data.image !== '') { + el.classList.remove('d-none'); + } + }); +} + export function pageSelector(el: Element) { if (!(el instanceof HTMLSelectElement)) return; el.addEventListener('change', function () { @@ -8,57 +55,6 @@ export function pageSelector(el: Element) { } (function ($) { - $.fn.linkCard = function (options) { - const settings = $.extend( - { - endpoint: '/api/checkin/card', - }, - options - ); - - return this.each(function () { - const $this = $(this); - - const url = $this.find('a').attr('href'); - if (!url) { - return; - } - - fetchGet(settings.endpoint, { url }) - .then((response) => response.json()) - .then((data) => { - const $metaColumn = $this.find('.col-12:last-of-type'); - const $imageColumn = $this.find('.col-12:first-of-type'); - const $title = $this.find('.card-title'); - const $desc = $this.find('.card-text'); - const $image = $imageColumn.find('img'); - - if (data.title === '') { - $title.hide(); - } else { - $title.text(data.title); - } - - if (data.description === '') { - $desc.hide(); - } else { - $desc.text(data.description); - } - - if (data.image === '') { - $imageColumn.hide(); - $metaColumn.removeClass('col-md-6'); - } else { - $image.attr('src', data.image); - } - - if (data.title !== '' || data.description !== '' || data.image !== '') { - $this.removeClass('d-none'); - } - }); - }); - }; - $.fn.deleteCheckinModal = function () { return this.each(function () { $(this) From 23189b76e40158f18371be30f071e8922a8015e4 Mon Sep 17 00:00:00 2001 From: shibafu Date: Fri, 7 Aug 2020 00:53:36 +0900 Subject: [PATCH 03/26] =?UTF-8?q?deleteCheckinModal=E3=82=92Vanilla?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/@types/jquery-tissue.d.ts | 5 -- resources/assets/js/app.ts | 16 +++--- resources/assets/js/bootstrap.ts | 3 -- resources/assets/js/tissue.ts | 53 ++++++++++--------- 4 files changed, 37 insertions(+), 40 deletions(-) delete mode 100644 resources/assets/js/@types/jquery-tissue.d.ts diff --git a/resources/assets/js/@types/jquery-tissue.d.ts b/resources/assets/js/@types/jquery-tissue.d.ts deleted file mode 100644 index 0494a7b..0000000 --- a/resources/assets/js/@types/jquery-tissue.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// tissue.ts で定義されているjQuery Pluginの型定義 - -interface JQuery { - deleteCheckinModal: () => this; -} diff --git a/resources/assets/js/app.ts b/resources/assets/js/app.ts index fda7cbf..10fdc70 100644 --- a/resources/assets/js/app.ts +++ b/resources/assets/js/app.ts @@ -1,6 +1,6 @@ import * as Cookies from 'js-cookie'; import { fetchPostJson, fetchDeleteJson, ResponseError } from './fetch'; -import { linkCard, pageSelector } from './tissue'; +import { linkCard, pageSelector, deleteCheckinModal } from './tissue'; require('./bootstrap'); @@ -24,11 +24,15 @@ $(() => { document.querySelectorAll('.tis-page-selector').forEach(pageSelector); document.querySelectorAll('.link-card').forEach(linkCard); - const $deleteCheckinModal = $('#deleteCheckinModal').deleteCheckinModal(); - $(document).on('click', '[data-target="#deleteCheckinModal"]', function (event) { - event.preventDefault(); - $deleteCheckinModal.modal('show', this); - }); + + const elDeleteCheckinModal = document.getElementById('deleteCheckinModal'); + if (elDeleteCheckinModal) { + const $deleteCheckinModal = deleteCheckinModal(elDeleteCheckinModal); + $(document).on('click', '[data-target="#deleteCheckinModal"]', function (event) { + event.preventDefault(); + $deleteCheckinModal.modal('show', this); + }); + } $(document).on('click', '[data-href]', function (_event) { location.href = $(this).data('href'); diff --git a/resources/assets/js/bootstrap.ts b/resources/assets/js/bootstrap.ts index fbfc914..02b71c6 100644 --- a/resources/assets/js/bootstrap.ts +++ b/resources/assets/js/bootstrap.ts @@ -1,5 +1,2 @@ -// jQuery -import './tissue'; - // Bootstrap import 'bootstrap'; diff --git a/resources/assets/js/tissue.ts b/resources/assets/js/tissue.ts index 0e0b945..ae2ddcb 100644 --- a/resources/assets/js/tissue.ts +++ b/resources/assets/js/tissue.ts @@ -1,6 +1,6 @@ import { fetchGet } from './fetch'; -function suicide(e: T) { +export function suicide(e: T) { return function (): never { throw e; }; @@ -45,33 +45,34 @@ export function linkCard(el: Element) { el.classList.remove('d-none'); } }); + + return el; } export function pageSelector(el: Element) { - if (!(el instanceof HTMLSelectElement)) return; - el.addEventListener('change', function () { - location.href = this.options[this.selectedIndex].dataset.href as string; - }); + if (el instanceof HTMLSelectElement) { + el.addEventListener('change', function () { + location.href = this.options[this.selectedIndex].dataset.href as string; + }); + } + return el; } -(function ($) { - $.fn.deleteCheckinModal = function () { - return this.each(function () { - $(this) - .on('show.bs.modal', function (event) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const target = $(event.relatedTarget!); - const modal = $(this); - modal.find('.modal-body .date-label').text(target.data('date')); - modal.data('id', target.data('id')); - }) - .find('.btn-danger') - .on('click', function (_event) { - const modal = $('#deleteCheckinModal'); - const form = modal.find('form'); - form.attr('action', form.attr('action')?.replace('@', modal.data('id')) || null); - form.submit(); - }); - }); - }; -})(jQuery); +export function deleteCheckinModal(el: Element) { + return $(el) + .on('show.bs.modal', function (event) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const target = $(event.relatedTarget!); + const modal = $(this); + modal.find('.modal-body .date-label').text(target.data('date')); + modal.data('id', target.data('id')); + }) + .find('.btn-danger') + .on('click', function (_event) { + const modal = $('#deleteCheckinModal'); + const form = modal.find('form'); + form.attr('action', form.attr('action')?.replace('@', modal.data('id')) || null); + form.submit(); + }) + .end(); +} From 723587b0acc49c4638df4a049903f789de205805 Mon Sep 17 00:00:00 2001 From: shibafu Date: Fri, 7 Aug 2020 09:50:01 +0900 Subject: [PATCH 04/26] =?UTF-8?q?deleteCheckinModal=E3=81=AE=E4=B8=AD?= =?UTF-8?q?=E8=BA=AB=E3=81=A7=E3=81=AA=E3=82=8B=E3=81=B9=E3=81=8FjQuery?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E3=82=8F=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/tissue.ts | 31 +++++++++------------- resources/views/ejaculation/show.blade.php | 12 ++++----- resources/views/user/profile.blade.php | 12 ++++----- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/resources/assets/js/tissue.ts b/resources/assets/js/tissue.ts index ae2ddcb..804ef4d 100644 --- a/resources/assets/js/tissue.ts +++ b/resources/assets/js/tissue.ts @@ -6,6 +6,8 @@ export function suicide(e: T) { }; } +const die = suicide('Element not found!'); + export function linkCard(el: Element) { const url = el.querySelector('a')?.href; if (!url) { @@ -15,7 +17,6 @@ export function linkCard(el: Element) { fetchGet('/api/checkin/card', { url }) .then((response) => response.json()) .then((data) => { - const die = suicide('Element not found!'); const metaColumn = el.querySelector('.col-12:last-of-type') || die(); const imageColumn = el.querySelector('.col-12:first-of-type') || die(); const title = el.querySelector('.card-title') || die(); @@ -58,21 +59,15 @@ export function pageSelector(el: Element) { return el; } -export function deleteCheckinModal(el: Element) { - return $(el) - .on('show.bs.modal', function (event) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const target = $(event.relatedTarget!); - const modal = $(this); - modal.find('.modal-body .date-label').text(target.data('date')); - modal.data('id', target.data('id')); - }) - .find('.btn-danger') - .on('click', function (_event) { - const modal = $('#deleteCheckinModal'); - const form = modal.find('form'); - form.attr('action', form.attr('action')?.replace('@', modal.data('id')) || null); - form.submit(); - }) - .end(); +export function deleteCheckinModal(modal: Element) { + let id: any = null; + modal.querySelector('form')?.addEventListener('submit', function () { + this.action = this.action.replace('@', id); + }); + return $(modal).on('show.bs.modal', function (event) { + const target = event.relatedTarget || die(); + const dateLabel = this.querySelector('.modal-body .date-label') || die(); + dateLabel.textContent = target.dataset.date || null; + id = target.dataset.id; + }); } diff --git a/resources/views/ejaculation/show.blade.php b/resources/views/ejaculation/show.blade.php index 5dea347..4f9db40 100644 --- a/resources/views/ejaculation/show.blade.php +++ b/resources/views/ejaculation/show.blade.php @@ -97,13 +97,13 @@ 削除確認 @endslot のチェックインを削除してもよろしいですか? -
- {{ csrf_field() }} - {{ method_field('DELETE') }} -
@slot('footer') - - +
+ {{ csrf_field() }} + {{ method_field('DELETE') }} + + +
@endslot @endcomponent @endsection diff --git a/resources/views/user/profile.blade.php b/resources/views/user/profile.blade.php index d850e6a..d7c39d7 100644 --- a/resources/views/user/profile.blade.php +++ b/resources/views/user/profile.blade.php @@ -117,13 +117,13 @@ 削除確認 @endslot のチェックインを削除してもよろしいですか? -
- {{ csrf_field() }} - {{ method_field('DELETE') }} -
@slot('footer') - - +
+ {{ csrf_field() }} + {{ method_field('DELETE') }} + + +
@endslot @endcomponent @endsection From 7aa11275cc135c43e2339dba96ce4318dff9c81c Mon Sep 17 00:00:00 2001 From: shibafu Date: Sat, 8 Aug 2020 18:32:32 +0900 Subject: [PATCH 05/26] =?UTF-8?q?OGPResolver:=20=E3=83=AA=E3=83=80?= =?UTF-8?q?=E3=82=A4=E3=83=AC=E3=82=AF=E3=83=88=E6=99=82=E3=81=ABCookie?= =?UTF-8?q?=E3=82=92=E7=B6=AD=E6=8C=81=E3=81=95=E3=81=9B=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/MetadataResolver/OGPResolver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/MetadataResolver/OGPResolver.php b/app/MetadataResolver/OGPResolver.php index a1cf603..9bd0bb3 100644 --- a/app/MetadataResolver/OGPResolver.php +++ b/app/MetadataResolver/OGPResolver.php @@ -3,6 +3,8 @@ namespace App\MetadataResolver; use GuzzleHttp\Client; +use GuzzleHttp\Cookie\CookieJar; +use GuzzleHttp\RequestOptions; class OGPResolver implements Resolver, Parser { @@ -18,7 +20,7 @@ class OGPResolver implements Resolver, Parser public function resolve(string $url): Metadata { - return $this->parse($this->client->get($url)->getBody()); + return $this->parse($this->client->get($url, [RequestOptions::COOKIES => new CookieJar()])->getBody()); } public function parse(string $html): Metadata From b99930e1452fa26eb39f0b70cce5d518fad38cf5 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 10 Aug 2020 00:10:06 +0900 Subject: [PATCH 06/26] =?UTF-8?q?EjaculationController=E3=81=A7=E3=83=88?= =?UTF-8?q?=E3=83=A9=E3=83=B3=E3=82=B6=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E3=81=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/EjaculationController.php | 90 ++++++++++--------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index bd8d70c..8446c96 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -9,6 +9,7 @@ use App\User; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\DB; use Validator; class EjaculationController extends Controller @@ -52,29 +53,33 @@ class EjaculationController extends Controller return redirect()->route('checkin')->withErrors($validator)->withInput(); } - $ejaculation = Ejaculation::create([ - 'user_id' => Auth::id(), - 'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']), - 'note' => $inputs['note'] ?? '', - 'link' => $inputs['link'] ?? '', - 'source' => Ejaculation::SOURCE_WEB, - 'is_private' => $request->has('is_private') ?? false, - 'is_too_sensitive' => $request->has('is_too_sensitive') ?? false - ]); + $ejaculation = DB::transaction(function () use ($request, $inputs) { + $ejaculation = Ejaculation::create([ + 'user_id' => Auth::id(), + 'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']), + 'note' => $inputs['note'] ?? '', + 'link' => $inputs['link'] ?? '', + 'source' => Ejaculation::SOURCE_WEB, + 'is_private' => $request->has('is_private') ?? false, + 'is_too_sensitive' => $request->has('is_too_sensitive') ?? false + ]); - $tagIds = []; - if (!empty($inputs['tags'])) { - $tags = explode(' ', $inputs['tags']); - foreach ($tags as $tag) { - if ($tag === '') { - continue; + $tagIds = []; + if (!empty($inputs['tags'])) { + $tags = explode(' ', $inputs['tags']); + foreach ($tags as $tag) { + if ($tag === '') { + continue; + } + + $tag = Tag::firstOrCreate(['name' => $tag]); + $tagIds[] = $tag->id; } - - $tag = Tag::firstOrCreate(['name' => $tag]); - $tagIds[] = $tag->id; } - } - $ejaculation->tags()->sync($tagIds); + $ejaculation->tags()->sync($tagIds); + + return $ejaculation; + }); if (!empty($ejaculation->link)) { event(new LinkDiscovered($ejaculation->link)); @@ -144,27 +149,29 @@ class EjaculationController extends Controller return redirect()->route('checkin.edit', ['id' => $id])->withErrors($validator)->withInput(); } - $ejaculation->fill([ - 'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']), - 'note' => $inputs['note'] ?? '', - 'link' => $inputs['link'] ?? '', - 'is_private' => $request->has('is_private') ?? false, - 'is_too_sensitive' => $request->has('is_too_sensitive') ?? false - ])->save(); + DB::transaction(function () use ($ejaculation, $request, $inputs) { + $ejaculation->fill([ + 'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']), + 'note' => $inputs['note'] ?? '', + 'link' => $inputs['link'] ?? '', + 'is_private' => $request->has('is_private') ?? false, + 'is_too_sensitive' => $request->has('is_too_sensitive') ?? false + ])->save(); - $tagIds = []; - if (!empty($inputs['tags'])) { - $tags = explode(' ', $inputs['tags']); - foreach ($tags as $tag) { - if ($tag === '') { - continue; + $tagIds = []; + if (!empty($inputs['tags'])) { + $tags = explode(' ', $inputs['tags']); + foreach ($tags as $tag) { + if ($tag === '') { + continue; + } + + $tag = Tag::firstOrCreate(['name' => $tag]); + $tagIds[] = $tag->id; } - - $tag = Tag::firstOrCreate(['name' => $tag]); - $tagIds[] = $tag->id; } - } - $ejaculation->tags()->sync($tagIds); + $ejaculation->tags()->sync($tagIds); + }); if (!empty($ejaculation->link)) { event(new LinkDiscovered($ejaculation->link)); @@ -180,8 +187,11 @@ class EjaculationController extends Controller $this->authorize('edit', $ejaculation); $user = User::findOrFail($ejaculation->user_id); - $ejaculation->tags()->detach(); - $ejaculation->delete(); + + DB::transaction(function () use ($ejaculation) { + $ejaculation->tags()->detach(); + $ejaculation->delete(); + }); return redirect()->route('user.profile', ['name' => $user->name])->with('status', '削除しました。'); } From 196819270b79c1c8fc0d5db67711195271f13a45 Mon Sep 17 00:00:00 2001 From: shibafu Date: Sun, 17 May 2020 17:11:35 +0900 Subject: [PATCH 07/26] wip --- package.json | 8 ++ resources/assets/js/checkin.ts | 8 ++ resources/assets/js/components/TagInput.scss | 10 +++ resources/assets/js/components/TagInput2.tsx | 76 ++++++++++++++++++ resources/views/ejaculation/checkin.blade.php | 1 + tsconfig.json | 5 +- yarn.lock | 78 ++++++++++++++++++- 7 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 resources/assets/js/components/TagInput.scss create mode 100644 resources/assets/js/components/TagInput2.tsx diff --git a/package.json b/package.json index 63acde8..c8b40b4 100644 --- a/package.json +++ b/package.json @@ -73,5 +73,13 @@ "composer fix", "git add" ] + }, + "dependencies": { + "@types/classnames": "^2.2.10", + "@types/react": "^16.9.35", + "@types/react-dom": "^16.9.8", + "classnames": "^2.2.6", + "react": "^16.13.1", + "react-dom": "^16.13.1" } } diff --git a/resources/assets/js/checkin.ts b/resources/assets/js/checkin.ts index 4a1bf50..45bbd2a 100644 --- a/resources/assets/js/checkin.ts +++ b/resources/assets/js/checkin.ts @@ -2,6 +2,9 @@ import Vue from 'vue'; import TagInput from './components/TagInput.vue'; import MetadataPreview from './components/MetadataPreview.vue'; import { fetchGet, ResponseError } from './fetch'; +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import TagInput2 from './components/TagInput2'; export const bus = new Vue({ name: 'EventBus' }); @@ -66,3 +69,8 @@ new Vue({ }, }, }); + +ReactDOM.render( + React.createElement(TagInput2, { id: 'tagInput2', name: 'tags2', value: '', isInvalid: false }), + document.querySelector('#tagInput2') +); diff --git a/resources/assets/js/components/TagInput.scss b/resources/assets/js/components/TagInput.scss new file mode 100644 index 0000000..b2f85af --- /dev/null +++ b/resources/assets/js/components/TagInput.scss @@ -0,0 +1,10 @@ +:local { + .tag-item { + cursor: pointer; + } + + .tag-input { + border: 0; + outline: 0; + } +} diff --git a/resources/assets/js/components/TagInput2.tsx b/resources/assets/js/components/TagInput2.tsx new file mode 100644 index 0000000..1d6c124 --- /dev/null +++ b/resources/assets/js/components/TagInput2.tsx @@ -0,0 +1,76 @@ +import * as React from 'react'; +import { useState, useRef } from 'react'; +import * as classNames from 'classnames'; +const styles = require('./TagInput.scss'); // TODO: 読めてない + +type TagInputProps = { + id: string; + name: string; + value: string; + isInvalid: boolean; +}; + +const TagInput: React.FC = ({ id, name, value, isInvalid }) => { + const [tags, setTags] = useState(value.trim() !== '' ? value.trim().split(' ') : []); + const [buffer, setBuffer] = useState(''); + const containerClass = classNames('form-control', 'h-auto', { 'is-invalid': isInvalid }); + const inputRef = useRef(null); + const removeTag = (index: number) => { + setTags(tags.filter((v, i) => i != index)); + }; + const onKeyDown = (event: React.KeyboardEvent) => { + if (buffer.trim() !== '') { + switch (event.key) { + case 'Tab': + case 'Enter': + case ' ': + if ((event as any).isComposing !== true) { + setTags(tags.concat(buffer.trim())); + setBuffer(''); + } + event.preventDefault(); + break; + case 'Unidentified': + // 実際にテキストボックスに入力されている文字を見に行く (フォールバック処理) + const nativeEvent = event.nativeEvent; + if (nativeEvent.srcElement && (nativeEvent.srcElement as HTMLInputElement).value.slice(-1) == ' ') { + setTags(tags.concat(buffer.trim())); + setBuffer(''); + event.preventDefault(); + } + break; + } + } else if (event.key === 'Enter') { + // 誤爆防止 + event.preventDefault(); + } + }; + + return ( +
inputRef.current?.focus()}> + +
    + {tags.map((tag, i) => ( +
  • removeTag(i)} + > + {tag} | x +
  • + ))} +
+ setBuffer(e.target.value)} + onKeyDown={onKeyDown} + /> +
+ ); +}; + +export default TagInput; diff --git a/resources/views/ejaculation/checkin.blade.php b/resources/views/ejaculation/checkin.blade.php index 611ae85..1ae063f 100644 --- a/resources/views/ejaculation/checkin.blade.php +++ b/resources/views/ejaculation/checkin.blade.php @@ -40,6 +40,7 @@
+
Tab, Enter, 半角スペースのいずれかで入力確定します。 diff --git a/tsconfig.json b/tsconfig.json index d2d1b2c..4801f69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,9 +5,10 @@ "module": "es2015", "moduleResolution": "node", "strict": true, - "experimentalDecorators": true + "experimentalDecorators": true, + "jsx": "react" }, "include": [ "resources/assets/js/**/*" ] -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index e287e43..d26d05d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -772,6 +772,11 @@ dependencies: moment "^2.10.2" +"@types/classnames@^2.2.10": + version "2.2.10" + resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.10.tgz#cc658ca319b6355399efc1f5b9e818f1a24bf999" + integrity sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ== + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -828,6 +833,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.0.tgz#4e498dbf355795a611a87ae5ef811a8660d42662" integrity sha512-Onhn+z72D2O2Pb2ql2xukJ55rglumsVo1H6Fmyi8mlU9SvKdBk/pUSUAiBY/d9bAOF7VVWajX3sths/+g6ZiAQ== +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" @@ -838,6 +848,21 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a" integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ== +"@types/react-dom@^16.9.8": + version "16.9.8" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" + integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^16.9.35": + version "16.9.46" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.46.tgz#f0326cd7adceda74148baa9bff6e918632f5069e" + integrity sha512-dbHzO3aAq1lB3jRQuNpuZ/mnu+CdD3H0WVaaBQA8LTT3S33xhVBUj232T8M3tAhSWJs/D/UqORYUlJNl/8VQZg== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/sizzle@*": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" @@ -1937,6 +1962,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + clean-css@4.2.x, clean-css@^4.1.3: version "4.2.2" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.2.tgz#8519abda724b3e759bc79d196369906925d81a3f" @@ -2489,6 +2519,11 @@ csso@^4.0.2: dependencies: css-tree "1.0.0-alpha.37" +csstype@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7" + integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -4988,7 +5023,7 @@ longest-streak@^2.0.1: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== -loose-envify@^1.0.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -6499,6 +6534,15 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +prop-types@^15.6.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + property-expr@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" @@ -6639,6 +6683,30 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +react-dom@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" + integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.19.1" + +react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" + integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" @@ -7091,6 +7159,14 @@ sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + schema-utils@^0.4.5: version "0.4.7" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" From ae79f0225e636d2de167ac1d9f64524562d8f099 Mon Sep 17 00:00:00 2001 From: shibafu Date: Wed, 12 Aug 2020 23:05:38 +0900 Subject: [PATCH 08/26] =?UTF-8?q?CSS=E3=82=92=E3=81=A9=E3=81=86=E3=81=AB?= =?UTF-8?q?=E3=81=8B=E3=81=99=E3=82=8B=E3=81=AE=E3=82=92=E8=AB=A6=E3=82=81?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/components/TagInput.scss | 10 ---------- resources/assets/js/components/TagInput2.tsx | 5 ++--- resources/assets/sass/app.scss | 1 + resources/assets/sass/components/_tag-input.scss | 8 ++++++++ 4 files changed, 11 insertions(+), 13 deletions(-) delete mode 100644 resources/assets/js/components/TagInput.scss create mode 100644 resources/assets/sass/components/_tag-input.scss diff --git a/resources/assets/js/components/TagInput.scss b/resources/assets/js/components/TagInput.scss deleted file mode 100644 index b2f85af..0000000 --- a/resources/assets/js/components/TagInput.scss +++ /dev/null @@ -1,10 +0,0 @@ -:local { - .tag-item { - cursor: pointer; - } - - .tag-input { - border: 0; - outline: 0; - } -} diff --git a/resources/assets/js/components/TagInput2.tsx b/resources/assets/js/components/TagInput2.tsx index 1d6c124..6576081 100644 --- a/resources/assets/js/components/TagInput2.tsx +++ b/resources/assets/js/components/TagInput2.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { useState, useRef } from 'react'; import * as classNames from 'classnames'; -const styles = require('./TagInput.scss'); // TODO: 読めてない type TagInputProps = { id: string; @@ -53,7 +52,7 @@ const TagInput: React.FC = ({ id, name, value, isInvalid }) => { {tags.map((tag, i) => (
  • removeTag(i)} > {tag} | x @@ -64,7 +63,7 @@ const TagInput: React.FC = ({ id, name, value, isInvalid }) => { id={id} ref={inputRef} type="text" - className={styles.tagInput} + className="tis-tag-input-field" value={buffer} onChange={(e) => setBuffer(e.target.value)} onKeyDown={onKeyDown} diff --git a/resources/assets/sass/app.scss b/resources/assets/sass/app.scss index 6f38126..54e7a86 100644 --- a/resources/assets/sass/app.scss +++ b/resources/assets/sass/app.scss @@ -13,6 +13,7 @@ $primary: #e53fb1; // Components @import "components/ejaculation"; @import "components/link-card"; +@import "components/tag-input"; // Tag @import "tag/index"; diff --git a/resources/assets/sass/components/_tag-input.scss b/resources/assets/sass/components/_tag-input.scss new file mode 100644 index 0000000..c453934 --- /dev/null +++ b/resources/assets/sass/components/_tag-input.scss @@ -0,0 +1,8 @@ +.tis-tag-input-item { + cursor: pointer; +} + +.tis-tag-input-field { + border: 0; + outline: 0; +} From 969ddb94a908d6a32fb7576df8f26e709d4477fa Mon Sep 17 00:00:00 2001 From: shibafu Date: Wed, 12 Aug 2020 23:06:17 +0900 Subject: [PATCH 09/26] =?UTF-8?q?=E3=82=BF=E3=82=B0=E3=81=AE=E7=A2=BA?= =?UTF-8?q?=E5=AE=9A=E6=99=82=E3=81=AB=E7=A9=BA=E7=99=BD=E6=96=87=E5=AD=97?= =?UTF-8?q?=E3=82=92=E7=BD=AE=E6=8F=9B=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit from 978eccd643cd3fa628ce7347b7e375ecabcfe9e1 --- resources/assets/js/components/TagInput2.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/assets/js/components/TagInput2.tsx b/resources/assets/js/components/TagInput2.tsx index 6576081..b4a83a3 100644 --- a/resources/assets/js/components/TagInput2.tsx +++ b/resources/assets/js/components/TagInput2.tsx @@ -24,20 +24,21 @@ const TagInput: React.FC = ({ id, name, value, isInvalid }) => { case 'Enter': case ' ': if ((event as any).isComposing !== true) { - setTags(tags.concat(buffer.trim())); + setTags(tags.concat(buffer.trim().replace(/\s+/g, '_'))); setBuffer(''); } event.preventDefault(); break; - case 'Unidentified': + case 'Unidentified': { // 実際にテキストボックスに入力されている文字を見に行く (フォールバック処理) const nativeEvent = event.nativeEvent; if (nativeEvent.srcElement && (nativeEvent.srcElement as HTMLInputElement).value.slice(-1) == ' ') { - setTags(tags.concat(buffer.trim())); + setTags(tags.concat(buffer.trim().replace(/\s+/g, '_'))); setBuffer(''); event.preventDefault(); } break; + } } } else if (event.key === 'Enter') { // 誤爆防止 From 064cfff211ec718d62f5371d3b8f2afd72a2b9ad Mon Sep 17 00:00:00 2001 From: shibafu Date: Thu, 13 Aug 2020 00:38:26 +0900 Subject: [PATCH 10/26] wip --- .../assets/js/{checkin.ts => checkin.tsx} | 13 ++- .../assets/js/components/MetadataPreview2.tsx | 110 ++++++++++++++++++ .../sass/components/_metadata-preview.scss | 28 +++++ resources/views/ejaculation/checkin.blade.php | 1 + webpack.mix.js | 2 +- 5 files changed, 152 insertions(+), 2 deletions(-) rename resources/assets/js/{checkin.ts => checkin.tsx} (89%) create mode 100644 resources/assets/js/components/MetadataPreview2.tsx create mode 100644 resources/assets/sass/components/_metadata-preview.scss diff --git a/resources/assets/js/checkin.ts b/resources/assets/js/checkin.tsx similarity index 89% rename from resources/assets/js/checkin.ts rename to resources/assets/js/checkin.tsx index 45bbd2a..5cbe176 100644 --- a/resources/assets/js/checkin.ts +++ b/resources/assets/js/checkin.tsx @@ -15,6 +15,17 @@ export enum MetadataLoadState { Failed, } +export type Metadata = { + url: string; + title: string; + description: string; + image: string; + expires_at: string | null; + tags: { + name: string; + }[]; +}; + new Vue({ el: '#app', data: { @@ -71,6 +82,6 @@ new Vue({ }); ReactDOM.render( - React.createElement(TagInput2, { id: 'tagInput2', name: 'tags2', value: '', isInvalid: false }), + , document.querySelector('#tagInput2') ); diff --git a/resources/assets/js/components/MetadataPreview2.tsx b/resources/assets/js/components/MetadataPreview2.tsx new file mode 100644 index 0000000..e2dcdac --- /dev/null +++ b/resources/assets/js/components/MetadataPreview2.tsx @@ -0,0 +1,110 @@ +import * as React from 'react'; +import { Metadata, MetadataLoadState } from '../checkin'; +import * as classNames from 'classnames'; + +type Suggestion = { + name: string; + used: boolean; +}; + +type MetadataPreviewProps = { + state: MetadataLoadState; + metadata: Metadata | null; + tags: string[]; + handleAddTag: (tag: string) => void; +}; + +const MetadataLoading = () => ( +
    +
    +
    +
    + オカズの情報を読み込んでいます… +
    +
    +
    +
    +); + +const MetadataLoadFailed = () => ( +
    +
    +
    +
    + オカズの情報を読み込めませんでした +
    +
    +
    +
    +); + +export const MetadataPreview: React.FC = ({ state, metadata, tags, handleAddTag }) => { + if (state === MetadataLoadState.Inactive) { + return null; + } + const hasImage = metadata !== null && metadata.image !== ''; + const descClasses = classNames({ + 'col-8': hasImage, + 'col-12': !hasImage, + }); + const tagClasses = (s: Suggestion) => + classNames({ + 'list-inline-item': true, + badge: true, + 'badge-primary': !s.used, + 'badge-secondary': s.used, + 'metadata-tag-item': true, + }); + const suggestions = + metadata?.tags.map((t) => ({ + name: t.name, + used: tags.indexOf(t.name) !== -1, + })) ?? []; + + return ( +
    +
    +
    + {state === MetadataLoadState.Loading ? ( + + ) : state === MetadataLoadState.Success ? ( +
    +
    + Thumbnail +
    +
    +
    +
    {metadata?.title}
    + {suggestions.length > 0 && ( + <> +

    + タグ候補 +
    + + (クリックするとタグ入力欄にコピーできます) + +

    +
      + {suggestions.map((tag) => ( +
    • handleAddTag(tag.name)} + > + {tag.name} +
    • + ))} +
    + + )} +
    +
    +
    + ) : ( + + )} +
    +
    +
    + ); +}; diff --git a/resources/assets/sass/components/_metadata-preview.scss b/resources/assets/sass/components/_metadata-preview.scss new file mode 100644 index 0000000..4ce8e79 --- /dev/null +++ b/resources/assets/sass/components/_metadata-preview.scss @@ -0,0 +1,28 @@ +.tis-metadata-preview { + &-link-card { + $height: 150px; + overflow: hidden; + font-size: small; + + .row > div:first-child { + display: flex; + + &:not([display='none']) { + min-height: $height; + + img { + position: absolute; + } + } + } + + .card-text { + white-space: pre-line; + } + } + + &-tag-item { + cursor: pointer; + user-select: none; + } +} diff --git a/resources/views/ejaculation/checkin.blade.php b/resources/views/ejaculation/checkin.blade.php index 1ae063f..9ffb8ca 100644 --- a/resources/views/ejaculation/checkin.blade.php +++ b/resources/views/ejaculation/checkin.blade.php @@ -65,6 +65,7 @@
  • +
    diff --git a/webpack.mix.js b/webpack.mix.js index 16ed4e0..dd4c5e1 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -20,7 +20,7 @@ mix.ts('resources/assets/js/app.ts', 'public/js') .ts('resources/assets/js/setting/privacy.ts', 'public/js/setting') .ts('resources/assets/js/setting/import.ts', 'public/js/setting') .ts('resources/assets/js/setting/deactivate.ts', 'public/js/setting') - .ts('resources/assets/js/checkin.ts', 'public/js') + .ts('resources/assets/js/checkin.tsx', 'public/js') .sass('resources/assets/sass/app.scss', 'public/css') .autoload({ jquery: ['$', 'jQuery', 'window.jQuery'], From e961a2d4b40010a8f0c05904ebf8ba344743c591 Mon Sep 17 00:00:00 2001 From: shibafu Date: Thu, 13 Aug 2020 01:57:09 +0900 Subject: [PATCH 11/26] =?UTF-8?q?export=20default=E3=81=AF=E5=BE=AE?= =?UTF-8?q?=E5=A6=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/checkin.tsx | 2 +- resources/assets/js/components/TagInput2.tsx | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/assets/js/checkin.tsx b/resources/assets/js/checkin.tsx index 5cbe176..29d8b7e 100644 --- a/resources/assets/js/checkin.tsx +++ b/resources/assets/js/checkin.tsx @@ -4,7 +4,7 @@ import MetadataPreview from './components/MetadataPreview.vue'; import { fetchGet, ResponseError } from './fetch'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import TagInput2 from './components/TagInput2'; +import { TagInput as TagInput2 } from './components/TagInput2'; export const bus = new Vue({ name: 'EventBus' }); diff --git a/resources/assets/js/components/TagInput2.tsx b/resources/assets/js/components/TagInput2.tsx index b4a83a3..11c654f 100644 --- a/resources/assets/js/components/TagInput2.tsx +++ b/resources/assets/js/components/TagInput2.tsx @@ -9,7 +9,7 @@ type TagInputProps = { isInvalid: boolean; }; -const TagInput: React.FC = ({ id, name, value, isInvalid }) => { +export const TagInput: React.FC = ({ id, name, value, isInvalid }) => { const [tags, setTags] = useState(value.trim() !== '' ? value.trim().split(' ') : []); const [buffer, setBuffer] = useState(''); const containerClass = classNames('form-control', 'h-auto', { 'is-invalid': isInvalid }); @@ -72,5 +72,3 @@ const TagInput: React.FC = ({ id, name, value, isInvalid }) => {
    ); }; - -export default TagInput; From 04d546b1f02374a16afb2f4d55ac46cb4154d75e Mon Sep 17 00:00:00 2001 From: shibafu Date: Sun, 16 Aug 2020 14:38:35 +0900 Subject: [PATCH 12/26] =?UTF-8?q?Twitter=E3=81=AE=E3=82=B5=E3=83=96?= =?UTF-8?q?=E3=83=89=E3=83=A1=E3=82=A4=E3=83=B3=E5=AF=BE=E5=BF=9C=E7=94=A8?= =?UTF-8?q?Resolver=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/MetadataResolver/MetadataResolver.php | 1 + app/MetadataResolver/TwitterResolver.php | 33 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 app/MetadataResolver/TwitterResolver.php diff --git a/app/MetadataResolver/MetadataResolver.php b/app/MetadataResolver/MetadataResolver.php index 8470275..6ab663d 100644 --- a/app/MetadataResolver/MetadataResolver.php +++ b/app/MetadataResolver/MetadataResolver.php @@ -34,6 +34,7 @@ class MetadataResolver implements Resolver '~www\.xtube\.com/video-watch/.*-\d+$~'=> XtubeResolver::class, '~ss\.kb10uy\.org/posts/\d+$~' => Kb10uyShortStoryServerResolver::class, '~www\.hentai-foundry\.com/pictures/user/.+/\d+/.+~'=> HentaiFoundryResolver::class, + '~(www\.)?((mobile|m)\.)?twitter\.com/(#!/)?[0-9a-zA-Z_]{1,15}/status(es)?/([0-9]+)/?(\\?.+)?$~' => TwitterResolver::class, ]; public $mimeTypes = [ diff --git a/app/MetadataResolver/TwitterResolver.php b/app/MetadataResolver/TwitterResolver.php new file mode 100644 index 0000000..adfb5d3 --- /dev/null +++ b/app/MetadataResolver/TwitterResolver.php @@ -0,0 +1,33 @@ +client = $client; + $this->ogpResolver = $ogpResolver; + } + + public function resolve(string $url): Metadata + { + $url = preg_replace('/(www\.)?(mobile|m)\.twitter\.com/u', 'twitter.com', $url); + + $res = $this->client->get($url); + $html = (string) $res->getBody(); + + return $this->ogpResolver->parse($html); + } +} From 6968ca7333a873bcb055ae1e038a7d6473523dde Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 16:00:04 +0900 Subject: [PATCH 13/26] =?UTF-8?q?=E3=82=84=E3=82=8B=E3=81=A0=E3=81=91.tsx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/EjaculationController.php | 54 +++-- resources/assets/js/checkin.tsx | 87 +------- .../assets/js/components/CheckinForm.tsx | 187 ++++++++++++++++++ ...tadataPreview2.tsx => MetadataPreview.tsx} | 66 ++++++- .../assets/js/components/MetadataPreview.vue | 156 --------------- .../{TagInput2.tsx => TagInput.tsx} | 36 ++-- resources/assets/js/components/TagInput.vue | 96 --------- resources/assets/sass/app.scss | 1 + .../sass/components/_metadata-preview.scss | 6 +- .../assets/sass/components/_tag-input.scss | 15 +- resources/views/ejaculation/checkin.blade.php | 93 +-------- resources/views/ejaculation/edit.blade.php | 91 +-------- 12 files changed, 332 insertions(+), 556 deletions(-) create mode 100644 resources/assets/js/components/CheckinForm.tsx rename resources/assets/js/components/{MetadataPreview2.tsx => MetadataPreview.tsx} (70%) delete mode 100644 resources/assets/js/components/MetadataPreview.vue rename resources/assets/js/components/{TagInput2.tsx => TagInput.tsx} (69%) delete mode 100644 resources/assets/js/components/TagInput.vue diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index 8446c96..e59aece 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -16,17 +16,26 @@ class EjaculationController extends Controller { public function create(Request $request) { - $defaults = [ - 'date' => $request->input('date', date('Y/m/d')), - 'time' => $request->input('time', date('H:i')), - 'link' => $request->input('link', ''), - 'tags' => $request->input('tags', ''), - 'note' => $request->input('note', ''), - 'is_private' => $request->input('is_private', 0) == 1, - 'is_too_sensitive' => $request->input('is_too_sensitive', 0) == 1 + $tags = old('tags') ?? $request->input('tags', ''); + if (!empty($tags)) { + $tags = explode(' ', $tags); + } + + $errors = $request->session()->get('errors'); + $initialState = [ + 'fields' => [ + 'date' => old('date') ?? $request->input('date', date('Y/m/d')), + 'time' => old('time') ?? $request->input('time', date('H:i')), + 'link' => old('link') ?? $request->input('link', ''), + 'tags' => $tags, + 'note' => old('note') ?? $request->input('note', ''), + 'is_private' => old('is_private') ?? $request->input('is_private', 0) == 1, + 'is_too_sensitive' => old('is_too_sensitive') ?? $request->input('is_too_sensitive', 0) == 1 + ], + 'errors' => isset($errors) ? $errors->getMessages() : null ]; - return view('ejaculation.checkin')->with('defaults', $defaults); + return view('ejaculation.checkin')->with('initialState', $initialState); } public function store(Request $request) @@ -112,13 +121,36 @@ class EjaculationController extends Controller return view('ejaculation.show')->with(compact('user', 'ejaculation', 'ejaculatedSpan')); } - public function edit($id) + public function edit(Request $request, $id) { $ejaculation = Ejaculation::findOrFail($id); $this->authorize('edit', $ejaculation); - return view('ejaculation.edit')->with(compact('ejaculation')); + if (old('tags') === null) { + $tags = $ejaculation->tags->pluck('name'); + } else { + $tags = old('tags'); + if (!empty($tags)) { + $tags = explode(' ', $tags); + } + } + + $errors = $request->session()->get('errors'); + $initialState = [ + 'fields' => [ + 'date' => old('date') ?? $ejaculation->ejaculated_date->format('Y/m/d'), + 'time' => old('time') ?? $ejaculation->ejaculated_date->format('H:i'), + 'link' => old('link') ?? $ejaculation->link, + 'tags' => $tags, + 'note' => old('note') ?? $ejaculation->note, + 'is_private' => is_bool(old('is_private')) ? old('is_private') : $ejaculation->note, + 'is_too_sensitive' => is_bool(old('is_too_sensitive')) ? old('is_too_sensitive') : $ejaculation->is_too_sensitive + ], + 'errors' => isset($errors) ? $errors->getMessages() : null + ]; + + return view('ejaculation.edit')->with(compact('ejaculation', 'initialState')); } public function update(Request $request, $id) diff --git a/resources/assets/js/checkin.tsx b/resources/assets/js/checkin.tsx index 29d8b7e..23ce902 100644 --- a/resources/assets/js/checkin.tsx +++ b/resources/assets/js/checkin.tsx @@ -1,87 +1,6 @@ -import Vue from 'vue'; -import TagInput from './components/TagInput.vue'; -import MetadataPreview from './components/MetadataPreview.vue'; -import { fetchGet, ResponseError } from './fetch'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import { TagInput as TagInput2 } from './components/TagInput2'; +import { CheckinForm } from './components/CheckinForm'; -export const bus = new Vue({ name: 'EventBus' }); - -export enum MetadataLoadState { - Inactive, - Loading, - Success, - Failed, -} - -export type Metadata = { - url: string; - title: string; - description: string; - image: string; - expires_at: string | null; - tags: { - name: string; - }[]; -}; - -new Vue({ - el: '#app', - data: { - metadata: null, - metadataLoadState: MetadataLoadState.Inactive, - }, - components: { - TagInput, - MetadataPreview, - }, - mounted() { - // オカズリンクにURLがセットされている場合は、すぐにメタデータを取得する - const linkInput = this.$el.querySelector('#link'); - if (linkInput && /^https?:\/\//.test(linkInput.value)) { - this.fetchMetadata(linkInput.value); - } - }, - methods: { - // オカズリンクの変更時 - onChangeLink(event: Event) { - if (event.target instanceof HTMLInputElement) { - const url = event.target.value; - - if (url.trim() === '' || !/^https?:\/\//.test(url)) { - this.metadata = null; - this.metadataLoadState = MetadataLoadState.Inactive; - return; - } - - this.fetchMetadata(url); - } - }, - // メタデータの取得 - fetchMetadata(url: string) { - this.metadataLoadState = MetadataLoadState.Loading; - - fetchGet('/api/checkin/card', { url }) - .then((response) => { - if (!response.ok) { - throw new ResponseError(response); - } - return response.json(); - }) - .then((data) => { - this.metadata = data; - this.metadataLoadState = MetadataLoadState.Success; - }) - .catch(() => { - this.metadata = null; - this.metadataLoadState = MetadataLoadState.Failed; - }); - }, - }, -}); - -ReactDOM.render( - , - document.querySelector('#tagInput2') -); +const initialState = JSON.parse(document.getElementById('initialState')?.textContent as string); +ReactDOM.render(, document.getElementById('checkinForm')); diff --git a/resources/assets/js/components/CheckinForm.tsx b/resources/assets/js/components/CheckinForm.tsx new file mode 100644 index 0000000..5931869 --- /dev/null +++ b/resources/assets/js/components/CheckinForm.tsx @@ -0,0 +1,187 @@ +import * as React from 'react'; +import { useState } from 'react'; +import * as classNames from 'classnames'; +import { TagInput } from './TagInput'; +import { MetadataPreview } from './MetadataPreview'; + +type CheckboxProps = { + id: string; + name: string; + className?: string; + checked?: boolean; + onChange?: (newValue: boolean) => void; +}; + +const Checkbox: React.FC = ({ id, name, className, checked, onChange, children }) => ( +
    + onChange && onChange(e.target.checked)} + /> + +
    +); + +type FieldErrorProps = { + errors?: string[]; +}; + +const FieldError: React.FC = ({ errors }) => + (errors && errors.length > 0 &&
    {errors[0]}
    ) || null; + +const StandaloneFieldError: React.FC = ({ errors }) => + (errors && errors.length > 0 && ( +
    + {errors[0]} +
    + )) || + null; + +export type CheckinFormProps = { + initialState: any; +}; + +export const CheckinForm: React.FC = ({ initialState }) => { + const [date, setDate] = useState(initialState.fields.date || ''); + const [time, setTime] = useState(initialState.fields.time || ''); + const [tags, setTags] = useState(initialState.fields.tags || []); + const [link, setLink] = useState(initialState.fields.link || ''); + const [linkForPreview, setLinkForPreview] = useState(link); + const [note, setNote] = useState(initialState.fields.note || ''); + const [isPrivate, setPrivate] = useState(!!initialState.fields.is_private); + const [isTooSensitive, setTooSensitive] = useState(!!initialState.fields.is_too_sensitive); + + return ( + <> +
    +
    + + setDate(e.target.value)} + /> + +
    +
    + + setTime(e.target.value)} + /> + +
    + +
    +
    +
    + + setTags(v)} + /> + Tab, Enter, 半角スペースのいずれかで入力確定します。 + +
    +
    +
    +
    + + setLink(e.target.value)} + onBlur={() => setLinkForPreview(link)} + /> + オカズのURLを貼り付けて登録することができます。 + +
    +
    + setTags(tags.concat(v))} /> +
    +
    + + - - 最大 500 文字 - - @if ($errors->has('note')) -
    {{ $errors->first('note') }}
    - @endif -
    -
    -
    -

    オプション

    -
    -
    - - -
    -
    - - -
    -
    -
    - -
    - +
    +
    しばらくお待ちください…

    Tips: ブックマークレットや共有機能で、簡単にチェックインできます! 使い方はこちら

    @@ -107,5 +21,6 @@ @endsection @push('script') + @endpush diff --git a/resources/views/ejaculation/edit.blade.php b/resources/views/ejaculation/edit.blade.php index ffdbd45..33353ad 100644 --- a/resources/views/ejaculation/edit.blade.php +++ b/resources/views/ejaculation/edit.blade.php @@ -3,7 +3,7 @@ @section('title', 'チェックインの修正') @section('content') -
    +

    チェックインの修正


    @@ -11,92 +11,8 @@
    {{ method_field('PUT') }} {{ csrf_field() }} - -
    -
    - - - - @if ($errors->has('date')) -
    {{ $errors->first('date') }}
    - @endif -
    -
    - - - - @if ($errors->has('time')) -
    {{ $errors->first('time') }}
    - @endif -
    - @if ($errors->has('datetime')) -
    - {{ $errors->first('datetime') }} -
    - @endif -
    -
    -
    - - - - Tab, Enter, 半角スペースのいずれかで入力確定します。 - - - @if ($errors->has('tags')) -
    {{ $errors->first('tags') }}
    - @endif -
    -
    -
    -
    - - - - オカズのURLを貼り付けて登録することができます。 - - @if ($errors->has('link')) -
    {{ $errors->first('link') }}
    - @endif -
    -
    - -
    -
    - - - - 最大 500 文字 - - @if ($errors->has('note')) -
    {{ $errors->first('note') }}
    - @endif -
    -
    -
    -

    オプション

    -
    -
    - is_private) ? 'checked' : '' }}> - -
    -
    - is_too_sensitive) ? 'checked' : '' }}> - -
    -
    -
    - -
    - +
    +
    しばらくお待ちください…
    @@ -105,5 +21,6 @@ @endsection @push('script') + @endpush From f37a9c79f42e7d862342da159105a341f3e9c058 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 16:02:39 +0900 Subject: [PATCH 14/26] update package.json --- package.json | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index c8b40b4..4c83391 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,18 @@ "@types/bootstrap": "^4.5.0", "@types/cal-heatmap": "^3.3.10", "@types/chart.js": "^2.9.22", + "@types/classnames": "^2.2.10", "@types/jquery": "^3.3.38", "@types/js-cookie": "^2.2.0", "@types/qs": "^6.9.4", + "@types/react": "^16.9.35", + "@types/react-dom": "^16.9.8", "@typescript-eslint/eslint-plugin": "^3.1.0", "@typescript-eslint/parser": "^3.1.0", "bootstrap": "^4.5.0", "cal-heatmap": "^3.3.10", "chart.js": "^2.7.1", + "classnames": "^2.2.6", "cross-env": "^5.2.0", "date-fns": "^1.30.1", "eslint": "^7.6.0", @@ -40,6 +44,8 @@ "popper.js": "^1.14.7", "prettier": "^2.0.5", "qs": "^6.9.4", + "react": "^16.13.1", + "react-dom": "^16.13.1", "resolve-url-loader": "^3.1.1", "sass": "^1.26.8", "sass-loader": "^7.1.0", @@ -73,13 +79,5 @@ "composer fix", "git add" ] - }, - "dependencies": { - "@types/classnames": "^2.2.10", - "@types/react": "^16.9.35", - "@types/react-dom": "^16.9.8", - "classnames": "^2.2.6", - "react": "^16.13.1", - "react-dom": "^16.13.1" } } From 228b1cdaaada084cfe0e32e21e903a3a8e72a96d Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 16:08:35 +0900 Subject: [PATCH 15/26] =?UTF-8?q?fix=20=E3=81=84=E3=82=8D=E3=81=84?= =?UTF-8?q?=E3=82=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/checkin.tsx | 2 +- resources/assets/js/components/CheckBox.tsx | 25 +++++++++ .../assets/js/components/CheckinForm.tsx | 51 +++---------------- resources/assets/js/components/FieldError.tsx | 16 ++++++ 4 files changed, 49 insertions(+), 45 deletions(-) create mode 100644 resources/assets/js/components/CheckBox.tsx create mode 100644 resources/assets/js/components/FieldError.tsx diff --git a/resources/assets/js/checkin.tsx b/resources/assets/js/checkin.tsx index 23ce902..80b5a88 100644 --- a/resources/assets/js/checkin.tsx +++ b/resources/assets/js/checkin.tsx @@ -3,4 +3,4 @@ import * as ReactDOM from 'react-dom'; import { CheckinForm } from './components/CheckinForm'; const initialState = JSON.parse(document.getElementById('initialState')?.textContent as string); -ReactDOM.render(, document.getElementById('checkinForm')); +ReactDOM.render(, document.getElementById('checkinForm')); diff --git a/resources/assets/js/components/CheckBox.tsx b/resources/assets/js/components/CheckBox.tsx new file mode 100644 index 0000000..30a7226 --- /dev/null +++ b/resources/assets/js/components/CheckBox.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; + +type CheckboxProps = { + id: string; + name: string; + className?: string; + checked?: boolean; + onChange?: (newValue: boolean) => void; +}; + +export const CheckBox: React.FC = ({ id, name, className, checked, onChange, children }) => ( +
    + onChange && onChange(e.target.checked)} + /> + +
    +); diff --git a/resources/assets/js/components/CheckinForm.tsx b/resources/assets/js/components/CheckinForm.tsx index 5931869..442b436 100644 --- a/resources/assets/js/components/CheckinForm.tsx +++ b/resources/assets/js/components/CheckinForm.tsx @@ -1,49 +1,12 @@ import * as React from 'react'; import { useState } from 'react'; import * as classNames from 'classnames'; +import { CheckBox } from './CheckBox'; +import { FieldError, StandaloneFieldError } from './FieldError'; import { TagInput } from './TagInput'; import { MetadataPreview } from './MetadataPreview'; -type CheckboxProps = { - id: string; - name: string; - className?: string; - checked?: boolean; - onChange?: (newValue: boolean) => void; -}; - -const Checkbox: React.FC = ({ id, name, className, checked, onChange, children }) => ( -
    - onChange && onChange(e.target.checked)} - /> - -
    -); - -type FieldErrorProps = { - errors?: string[]; -}; - -const FieldError: React.FC = ({ errors }) => - (errors && errors.length > 0 &&
    {errors[0]}
    ) || null; - -const StandaloneFieldError: React.FC = ({ errors }) => - (errors && errors.length > 0 && ( -
    - {errors[0]} -
    - )) || - null; - -export type CheckinFormProps = { +type CheckinFormProps = { initialState: any; }; @@ -157,7 +120,7 @@ export const CheckinForm: React.FC = ({ initialState }) => {

    オプション

    - = ({ initialState }) => { onChange={(v) => setPrivate(v)} > このチェックインを非公開にする - - + = ({ initialState }) => { onChange={(v) => setTooSensitive(v)} > チェックイン対象のオカズをより過激なオカズとして設定する - +
    diff --git a/resources/assets/js/components/FieldError.tsx b/resources/assets/js/components/FieldError.tsx new file mode 100644 index 0000000..61ec77e --- /dev/null +++ b/resources/assets/js/components/FieldError.tsx @@ -0,0 +1,16 @@ +import * as React from 'react'; + +type FieldErrorProps = { + errors?: string[]; +}; + +export const FieldError: React.FC = ({ errors }) => + (errors && errors.length > 0 &&
    {errors[0]}
    ) || null; + +export const StandaloneFieldError: React.FC = ({ errors }) => + (errors && errors.length > 0 && ( +
    + {errors[0]} +
    + )) || + null; From 432c2bf4d598f4df8053ee2a6dc91e3840a96c94 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 16:11:31 +0900 Subject: [PATCH 16/26] rm vue --- package.json | 6 +----- yarn.lock | 30 +----------------------------- 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 4c83391..53111dd 100644 --- a/package.json +++ b/package.json @@ -52,11 +52,7 @@ "stylelint": "^9.10.1", "stylelint-config-recess-order": "^2.0.4", "ts-loader": "^6.0.1", - "typescript": "^3.4.5", - "vue": "^2.6.10", - "vue-class-component": "^7.1.0", - "vue-property-decorator": "^9.0.0", - "vue-template-compiler": "^2.6.10" + "typescript": "^3.4.5" }, "stylelint": { "extends": "stylelint-config-recess-order" diff --git a/yarn.lock b/yarn.lock index d26d05d..ebfaef2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2554,11 +2554,6 @@ date-fns@^1.27.2, date-fns@^1.30.1: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -de-indent@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" - integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= - debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3907,7 +3902,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@1.2.x, he@^1.1.0: +he@1.2.x: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -8431,11 +8426,6 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -vue-class-component@^7.1.0: - version "7.2.2" - resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-7.2.2.tgz#aecc6d28801f64c61eb04407cf3a5476da26b0c0" - integrity sha512-QjVfjRffux0rUBNtxr1hvUxDrfifDvk9q/OSdB/sKIlfxAudDF2E1YTeiEC+qOYIOOBGWkgSKQSnast6H+S38w== - vue-eslint-parser@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.1.0.tgz#9cdbcc823e656b087507a1911732b867ac101e83" @@ -8464,11 +8454,6 @@ vue-loader@^15.4.2: vue-hot-reload-api "^2.3.0" vue-style-loader "^4.1.0" -vue-property-decorator@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-9.0.0.tgz#0a5f6d47d33ca62a8876108ccfa65c2c4fb7325a" - integrity sha512-oegTNPItuHOkW0AP1MnbdNwkmyhfsUIIXvIRHpgC18tVoEo21/i6kItyeekjMs8JgZJeuHzsaTc/DZaJFH4IWQ== - 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" @@ -8477,24 +8462,11 @@ vue-style-loader@^4.1.0: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.6.10: - version "2.6.11" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080" - integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA== - dependencies: - de-indent "^1.0.2" - he "^1.1.0" - vue-template-es2015-compiler@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== -vue@^2.6.10: - version "2.6.11" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5" - integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ== - watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" From 8641f263506ed15dba8343e3dac21d250049da4b Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 16:19:14 +0900 Subject: [PATCH 17/26] fix eslint --- .eslintrc.js | 18 +++-- package.json | 4 +- yarn.lock | 194 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 172 insertions(+), 44 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 9c54f9b..4514804 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,25 +6,33 @@ module.exports = { }, extends: [ 'eslint:recommended', - 'plugin:vue/essential', + 'plugin:react/recommended', 'plugin:prettier/recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'prettier/@typescript-eslint', - 'prettier/vue', + 'prettier/react', ], - parser: 'vue-eslint-parser', + parser: '@typescript-eslint/parser', parserOptions: { ecmaVersion: 11, - parser: '@typescript-eslint/parser', + ecmaFeatures: { + jsx: true, + }, sourceType: 'module', }, - plugins: ['prettier', 'vue', '@typescript-eslint', 'jquery'], + plugins: ['prettier', 'react', '@typescript-eslint', 'jquery'], rules: { '@typescript-eslint/explicit-module-boundary-types': 0, '@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], 'jquery/no-ajax': 2, 'jquery/no-ajax-events': 2, + 'react/prop-types': 0, + }, + settings: { + react: { + version: 'detect', + }, }, }; diff --git a/package.json b/package.json index 53111dd..135f53f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", - "eslint": "eslint --ext .js,.ts,.vue resources/", + "eslint": "eslint --ext .js,.ts,.tsx resources/", "stylelint": "stylelint resources/assets/sass/**/*" }, "devDependencies": { @@ -33,7 +33,7 @@ "eslint-config-prettier": "^6.11.0", "eslint-plugin-jquery": "^1.5.1", "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-vue": "^6.2.2", + "eslint-plugin-react": "^7.20.6", "husky": "^1.3.1", "jquery": "^3.5.0", "js-cookie": "^2.2.0", diff --git a/yarn.lock b/yarn.lock index ebfaef2..0fa4fc1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1127,11 +1127,6 @@ acorn@^6.0.7, acorn@^6.2.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== - acorn@^7.3.1: version "7.4.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" @@ -1301,6 +1296,15 @@ array-flatten@^2.1.0: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== +array-includes@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + array-union@^1.0.1, array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -1318,6 +1322,15 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flatmap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" + integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -2754,6 +2767,13 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -2942,6 +2962,23 @@ error-stack-parser@^2.0.0: dependencies: stackframe "^1.1.1" +es-abstract@^1.17.0, es-abstract@^1.17.5: + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.0" + is-regex "^1.1.0" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: version "1.17.4" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" @@ -3031,14 +3068,22 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-vue@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-6.2.2.tgz#27fecd9a3a24789b0f111ecdd540a9e56198e0fe" - integrity sha512-Nhc+oVAHm0uz/PkJAWscwIT4ijTrK5fqNqz9QB1D35SbbuMG1uB6Yr5AJpvPSWg+WOw7nYNswerYh0kOk64gqQ== +eslint-plugin-react@^7.20.6: + version "7.20.6" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" + integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== dependencies: - natural-compare "^1.4.0" - semver "^5.6.0" - vue-eslint-parser "^7.0.0" + array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.4.1" + object.entries "^1.1.2" + object.fromentries "^2.0.2" + object.values "^1.1.1" + prop-types "^15.7.2" + resolve "^1.17.0" + string.prototype.matchall "^4.0.2" eslint-scope@^4.0.3: version "4.0.3" @@ -3110,15 +3155,6 @@ eslint@^7.6.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== - dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" - espree@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69" @@ -3138,7 +3174,7 @@ esprima@~3.1.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= -esquery@^1.0.1, esquery@^1.2.0: +esquery@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== @@ -4253,6 +4289,15 @@ internal-ip@^4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" +internal-slot@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" + integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== + dependencies: + es-abstract "^1.17.0-next.1" + has "^1.0.3" + side-channel "^1.0.2" + interpret@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" @@ -4376,6 +4421,11 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -4576,6 +4626,13 @@ is-regex@^1.0.4, is-regex@^1.0.5: dependencies: has "^1.0.3" +is-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -4591,6 +4648,11 @@ is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + is-supported-regexp-flag@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca" @@ -4731,6 +4793,14 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsx-ast-utils@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" + integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== + dependencies: + array-includes "^3.1.1" + object.assign "^4.1.0" + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -5638,6 +5708,25 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.entries@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" + integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + has "^1.0.3" + +object.fromentries@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + object.getownpropertydescriptors@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" @@ -5660,7 +5749,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0: +object.values@^1.1.0, object.values@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== @@ -6529,7 +6618,7 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -prop-types@^15.6.2: +prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -6821,7 +6910,7 @@ regex-parser@2.2.10: resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.10.tgz#9e66a8f73d89a107616e63b39d4deddfee912b37" integrity sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA== -regexp.prototype.flags@^1.2.0: +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== @@ -7027,6 +7116,13 @@ resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1: dependencies: path-parse "^1.0.6" +resolve@^1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -7337,6 +7433,14 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +side-channel@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -7638,6 +7742,26 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string.prototype.matchall@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" + integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" + +string.prototype.trimend@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -7654,6 +7778,14 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" +string.prototype.trimstart@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -8426,18 +8558,6 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -vue-eslint-parser@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.1.0.tgz#9cdbcc823e656b087507a1911732b867ac101e83" - integrity sha512-Kr21uPfthDc63nDl27AGQEhtt9VrZ9nkYk/NTftJ2ws9XiJwzJJCnCr3AITQ2jpRMA0XPGDECxYH8E027qMK9Q== - dependencies: - debug "^4.1.1" - eslint-scope "^5.0.0" - eslint-visitor-keys "^1.1.0" - espree "^6.2.1" - esquery "^1.0.1" - lodash "^4.17.15" - vue-hot-reload-api@^2.3.0: version "2.3.4" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" From 7d8969e5f1d9e959fb58d72acb58028fb615e0a8 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 18:17:38 +0900 Subject: [PATCH 18/26] esModuleInterop --- resources/assets/js/app.ts | 2 +- resources/assets/js/checkin.tsx | 4 ++-- resources/assets/js/components/CheckBox.tsx | 2 +- resources/assets/js/components/CheckinForm.tsx | 4 ++-- resources/assets/js/components/FieldError.tsx | 2 +- resources/assets/js/components/MetadataPreview.tsx | 4 ++-- resources/assets/js/components/TagInput.tsx | 4 ++-- resources/assets/js/home.ts | 2 +- resources/assets/js/user/profile.ts | 2 +- resources/assets/js/user/stats.ts | 4 ++-- tsconfig.json | 3 ++- 11 files changed, 17 insertions(+), 16 deletions(-) diff --git a/resources/assets/js/app.ts b/resources/assets/js/app.ts index 10fdc70..03e22fe 100644 --- a/resources/assets/js/app.ts +++ b/resources/assets/js/app.ts @@ -1,4 +1,4 @@ -import * as Cookies from 'js-cookie'; +import Cookies from 'js-cookie'; import { fetchPostJson, fetchDeleteJson, ResponseError } from './fetch'; import { linkCard, pageSelector, deleteCheckinModal } from './tissue'; diff --git a/resources/assets/js/checkin.tsx b/resources/assets/js/checkin.tsx index 80b5a88..5be6ce0 100644 --- a/resources/assets/js/checkin.tsx +++ b/resources/assets/js/checkin.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; +import React from 'react'; +import ReactDOM from 'react-dom'; import { CheckinForm } from './components/CheckinForm'; const initialState = JSON.parse(document.getElementById('initialState')?.textContent as string); diff --git a/resources/assets/js/components/CheckBox.tsx b/resources/assets/js/components/CheckBox.tsx index 30a7226..fb64b2c 100644 --- a/resources/assets/js/components/CheckBox.tsx +++ b/resources/assets/js/components/CheckBox.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; type CheckboxProps = { id: string; diff --git a/resources/assets/js/components/CheckinForm.tsx b/resources/assets/js/components/CheckinForm.tsx index 442b436..e3ff20b 100644 --- a/resources/assets/js/components/CheckinForm.tsx +++ b/resources/assets/js/components/CheckinForm.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; +import React from 'react'; import { useState } from 'react'; -import * as classNames from 'classnames'; +import classNames from 'classnames'; import { CheckBox } from './CheckBox'; import { FieldError, StandaloneFieldError } from './FieldError'; import { TagInput } from './TagInput'; diff --git a/resources/assets/js/components/FieldError.tsx b/resources/assets/js/components/FieldError.tsx index 61ec77e..3cb2154 100644 --- a/resources/assets/js/components/FieldError.tsx +++ b/resources/assets/js/components/FieldError.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; type FieldErrorProps = { errors?: string[]; diff --git a/resources/assets/js/components/MetadataPreview.tsx b/resources/assets/js/components/MetadataPreview.tsx index 5a3db0c..7e3c5e8 100644 --- a/resources/assets/js/components/MetadataPreview.tsx +++ b/resources/assets/js/components/MetadataPreview.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; +import React from 'react'; import { useEffect, useState } from 'react'; -import * as classNames from 'classnames'; +import classNames from 'classnames'; import { fetchGet, ResponseError } from '../fetch'; enum MetadataLoadState { diff --git a/resources/assets/js/components/TagInput.tsx b/resources/assets/js/components/TagInput.tsx index 2d12e24..493302e 100644 --- a/resources/assets/js/components/TagInput.tsx +++ b/resources/assets/js/components/TagInput.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; +import React from 'react'; import { useState, useRef } from 'react'; -import * as classNames from 'classnames'; +import classNames from 'classnames'; type TagInputProps = { id: string; diff --git a/resources/assets/js/home.ts b/resources/assets/js/home.ts index 2d6f431..84ad1de 100644 --- a/resources/assets/js/home.ts +++ b/resources/assets/js/home.ts @@ -1,4 +1,4 @@ -import * as Chart from 'chart.js'; +import Chart from 'chart.js'; const graph = document.getElementById('global-count-graph') as HTMLCanvasElement; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/resources/assets/js/user/profile.ts b/resources/assets/js/user/profile.ts index 8557397..d3d4b72 100644 --- a/resources/assets/js/user/profile.ts +++ b/resources/assets/js/user/profile.ts @@ -1,4 +1,4 @@ -import * as CalHeatMap from 'cal-heatmap'; +import CalHeatMap from 'cal-heatmap'; import { subMonths } from 'date-fns'; if (document.getElementById('cal-heatmap')) { diff --git a/resources/assets/js/user/stats.ts b/resources/assets/js/user/stats.ts index 7b23235..f3c0c2a 100644 --- a/resources/assets/js/user/stats.ts +++ b/resources/assets/js/user/stats.ts @@ -1,5 +1,5 @@ -import * as CalHeatMap from 'cal-heatmap'; -import * as Chart from 'chart.js'; +import CalHeatMap from 'cal-heatmap'; +import Chart from 'chart.js'; import { addMonths, format } from 'date-fns'; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/tsconfig.json b/tsconfig.json index 4801f69..6c2eca6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,8 @@ "moduleResolution": "node", "strict": true, "experimentalDecorators": true, - "jsx": "react" + "jsx": "react", + "esModuleInterop": true }, "include": [ "resources/assets/js/**/*" From 4405a2b526dff7f3433950592f6fcec9608c3cba Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 18:23:16 +0900 Subject: [PATCH 19/26] concat import --- resources/assets/js/components/CheckinForm.tsx | 3 +-- resources/assets/js/components/MetadataPreview.tsx | 3 +-- resources/assets/js/components/TagInput.tsx | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/resources/assets/js/components/CheckinForm.tsx b/resources/assets/js/components/CheckinForm.tsx index e3ff20b..fec11be 100644 --- a/resources/assets/js/components/CheckinForm.tsx +++ b/resources/assets/js/components/CheckinForm.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import { useState } from 'react'; +import React, { useState } from 'react'; import classNames from 'classnames'; import { CheckBox } from './CheckBox'; import { FieldError, StandaloneFieldError } from './FieldError'; diff --git a/resources/assets/js/components/MetadataPreview.tsx b/resources/assets/js/components/MetadataPreview.tsx index 7e3c5e8..e4ecb2c 100644 --- a/resources/assets/js/components/MetadataPreview.tsx +++ b/resources/assets/js/components/MetadataPreview.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import { useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import classNames from 'classnames'; import { fetchGet, ResponseError } from '../fetch'; diff --git a/resources/assets/js/components/TagInput.tsx b/resources/assets/js/components/TagInput.tsx index 493302e..24f664b 100644 --- a/resources/assets/js/components/TagInput.tsx +++ b/resources/assets/js/components/TagInput.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import { useState, useRef } from 'react'; +import React, { useState, useRef } from 'react'; import classNames from 'classnames'; type TagInputProps = { From acc3c05c8645ca066b55371059c120289359b66f Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 17 Aug 2020 20:06:07 +0900 Subject: [PATCH 20/26] fix lint-staged extension --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 135f53f..b2de9a8 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "stylelint --fix", "git add" ], - "*.{ts,js,vue}": [ + "*.{ts,tsx,js}": [ "eslint --fix", "git add" ], From d894897b828d66e9a8f569fcf8e6f1853ff9e894 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2020 23:45:16 +0000 Subject: [PATCH 21/26] Bump @types/chart.js from 2.9.22 to 2.9.23 (#461) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b2de9a8..6b5af1d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "devDependencies": { "@types/bootstrap": "^4.5.0", "@types/cal-heatmap": "^3.3.10", - "@types/chart.js": "^2.9.22", + "@types/chart.js": "^2.9.23", "@types/classnames": "^2.2.10", "@types/jquery": "^3.3.38", "@types/js-cookie": "^2.2.0", diff --git a/yarn.lock b/yarn.lock index 0fa4fc1..e39ef96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -765,10 +765,10 @@ dependencies: "@types/d3" "^3" -"@types/chart.js@^2.9.22": - version "2.9.22" - resolved "https://registry.yarnpkg.com/@types/chart.js/-/chart.js-2.9.22.tgz#e52fd922aced217867445c2913b68ce98b1c2b5f" - integrity sha512-CneMxwh2T5fyMpXE5fuprTTmFtlLyZUFq1A3laUrCgOblDzupgiohrFg3jjsTIrqRI5K4qLZdrLN4zT9/MY5Dw== +"@types/chart.js@^2.9.23": + version "2.9.23" + resolved "https://registry.yarnpkg.com/@types/chart.js/-/chart.js-2.9.23.tgz#5de713e801f5aff4d042c7d49ab9691489c11848" + integrity sha512-4QQNE/b+digosu3mnj4E7aNQGKnlpzXa9JvQYPtexpO7v9gnDeqwc1DxF8vLJWLDCNoO6hH0EgO8K/7PtJl8wg== dependencies: moment "^2.10.2" From 3015f8261180b2f6aea0d3eb101b8c15418fec0b Mon Sep 17 00:00:00 2001 From: shibafu Date: Wed, 19 Aug 2020 09:46:18 +0900 Subject: [PATCH 22/26] =?UTF-8?q?=E9=9D=9E=E5=85=AC=E9=96=8B=E3=83=95?= =?UTF-8?q?=E3=83=A9=E3=82=B0=E3=80=81=E3=82=BB=E3=83=B3=E3=82=B7=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=83=96=E3=83=95=E3=83=A9=E3=82=B0=E3=81=AECSV?= =?UTF-8?q?=E5=87=BA=E5=8A=9B=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Services/CheckinCsvExporter.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Services/CheckinCsvExporter.php b/app/Services/CheckinCsvExporter.php index a94ec32..22607a0 100644 --- a/app/Services/CheckinCsvExporter.php +++ b/app/Services/CheckinCsvExporter.php @@ -30,7 +30,7 @@ class CheckinCsvExporter $csv->addStreamFilter('convert.mbstring.encoding.UTF-8:SJIS-win'); } - $header = ['日時', 'ノート', 'オカズリンク']; + $header = ['日時', 'ノート', 'オカズリンク', '非公開', 'センシティブ']; for ($i = 1; $i <= 32; $i++) { $header[] = "タグ{$i}"; } @@ -45,6 +45,8 @@ class CheckinCsvExporter $ejaculation->ejaculated_date->format('Y/m/d H:i'), $ejaculation->note, $ejaculation->link, + self::formatBoolean($ejaculation->is_private), + self::formatBoolean($ejaculation->is_too_sensitive), ]; foreach ($ejaculation->tags->take(32) as $tag) { $record[] = $tag->name; @@ -54,4 +56,9 @@ class CheckinCsvExporter }); }); } + + private static function formatBoolean($value): string + { + return $value ? 'true' : 'false'; + } } From 27e9a86be8ee74bc2f0b62b65d488c81663b1740 Mon Sep 17 00:00:00 2001 From: shibafu Date: Wed, 19 Aug 2020 21:00:34 +0900 Subject: [PATCH 23/26] add test --- .../Unit/Services/CheckinCsvImporterTest.php | 42 +++++++++++++++++++ tests/fixture/Csv/private.utf8.csv | 10 +++++ tests/fixture/Csv/too-sensitive.utf8.csv | 10 +++++ 3 files changed, 62 insertions(+) create mode 100644 tests/fixture/Csv/private.utf8.csv create mode 100644 tests/fixture/Csv/too-sensitive.utf8.csv diff --git a/tests/Unit/Services/CheckinCsvImporterTest.php b/tests/Unit/Services/CheckinCsvImporterTest.php index 8d208bf..f58ae7e 100644 --- a/tests/Unit/Services/CheckinCsvImporterTest.php +++ b/tests/Unit/Services/CheckinCsvImporterTest.php @@ -277,6 +277,48 @@ class CheckinCsvImporterTest extends TestCase $this->assertEquals(Ejaculation::SOURCE_CSV, $ejaculation->source); } + public function testIsPrivateUTF8() + { + $user = factory(User::class)->create(); + + $importer = new CheckinCsvImporter($user, __DIR__ . '/../../fixture/Csv/private.utf8.csv'); + $importer->execute(); + + $ejaculations = $user->ejaculations()->orderBy('ejaculated_date')->get(); + + $this->assertSame(9, $ejaculations->count()); + $this->assertTrue($ejaculations[0]->is_private); + $this->assertTrue($ejaculations[1]->is_private); + $this->assertTrue($ejaculations[2]->is_private); + $this->assertTrue($ejaculations[3]->is_private); + $this->assertFalse($ejaculations[4]->is_private); + $this->assertFalse($ejaculations[5]->is_private); + $this->assertFalse($ejaculations[6]->is_private); + $this->assertFalse($ejaculations[7]->is_private); + $this->assertFalse($ejaculations[8]->is_private); + } + + public function testIsTooSensitiveUTF8() + { + $user = factory(User::class)->create(); + + $importer = new CheckinCsvImporter($user, __DIR__ . '/../../fixture/Csv/too-sensitive.utf8.csv'); + $importer->execute(); + + $ejaculations = $user->ejaculations()->orderBy('ejaculated_date')->get(); + + $this->assertSame(9, $ejaculations->count()); + $this->assertTrue($ejaculations[0]->is_too_sensitive); + $this->assertTrue($ejaculations[1]->is_too_sensitive); + $this->assertTrue($ejaculations[2]->is_too_sensitive); + $this->assertTrue($ejaculations[3]->is_too_sensitive); + $this->assertFalse($ejaculations[4]->is_too_sensitive); + $this->assertFalse($ejaculations[5]->is_too_sensitive); + $this->assertFalse($ejaculations[6]->is_too_sensitive); + $this->assertFalse($ejaculations[7]->is_too_sensitive); + $this->assertFalse($ejaculations[8]->is_too_sensitive); + } + public function testDontThrowUniqueKeyViolation() { $user = factory(User::class)->create(); diff --git a/tests/fixture/Csv/private.utf8.csv b/tests/fixture/Csv/private.utf8.csv new file mode 100644 index 0000000..259b893 --- /dev/null +++ b/tests/fixture/Csv/private.utf8.csv @@ -0,0 +1,10 @@ +日時,非公開 +2020/01/23 06:01:00,true +2020/01/23 06:02:00,TRUE +2020/01/23 06:03:00,True +2020/01/23 06:04:00,1 +2020/01/23 07:01:00,false +2020/01/23 07:02:00,FALSE +2020/01/23 07:03:00,False +2020/01/23 07:04:00,0 +2020/01/23 07:05:00, diff --git a/tests/fixture/Csv/too-sensitive.utf8.csv b/tests/fixture/Csv/too-sensitive.utf8.csv new file mode 100644 index 0000000..24cd1ef --- /dev/null +++ b/tests/fixture/Csv/too-sensitive.utf8.csv @@ -0,0 +1,10 @@ +日時,センシティブ +2020/01/23 06:01:00,true +2020/01/23 06:02:00,TRUE +2020/01/23 06:03:00,True +2020/01/23 06:04:00,1 +2020/01/23 07:01:00,false +2020/01/23 07:02:00,FALSE +2020/01/23 07:03:00,False +2020/01/23 07:04:00,0 +2020/01/23 07:05:00, From 915b575e6eb7157cc97c5d1a641bc266d1e681fd Mon Sep 17 00:00:00 2001 From: shibafu Date: Wed, 19 Aug 2020 21:25:07 +0900 Subject: [PATCH 24/26] =?UTF-8?q?=E9=9D=9E=E5=85=AC=E9=96=8B=E3=83=95?= =?UTF-8?q?=E3=83=A9=E3=82=B0=E3=80=81=E3=82=BB=E3=83=B3=E3=82=B7=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=83=96=E3=83=95=E3=83=A9=E3=82=B0=E3=81=AECSV?= =?UTF-8?q?=E5=85=A5=E5=8A=9B=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Rules/FuzzyBoolean.php | 62 +++++++++++++++++++++++++++++ app/Services/CheckinCsvImporter.php | 9 +++++ 2 files changed, 71 insertions(+) create mode 100644 app/Rules/FuzzyBoolean.php diff --git a/app/Rules/FuzzyBoolean.php b/app/Rules/FuzzyBoolean.php new file mode 100644 index 0000000..ec40d71 --- /dev/null +++ b/app/Rules/FuzzyBoolean.php @@ -0,0 +1,62 @@ + ['required', new CsvDateTime()], 'ノート' => 'nullable|string|max:500', 'オカズリンク' => 'nullable|url|max:2000', + '非公開' => ['nullable', new FuzzyBoolean()], + 'センシティブ' => ['nullable', new FuzzyBoolean()], ]); if ($validator->fails()) { @@ -88,6 +91,12 @@ class CheckinCsvImporter $ejaculation->note = str_replace(["\r\n", "\r"], "\n", $record['ノート'] ?? ''); $ejaculation->link = $record['オカズリンク'] ?? ''; $ejaculation->source = Ejaculation::SOURCE_CSV; + if (isset($record['非公開'])) { + $ejaculation->is_private = FuzzyBoolean::isTruthy($record['非公開']); + } + if (isset($record['センシティブ'])) { + $ejaculation->is_too_sensitive = FuzzyBoolean::isTruthy($record['センシティブ']); + } try { $tags = $this->parseTags($line, $record); From f8a5cc5d542926dc2203eaf19eeb57a3dd722151 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Aug 2020 14:53:18 +0000 Subject: [PATCH 25/26] Bump date-fns from 1.30.1 to 2.15.0 Bumps [date-fns](https://github.com/date-fns/date-fns) from 1.30.1 to 2.15.0. - [Release notes](https://github.com/date-fns/date-fns/releases) - [Changelog](https://github.com/date-fns/date-fns/blob/master/CHANGELOG.md) - [Commits](https://github.com/date-fns/date-fns/compare/v1.30.1...v2.15.0) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6b5af1d..571830a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "chart.js": "^2.7.1", "classnames": "^2.2.6", "cross-env": "^5.2.0", - "date-fns": "^1.30.1", + "date-fns": "^2.15.0", "eslint": "^7.6.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-jquery": "^1.5.1", diff --git a/yarn.lock b/yarn.lock index e39ef96..00585d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2562,11 +2562,16 @@ d@1, d@^1.0.1: es5-ext "^0.10.50" type "^1.0.1" -date-fns@^1.27.2, date-fns@^1.30.1: +date-fns@^1.27.2: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== +date-fns@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.15.0.tgz#424de6b3778e4e69d3ff27046ec136af58ae5d5f" + integrity sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" From a54d57827f23374075ba2db7d9b2b9295d6f97ee Mon Sep 17 00:00:00 2001 From: shibafu Date: Wed, 19 Aug 2020 23:54:56 +0900 Subject: [PATCH 26/26] fix format pattern --- resources/assets/js/user/stats.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/js/user/stats.ts b/resources/assets/js/user/stats.ts index f3c0c2a..36ccc02 100644 --- a/resources/assets/js/user/stats.ts +++ b/resources/assets/js/user/stats.ts @@ -90,7 +90,7 @@ function createMonthlyGraphData(from: Date) { for (let i = 0; i < 12; i++) { const current = addMonths(from, i); - const yearAndMonth = format(current, 'YYYY/MM'); + const yearAndMonth = format(current, 'yyyy/MM'); keys.push(yearAndMonth); values.push(graphData.monthlySum[yearAndMonth] || 0); }