diff --git a/extensions/statistics/js/package-lock.json b/extensions/statistics/js/package-lock.json index 8f368c396..db98e9f0a 100644 --- a/extensions/statistics/js/package-lock.json +++ b/extensions/statistics/js/package-lock.json @@ -6,10 +6,15 @@ "": { "name": "@flarum/statistics", "dependencies": { + "@flarum/prettier-config": "^1.0.0", + "flarum-tsconfig": "^1.0.2", "flarum-webpack-config": "^1.0.0", "frappe-charts": "^1.6.2", "webpack": "^4.46.0", - "webpack-cli": "^4.9.0" + "webpack-cli": "^4.9.1" + }, + "devDependencies": { + "prettier": "^2.5.1" } }, "node_modules/@babel/code-frame": { @@ -1618,16 +1623,44 @@ "node": ">=10.0.0" } }, + "node_modules/@flarum/prettier-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@flarum/prettier-config/-/prettier-config-1.0.0.tgz", + "integrity": "sha512-3/AcliIi5jPt4i7COb5hsLv6hm4EeXT9yI9I2EuEvhPi2QR+O9Y/8wrqRuO5mDkRzCIhUY+mjIL/f9770Zwfqg==" + }, "node_modules/@polka/url": { "version": "1.0.0-next.21", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" }, + "node_modules/@types/jquery": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.12.tgz", + "integrity": "sha512-AlX/K29WByFhZ3UbVVn8eywPFwhDZGc/qhDWgy5mu4VVr9b+OQZKBegtS6Tqi9pk8A1aXVrYXuLhnjFJX8Wc/w==", + "dependencies": { + "@types/sizzle": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, + "node_modules/@types/mithril": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.8.tgz", + "integrity": "sha512-QzVV70DqUhWfLFpMFDBI9rRxtzeUUpbhiFDpUJYSV92AePgl+Qfficgv2MOb1Ceb+lBOQU8+L+Hjf2UielQjEw==" + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, + "node_modules/@types/throttle-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", + "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==" + }, "node_modules/@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -2822,6 +2855,11 @@ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, + "node_modules/dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -3379,6 +3417,17 @@ "node": ">=8" } }, + "node_modules/flarum-tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flarum-tsconfig/-/flarum-tsconfig-1.0.2.tgz", + "integrity": "sha512-RUaN7D6noLK9vY1F86NIc+IlIP1YAA3bJ4jGR5pIm8UxvLBLW8qrAHzIosuQJgvnge7VgTA5c2LoNefUK/9EiQ==", + "dependencies": { + "@types/jquery": "^3.5.5", + "@types/mithril": "^2.0.7", + "@types/throttle-debounce": "^2.1.0", + "dayjs": "^1.10.4" + } + }, "node_modules/flarum-webpack-config": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flarum-webpack-config/-/flarum-webpack-config-1.0.0.tgz", @@ -4705,6 +4754,18 @@ "node": ">=0.10.0" } }, + "node_modules/prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -6052,11 +6113,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -6358,9 +6414,9 @@ } }, "node_modules/webpack-cli": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz", - "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", + "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.1.0", @@ -6373,7 +6429,6 @@ "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", "webpack-merge": "^5.7.3" }, "bin": { @@ -7598,16 +7653,44 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz", "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==" }, + "@flarum/prettier-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@flarum/prettier-config/-/prettier-config-1.0.0.tgz", + "integrity": "sha512-3/AcliIi5jPt4i7COb5hsLv6hm4EeXT9yI9I2EuEvhPi2QR+O9Y/8wrqRuO5mDkRzCIhUY+mjIL/f9770Zwfqg==" + }, "@polka/url": { "version": "1.0.0-next.21", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" }, + "@types/jquery": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.12.tgz", + "integrity": "sha512-AlX/K29WByFhZ3UbVVn8eywPFwhDZGc/qhDWgy5mu4VVr9b+OQZKBegtS6Tqi9pk8A1aXVrYXuLhnjFJX8Wc/w==", + "requires": { + "@types/sizzle": "*" + } + }, "@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, + "@types/mithril": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.8.tgz", + "integrity": "sha512-QzVV70DqUhWfLFpMFDBI9rRxtzeUUpbhiFDpUJYSV92AePgl+Qfficgv2MOb1Ceb+lBOQU8+L+Hjf2UielQjEw==" + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, + "@types/throttle-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", + "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==" + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -8607,6 +8690,11 @@ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, + "dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -9050,6 +9138,17 @@ "path-exists": "^4.0.0" } }, + "flarum-tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flarum-tsconfig/-/flarum-tsconfig-1.0.2.tgz", + "integrity": "sha512-RUaN7D6noLK9vY1F86NIc+IlIP1YAA3bJ4jGR5pIm8UxvLBLW8qrAHzIosuQJgvnge7VgTA5c2LoNefUK/9EiQ==", + "requires": { + "@types/jquery": "^3.5.5", + "@types/mithril": "^2.0.7", + "@types/throttle-debounce": "^2.1.0", + "dayjs": "^1.10.4" + } + }, "flarum-webpack-config": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/flarum-webpack-config/-/flarum-webpack-config-1.0.0.tgz", @@ -10060,6 +10159,12 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, + "prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -11154,11 +11259,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -11398,9 +11498,9 @@ } }, "webpack-cli": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz", - "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", + "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", "requires": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.1.0", @@ -11413,7 +11513,6 @@ "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", "webpack-merge": "^5.7.3" }, "dependencies": { diff --git a/extensions/statistics/js/package.json b/extensions/statistics/js/package.json index dc6f06e89..061ec47a0 100644 --- a/extensions/statistics/js/package.json +++ b/extensions/statistics/js/package.json @@ -1,14 +1,22 @@ { "private": true, "name": "@flarum/statistics", + "prettier": "@flarum/prettier-config", "dependencies": { - "flarum-webpack-config": "^1.0.0", + "@flarum/prettier-config": "^1.0.0", "frappe-charts": "^1.6.2", + "flarum-tsconfig": "^1.0.2", + "flarum-webpack-config": "^1.0.0", "webpack": "^4.46.0", - "webpack-cli": "^4.9.0" + "webpack-cli": "^4.9.1" + }, + "devDependencies": { + "prettier": "^2.5.1" }, "scripts": { "dev": "webpack --mode development --watch", - "build": "webpack --mode production" + "build": "webpack --mode production", + "format": "prettier --write src", + "format-check": "prettier --check src" } } diff --git a/extensions/statistics/js/src/admin/components/StatisticsWidget.js b/extensions/statistics/js/src/admin/components/StatisticsWidget.js index 76617657c..f9ac9fb8a 100644 --- a/extensions/statistics/js/src/admin/components/StatisticsWidget.js +++ b/extensions/statistics/js/src/admin/components/StatisticsWidget.js @@ -7,11 +7,12 @@ * file that was distributed with this source code. */ -import DashboardWidget from 'flarum/components/DashboardWidget'; -import SelectDropdown from 'flarum/components/SelectDropdown'; -import Button from 'flarum/components/Button'; -import icon from 'flarum/helpers/icon'; -import abbreviateNumber from 'flarum/utils/abbreviateNumber'; +import app from 'flarum/admin/app'; +import DashboardWidget from 'flarum/admin/components/DashboardWidget'; +import SelectDropdown from 'flarum/common/components/SelectDropdown'; +import Button from 'flarum/common/components/Button'; +import icon from 'flarum/common/helpers/icon'; +import abbreviateNumber from 'flarum/common/utils/abbreviateNumber'; import { Chart } from 'frappe-charts/dist/frappe-charts.esm.js'; @@ -31,10 +32,10 @@ export default class StatisticsWidget extends DashboardWidget { this.entities = ['users', 'discussions', 'posts']; this.periods = { - today: {start: today, end: today + 86400, step: 3600}, - last_7_days: {start: today - 86400 * 7, end: today, step: 86400}, - last_28_days: {start: today - 86400 * 28, end: today, step: 86400}, - last_12_months: {start: today - 86400 * 364, end: today, step: 86400 * 7} + today: { start: today, end: today + 86400, step: 3600 }, + last_7_days: { start: today - 86400 * 7, end: today, step: 86400 }, + last_28_days: { start: today - 86400 * 28, end: today, step: 86400 }, + last_12_months: { start: today - 86400 * 364, end: today, step: 86400 * 7 }, }; this.selectedEntity = 'users'; @@ -54,11 +55,12 @@ export default class StatisticsWidget extends DashboardWidget {
{app.translator.trans('flarum-statistics.admin.statistics.total_label')}
- {Object.keys(this.periods).map(period => ( + {Object.keys(this.periods).map((period) => ( ))} @@ -66,30 +68,37 @@ export default class StatisticsWidget extends DashboardWidget {
- {this.entities.map(entity => { + {this.entities.map((entity) => { const totalCount = this.getTotalCount(entity); const thisPeriodCount = this.getPeriodCount(entity, thisPeriod); const lastPeriodCount = this.getPeriodCount(entity, this.getLastPeriod(thisPeriod)); - const periodChange = lastPeriodCount > 0 && (thisPeriodCount - lastPeriodCount) / lastPeriodCount * 100; + const periodChange = lastPeriodCount > 0 && ((thisPeriodCount - lastPeriodCount) / lastPeriodCount) * 100; return ( - -

{app.translator.trans('flarum-statistics.admin.statistics.'+entity+'_heading')}

-
{abbreviateNumber(totalCount)}
+
+

{app.translator.trans('flarum-statistics.admin.statistics.' + entity + '_heading')}

+
+ {abbreviateNumber(totalCount)} +
{abbreviateNumber(thisPeriodCount)}{' '} {periodChange ? ( - 0 ? 'up' : 'down')}> - {icon('fas fa-arrow-'+(periodChange > 0 ? 'up' : 'down'))} + 0 ? 'up' : 'down')}> + {icon('fas fa-arrow-' + (periodChange > 0 ? 'up' : 'down'))} {Math.abs(periodChange.toFixed(1))}% - ) : ''} + ) : ( + '' + )}
); })} -
+
); } @@ -121,18 +130,15 @@ export default class StatisticsWidget extends DashboardWidget { labels.push(label); - thisPeriod.push(this.getPeriodCount(this.selectedEntity, {start: i, end: i + period.step})); + thisPeriod.push(this.getPeriodCount(this.selectedEntity, { start: i, end: i + period.step })); - lastPeriod.push(this.getPeriodCount(this.selectedEntity, {start: i - periodLength, end: i - periodLength + period.step})); + lastPeriod.push(this.getPeriodCount(this.selectedEntity, { start: i - periodLength, end: i - periodLength + period.step })); } - const datasets = [ - {values: lastPeriod}, - {values: thisPeriod} - ]; + const datasets = [{ values: lastPeriod }, { values: thisPeriod }]; const data = { labels, - datasets + datasets, }; if (!this.chart) { @@ -143,12 +149,12 @@ export default class StatisticsWidget extends DashboardWidget { axisOptions: { xAxisMode: 'tick', yAxisMode: 'span', - xIsSeries: true + xIsSeries: true, }, lineOptions: { - hideDots: 1 + hideDots: 1, }, - colors: ['black', app.forum.attribute('themePrimaryColor')] + colors: ['black', app.forum.attribute('themePrimaryColor')], }); } else { this.chart.update(data); @@ -186,7 +192,7 @@ export default class StatisticsWidget extends DashboardWidget { getLastPeriod(thisPeriod) { return { start: thisPeriod.start - (thisPeriod.end - thisPeriod.start), - end: thisPeriod.start + end: thisPeriod.start, }; } } diff --git a/extensions/statistics/js/src/admin/index.js b/extensions/statistics/js/src/admin/index.js deleted file mode 100644 index a8664ee50..000000000 --- a/extensions/statistics/js/src/admin/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import app from 'flarum/app'; -import { extend } from 'flarum/extend'; - -import DashboardPage from 'flarum/components/DashboardPage'; - -import StatisticsWidget from './components/StatisticsWidget'; - -app.initializers.add('flarum-statistics', () => { - extend(DashboardPage.prototype, 'availableWidgets', widgets => { - widgets.add('statistics', , 20); - }); -}); diff --git a/extensions/statistics/js/src/admin/index.tsx b/extensions/statistics/js/src/admin/index.tsx new file mode 100644 index 000000000..8538f4806 --- /dev/null +++ b/extensions/statistics/js/src/admin/index.tsx @@ -0,0 +1,13 @@ +import app from 'flarum/admin/app'; +import { extend } from 'flarum/common/extend'; + +import DashboardPage from 'flarum/admin/components/DashboardPage'; + +import StatisticsWidget from './components/StatisticsWidget'; +import ItemList from 'flarum/common/utils/ItemList'; + +app.initializers.add('flarum-statistics', () => { + extend(DashboardPage.prototype, 'availableWidgets', function (widgets: ItemList) { + widgets.add('statistics', , 20); + }); +}); diff --git a/extensions/statistics/js/tsconfig.json b/extensions/statistics/js/tsconfig.json new file mode 100644 index 000000000..207c5b382 --- /dev/null +++ b/extensions/statistics/js/tsconfig.json @@ -0,0 +1,16 @@ +{ + // Use Flarum's tsconfig as a starting point + "extends": "flarum-tsconfig", + // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder + // and also tells your Typescript server to read core's global typings for + // access to `dayjs` and `$` in the global namespace. + "include": ["src/**/*", "../vendor/flarum/core/js/dist-typings/@types/**/*"], + "compilerOptions": { + // This will output typings to `dist-typings` + "declarationDir": "./dist-typings", + "baseUrl": ".", + "paths": { + "flarum/*": ["../vendor/flarum/core/js/dist-typings/*"] + } + } +}