mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
adding new chart system
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
/ui/public
|
|
||||||
/db/
|
|
||||||
/conf/
|
|
||||||
@@ -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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user