diff --git a/package.json b/package.json index 02a881f..9b1f55a 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,11 @@ "stylelint": "stylelint resources/assets/sass/**/*" }, "devDependencies": { + "@types/bootstrap": "^4.5.0", + "@types/cal-heatmap": "^3.3.10", + "@types/chart.js": "^2.7.1", "@types/jquery": "^3.3.38", + "@types/js-cookie": "^2.2.0", "bootstrap": "^4.5.0", "cal-heatmap": "^3.3.10", "chart.js": "^2.7.1", diff --git a/resources/assets/js/@types/cal-heatmap.d.ts b/resources/assets/js/@types/cal-heatmap.d.ts new file mode 100644 index 0000000..334e1d0 --- /dev/null +++ b/resources/assets/js/@types/cal-heatmap.d.ts @@ -0,0 +1,4 @@ +// なんか @types/cal-heatmap 入れても動かなかったんですけど!! +declare module 'cal-heatmap' { + export = CalHeatMap; +} diff --git a/resources/assets/js/@types/jquery-bootstrap.d.ts b/resources/assets/js/@types/jquery-bootstrap.d.ts new file mode 100644 index 0000000..7fd97d5 --- /dev/null +++ b/resources/assets/js/@types/jquery-bootstrap.d.ts @@ -0,0 +1,4 @@ +// @types/bootstrap に足りないもの +interface JQuery { + modal(action: "toggle" | "show" | "hide" | "handleUpdate" | "dispose", relatedTarget?: TElement): this; +} diff --git a/resources/assets/js/@types/jquery-tissue.d.ts b/resources/assets/js/@types/jquery-tissue.d.ts new file mode 100644 index 0000000..3938ccb --- /dev/null +++ b/resources/assets/js/@types/jquery-tissue.d.ts @@ -0,0 +1,12 @@ +// tissue.ts で定義されているjQuery Pluginの型定義 +declare namespace JQueryTissue { + interface LinkCardOptions { + endpoint: string; + } +} + +interface JQuery { + linkCard: (options?: JQueryTissue.LinkCardOptions) => this; + pageSelector: () => this; + deleteCheckinModal: () => this; +} diff --git a/resources/assets/js/vue-shims.d.ts b/resources/assets/js/@types/vue-shims.d.ts similarity index 100% rename from resources/assets/js/vue-shims.d.ts rename to resources/assets/js/@types/vue-shims.d.ts diff --git a/resources/assets/js/app.js b/resources/assets/js/app.ts similarity index 92% rename from resources/assets/js/app.js rename to resources/assets/js/app.ts index 3daf978..75486b1 100644 --- a/resources/assets/js/app.js +++ b/resources/assets/js/app.ts @@ -1,4 +1,5 @@ -import Cookies from 'js-cookie'; +import * as Cookies from 'js-cookie'; +import jqXHR = JQuery.jqXHR; require('./bootstrap'); @@ -40,7 +41,7 @@ $(() => { const isLiked = $this.data('liked'); if (isLiked) { - const callback = (data) => { + const callback = (data: any) => { $this.data('liked', false); $this.find('.oi-heart').removeClass('text-danger'); @@ -54,7 +55,7 @@ $(() => { type: 'json' }) .then(callback) - .catch(function (xhr) { + .catch(function (xhr: jqXHR) { if (xhr.status === 404) { callback(JSON.parse(xhr.responseText)); return; @@ -64,7 +65,7 @@ $(() => { alert('いいねを解除できませんでした。'); }); } else { - const callback = (data) => { + const callback = (data: any) => { $this.data('liked', true); $this.find('.oi-heart').addClass('text-danger'); @@ -81,7 +82,7 @@ $(() => { } }) .then(callback) - .catch(function (xhr) { + .catch(function (xhr: jqXHR) { if (xhr.status === 409) { callback(JSON.parse(xhr.responseText)); return; diff --git a/resources/assets/js/bootstrap.js b/resources/assets/js/bootstrap.ts similarity index 51% rename from resources/assets/js/bootstrap.js rename to resources/assets/js/bootstrap.ts index 81c1799..615345b 100644 --- a/resources/assets/js/bootstrap.js +++ b/resources/assets/js/bootstrap.ts @@ -2,16 +2,16 @@ import './tissue'; // Setup global request header -const token = document.head.querySelector('meta[name="csrf-token"]'); +const token = document.head.querySelector('meta[name="csrf-token"]'); if (!token) { console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token'); +} else { + $.ajaxSetup({ + headers: { + 'X-CSRF-TOKEN': token.content + } + }); } -$.ajaxSetup({ - headers: { - 'X-CSRF-TOKEN': token.content - } -}); - // Bootstrap import 'bootstrap'; diff --git a/resources/assets/js/home.js b/resources/assets/js/home.ts similarity index 77% rename from resources/assets/js/home.js rename to resources/assets/js/home.ts index a5d8f4b..55baa1e 100644 --- a/resources/assets/js/home.js +++ b/resources/assets/js/home.ts @@ -1,10 +1,10 @@ -import Chart from 'chart.js'; +import * as Chart from 'chart.js'; -const graph = document.getElementById('global-count-graph'); -const labels = JSON.parse(document.getElementById('global-count-labels').textContent); -const data = JSON.parse(document.getElementById('global-count-data').textContent); +const graph = document.getElementById('global-count-graph') as HTMLCanvasElement; +const labels = JSON.parse(document.getElementById('global-count-labels')!.textContent as string); +const data = JSON.parse(document.getElementById('global-count-data')!.textContent as string); -new Chart(graph.getContext('2d'), { +new Chart(graph.getContext('2d')!, { type: 'bar', data: { labels, diff --git a/resources/assets/js/setting/deactivate.js b/resources/assets/js/setting/deactivate.ts similarity index 100% rename from resources/assets/js/setting/deactivate.js rename to resources/assets/js/setting/deactivate.ts diff --git a/resources/assets/js/setting/import.js b/resources/assets/js/setting/import.ts similarity index 100% rename from resources/assets/js/setting/import.js rename to resources/assets/js/setting/import.ts diff --git a/resources/assets/js/setting/privacy.js b/resources/assets/js/setting/privacy.ts similarity index 100% rename from resources/assets/js/setting/privacy.js rename to resources/assets/js/setting/privacy.ts diff --git a/resources/assets/js/tissue.js b/resources/assets/js/tissue.ts similarity index 71% rename from resources/assets/js/tissue.js rename to resources/assets/js/tissue.ts index 4c14c75..e1a5a73 100644 --- a/resources/assets/js/tissue.js +++ b/resources/assets/js/tissue.ts @@ -1,12 +1,12 @@ (function ($) { $.fn.linkCard = function (options) { - var settings = $.extend({ + const settings = $.extend({ endpoint: '/api/checkin/card' }, options); return this.each(function () { - var $this = $(this); + const $this = $(this); $.ajax({ url: settings.endpoint, method: 'get', @@ -15,11 +15,11 @@ url: $this.find('a').attr('href') } }).then(function (data) { - var $metaColumn = $this.find('.col-12:last-of-type'); - var $imageColumn = $this.find('.col-12:first-of-type'); - var $title = $this.find('.card-title'); - var $desc = $this.find('.card-text'); - var $image = $imageColumn.find('img'); + 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(); @@ -56,17 +56,17 @@ $.fn.deleteCheckinModal = function () { return this.each(function () { $(this).on('show.bs.modal', function (event) { - var target = $(event.relatedTarget); - var modal = $(this); + 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) { - var modal = $('#deleteCheckinModal'); - var form = modal.find('form'); - form.attr('action', form.attr('action').replace('@', modal.data('id'))); + const modal = $('#deleteCheckinModal'); + const form = modal.find('form'); + form.attr('action', form.attr('action')?.replace('@', modal.data('id')) || null); form.submit(); }) }); }; -})(jQuery); \ No newline at end of file +})(jQuery); diff --git a/resources/assets/js/user/profile.js b/resources/assets/js/user/profile.ts similarity index 70% rename from resources/assets/js/user/profile.js rename to resources/assets/js/user/profile.ts index 24cba77..809c4e1 100644 --- a/resources/assets/js/user/profile.js +++ b/resources/assets/js/user/profile.ts @@ -1,4 +1,5 @@ -import CalHeatMap from 'cal-heatmap'; +import * as CalHeatMap from 'cal-heatmap'; +import {subMonths} from 'date-fns'; if (document.getElementById('cal-heatmap')) { new CalHeatMap().init({ @@ -7,9 +8,9 @@ if (document.getElementById('cal-heatmap')) { subDomain: 'day', domainLabelFormat: '%Y/%m', weekStartOnMonday: false, - start: new Date().setMonth(new Date().getMonth() - 9), + start: subMonths(new Date(), 9), range: 10, - data: JSON.parse(document.getElementById('count-by-day').textContent), + data: JSON.parse(document.getElementById('count-by-day')!.textContent as string), legend: [1, 2, 3, 4] }); } diff --git a/resources/assets/js/user/stats.js b/resources/assets/js/user/stats.ts similarity index 79% rename from resources/assets/js/user/stats.js rename to resources/assets/js/user/stats.ts index d1fda72..40b72bd 100644 --- a/resources/assets/js/user/stats.js +++ b/resources/assets/js/user/stats.ts @@ -1,12 +1,12 @@ -import CalHeatMap from 'cal-heatmap'; -import Chart from 'chart.js'; +import * as CalHeatMap from 'cal-heatmap'; +import * as Chart from 'chart.js'; import {addMonths, format} from 'date-fns'; -const graphData = JSON.parse(document.getElementById('graph-data').textContent); +const graphData = JSON.parse(document.getElementById('graph-data')!.textContent as string); -function createLineGraph(id, labels, data) { - const context = document.getElementById(id).getContext('2d'); - return new Chart(context, { +function createLineGraph(id: string, labels: string[], data: any) { + const context = (document.getElementById(id) as HTMLCanvasElement).getContext('2d'); + return new Chart(context!, { type: 'line', data: { labels: labels, @@ -41,9 +41,9 @@ function createLineGraph(id, labels, data) { }); } -function createBarGraph(id, labels, data) { - const context = document.getElementById(id).getContext('2d'); - new Chart(context, { +function createBarGraph(id: string, labels: string[], data: any) { + const context = (document.getElementById(id) as HTMLCanvasElement).getContext('2d'); + new Chart(context!, { type: 'bar', data: { labels: labels, @@ -73,10 +73,7 @@ function createBarGraph(id, labels, data) { }); } -/** - * @param {Date} from - */ -function createMonthlyGraphData(from) { +function createMonthlyGraphData(from: Date) { const keys = []; const values = []; @@ -90,9 +87,13 @@ function createMonthlyGraphData(from) { return {keys, values}; } -function getCurrentYear() { - const year = location.pathname.split('/').pop(); - return /^(20[0-9]{2})$/.test(year) ? year : null; +function getCurrentYear(): number { + const year = location.pathname.split('/').pop() || ''; + if (/^(20[0-9]{2})$/.test(year)) { + return parseInt(year, 10); + } else { + throw 'Invalid year'; + } } if (document.getElementById('cal-heatmap')) { diff --git a/webpack.mix.js b/webpack.mix.js index c897632..6fe6635 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -12,13 +12,13 @@ require('laravel-mix-bundle-analyzer') | */ -mix.js('resources/assets/js/app.js', 'public/js') - .js('resources/assets/js/home.js', 'public/js') - .js('resources/assets/js/user/profile.js', 'public/js/user') - .js('resources/assets/js/user/stats.js', 'public/js/user') - .js('resources/assets/js/setting/privacy.js', 'public/js/setting') - .js('resources/assets/js/setting/import.js', 'public/js/setting') - .js('resources/assets/js/setting/deactivate.js', 'public/js/setting') +mix.ts('resources/assets/js/app.ts', 'public/js') + .ts('resources/assets/js/home.ts', 'public/js') + .ts('resources/assets/js/user/profile.ts', 'public/js/user') + .ts('resources/assets/js/user/stats.ts', 'public/js/user') + .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') .sass('resources/assets/sass/app.scss', 'public/css') .autoload({ diff --git a/yarn.lock b/yarn.lock index c12e28a..206d5e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -745,6 +745,33 @@ dependencies: any-observable "^0.3.0" +"@types/bootstrap@^4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-4.5.0.tgz#07a079d3ee2b1646491082d6162048d7bf4610b5" + integrity sha512-AWu7D+Cduyic75YptSRiXuCIy1c3SsmYk/9ixS68Ft2eAgg2wRj5U2M+7PK5zpakk4gTgfrWHeGxJqkSjttwyQ== + dependencies: + "@types/jquery" "*" + popper.js "^1.14.1" + +"@types/cal-heatmap@^3.3.10": + version "3.5.35" + resolved "https://registry.yarnpkg.com/@types/cal-heatmap/-/cal-heatmap-3.5.35.tgz#ca66c42bef97b6ba4103fdcda9a381300f9929e3" + integrity sha512-QG6NfOPphdo58oNHZ6JXCwQ4KgC94OeUAdo+KNrkbMzA+4FkrlXD1BnxvncOsOfSiJiiaQwxdVoE/AXMin39vw== + dependencies: + "@types/d3" "^3" + +"@types/chart.js@^2.7.1": + version "2.9.21" + resolved "https://registry.yarnpkg.com/@types/chart.js/-/chart.js-2.9.21.tgz#ecb85f1aac2d7b28310df8cc9c88b6b5db1b91bd" + integrity sha512-bjwdC+SvE/c3rHYYcX8UbRmTvjEUP9Dhuk/iWXygH6EFDYf4OcofnwxBpJx+A4qU3YBr54a7wtPdswfg9Yt3rg== + dependencies: + moment "^2.10.2" + +"@types/d3@^3": + version "3.5.43" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.43.tgz#e9b4992817e0b6c5efaa7d6e5bb2cee4d73eab58" + integrity sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -759,13 +786,18 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/jquery@^3.3.38": +"@types/jquery@*", "@types/jquery@^3.3.38": version "3.3.38" resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.38.tgz#6385f1e1b30bd2bff55ae8ee75ea42a999cc3608" integrity sha512-nkDvmx7x/6kDM5guu/YpXkGZ/Xj/IwGiLDdKM99YA5Vag7pjGyTJ8BNUh/6hxEn/sEu5DKtyRgnONJ7EmOoKrA== dependencies: "@types/sizzle" "*" +"@types/js-cookie@^2.2.0": + version "2.2.6" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f" + integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -5627,7 +5659,7 @@ please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1: dependencies: semver-compare "^1.0.0" -popper.js@^1.14.7: +popper.js@^1.14.1, popper.js@^1.14.7: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==