adding new chart system

This commit is contained in:
Christian Kellner
2025-09-03 14:22:04 +02:00
parent 29026ccad8
commit f8e0376ddd
8 changed files with 44 additions and 76 deletions

View File

@@ -1,3 +0,0 @@
/ui/public
/db/
/conf/

View File

@@ -6,6 +6,10 @@ import react from 'eslint-plugin-react';
import babelParser from '@babel/eslint-parser'; import babelParser from '@babel/eslint-parser';
export default [ export default [
{
files: ['**/*.{js,jsx,ts,tsx}'],
ignores: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/public/**', 'db/**', 'conf/**'],
},
js.configs.recommended, js.configs.recommended,
prettier, prettier,
{ {
@@ -23,70 +27,34 @@ export default [
after: 'readonly', after: 'readonly',
it: 'readonly', it: 'readonly',
}, },
parserOptions: { parserOptions: { requireConfigFile: false },
requireConfigFile: false,
},
},
plugins: {
react,
}, },
plugins: { react },
rules: { rules: {
eqeqeq: [2, 'allow-null'], eqeqeq: [2, 'allow-null'],
// Semantics / Performance impacting
strict: 0, strict: 0,
'no-redeclare': [2, { builtinGlobals: false }], 'no-redeclare': [2, { builtinGlobals: false }],
'class-methods-use-this': 'off', 'class-methods-use-this': 'off',
// Style
indent: ['off', 2], indent: ['off', 2],
'linebreak-style': ['error', 'unix'], 'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }], quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }],
semi: ['error', 'always'], semi: ['error', 'always'],
'no-console': ['error', { allow: ['warn', 'error'] }], 'no-console': ['error', { allow: ['warn', 'error'] }],
// React
'jsx-quotes': ['error', 'prefer-double'], 'jsx-quotes': ['error', 'prefer-double'],
'react/display-name': 'off', 'react/display-name': 'off',
'react/forbid-prop-types': 'off', 'react/forbid-prop-types': 'off',
'react/jsx-closing-bracket-location': 'off', 'react/jsx-closing-bracket-location': 'off',
'react/jsx-curly-spacing': 'off', 'react/jsx-curly-spacing': 'off',
'react/jsx-handler-names': [ 'react/jsx-handler-names': ['off', { eventHandlerPrefix: 'handle', eventHandlerPropPrefix: 'on' }],
'off',
{
eventHandlerPrefix: 'handle',
eventHandlerPropPrefix: 'on',
},
],
'react/jsx-indent-props': 'off', 'react/jsx-indent-props': 'off',
'react/jsx-key': 'off', 'react/jsx-key': 'off',
'react/jsx-max-props-per-line': 'off', 'react/jsx-max-props-per-line': 'off',
'react/jsx-no-bind': [ 'react/jsx-no-bind': ['error', { ignoreRefs: true, allowArrowFunctions: true, allowBind: false }],
'error',
{
ignoreRefs: true,
allowArrowFunctions: true,
allowBind: false,
},
],
'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }], 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
'react/jsx-no-literals': 'off', 'react/jsx-no-literals': 'off',
'react/jsx-no-undef': 'error', 'react/jsx-no-undef': 'error',
'react/jsx-pascal-case': [ 'react/jsx-pascal-case': ['error', { allowAllCaps: true, ignore: [] }],
'error', 'react/sort-prop-types': ['off', { ignoreCase: true, callbacksLast: false, requiredFirst: false }],
{
allowAllCaps: true,
ignore: [],
},
],
'react/sort-prop-types': [
'off',
{
ignoreCase: true,
callbacksLast: false,
requiredFirst: false,
},
],
'react/jsx-sort-prop-types': 'off', 'react/jsx-sort-prop-types': 'off',
'react/jsx-sort-props': 'off', 'react/jsx-sort-props': 'off',
'react/jsx-uses-react': 'error', 'react/jsx-uses-react': 'error',
@@ -106,14 +74,7 @@ export default [
'react/require-render-return': 'error', 'react/require-render-return': 'error',
'react/self-closing-comp': 'warn', 'react/self-closing-comp': 'warn',
'react/sort-comp': 'off', 'react/sort-comp': 'off',
'react/jsx-wrap-multilines': [ 'react/jsx-wrap-multilines': ['warn', { declaration: true, assignment: true, return: true }],
'warn',
{
declaration: true,
assignment: true,
return: true,
},
],
'react/wrap-multilines': 'off', 'react/wrap-multilines': 'off',
'react/jsx-first-prop-new-line': 'off', 'react/jsx-first-prop-new-line': 'off',
'react/jsx-equals-spacing': ['warn', 'never'], 'react/jsx-equals-spacing': ['warn', 'never'],
@@ -126,20 +87,10 @@ export default [
'react/no-find-dom-node': 'warn', 'react/no-find-dom-node': 'warn',
'react/forbid-component-props': ['off', { forbid: [] }], 'react/forbid-component-props': ['off', { forbid: [] }],
'react/no-danger-with-children': 'error', 'react/no-danger-with-children': 'error',
'react/no-unused-prop-types': [ 'react/no-unused-prop-types': ['warn', { customValidators: [], skipShapeProps: true }],
'warn',
{
customValidators: [],
skipShapeProps: true,
},
],
'react/style-prop-object': 'error', 'react/style-prop-object': 'error',
'react/no-children-prop': 'warn', 'react/no-children-prop': 'warn',
}, },
settings: { settings: { react: { version: 'detect' } },
react: {
version: 'detect',
},
},
}, },
]; ];

View File

@@ -1,6 +1,6 @@
{ {
"name": "fredy", "name": "fredy",
"version": "11.4.4", "version": "11.5.0",
"description": "[F]ind [R]eal [E]states [d]amn eas[y].", "description": "[F]ind [R]eal [E]states [d]amn eas[y].",
"scripts": { "scripts": {
"prepare": "husky", "prepare": "husky",

View File

@@ -8,4 +8,4 @@ export function format(ts) {
second: 'numeric', second: 'numeric',
}).format(ts); }).format(ts);
} }
export const roundToNext5Minute = (ts) => Math.ceil(ts / (1000 * 60 * 5)) * (1000 * 60 * 5); export const roundToHour = (ts) => Math.ceil(ts / (1000 * 60 * 60)) * (1000 * 60 * 60);

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { roundToNext5Minute } from '../../../services/time/timeService'; import { roundToHour } from '../../../services/time/timeService';
import Headline from '../../../components/headline/Headline'; import Headline from '../../../components/headline/Headline';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
@@ -26,14 +26,13 @@ const JobInsight = function JobInsight() {
const allTimes = new Set(); const allTimes = new Set();
const cap = (s) => (s ? s[0].toUpperCase() + s.slice(1) : 'Unknown'); const cap = (s) => (s ? s[0].toUpperCase() + s.slice(1) : 'Unknown');
const toDate = (ts) => new Date(ts < 1e12 ? ts * 1000 : ts); // seconds vs ms
providers.forEach((key) => { providers.forEach((key) => {
const providerName = cap(key); const providerName = cap(key);
const tmpTimeObj = {}; const tmpTimeObj = {};
Object.values(data[key] || {}).forEach((listingTs) => { Object.values(data[key] || {}).forEach((listingTs) => {
const time = roundToNext5Minute(listingTs); const time = roundToHour(listingTs);
tmpTimeObj[time] = tmpTimeObj[time] == null ? 1 : tmpTimeObj[time] + 1; tmpTimeObj[time] = tmpTimeObj[time] == null ? 1 : tmpTimeObj[time] + 1;
allTimes.add(time); allTimes.add(time);
}); });
@@ -50,15 +49,20 @@ const JobInsight = function JobInsight() {
sortedTimes.forEach((t) => { sortedTimes.forEach((t) => {
result.push({ result.push({
listings: Number(t), // Date object for time axis listings: new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
}).format(new Date(parseInt(t))),
listingsNumber: bucket[t] || 0, // y value listingsNumber: bucket[t] || 0, // y value
provider: providerName, // series key provider: providerName, // series key
}); });
}); });
}); });
console.log(result);
return result; return result;
}; };

View File

@@ -11,6 +11,21 @@ const commonSpec = {
yField: 'listingsNumber', yField: 'listingsNumber',
seriesField: 'provider', seriesField: 'provider',
legends: { visible: true }, legends: { visible: true },
line: {
style: {
lineWidth: 2,
},
},
point: {
visible: false,
},
axes: [
{
orient: 'bottom',
field: 'listings',
zero: false,
},
],
}; };
const Linechart = function Linechart({ title, series, isLoading = false }) { const Linechart = function Linechart({ title, series, isLoading = false }) {
@@ -28,7 +43,6 @@ const Linechart = function Linechart({ title, series, isLoading = false }) {
}, },
data: { values: series }, data: { values: series },
}} }}
option={{ mode: 'desktop-browser' }}
/> />
)} )}
</Placeholder> </Placeholder>

View File

@@ -30,7 +30,8 @@ export default function ProviderMutator({ onVisibilityChanged, visible = false,
if (selectedProvider.baseUrl.indexOf(url.origin) === -1) { if (selectedProvider.baseUrl.indexOf(url.origin) === -1) {
return 'The url you have copied is not valid.'; return 'The url you have copied is not valid.';
} }
} catch (Exception) { /* eslint-disable no-unused-vars */
} catch (ignored) {
return 'The url you have copied is not valid.'; return 'The url you have copied is not valid.';
} }
return null; return null;

View File

@@ -38,7 +38,8 @@ export default function Login() {
username: username.trim(), username: username.trim(),
password, password,
}); });
} catch (Exception) { /* eslint-disable no-unused-vars */
} catch (ignored) {
Toast.error('Login unsuccessful…'); Toast.error('Login unsuccessful…');
return; return;
} }