= ({ moveTab, index, title, id, onClic
{tab.type === 'person' && ()}
{tab.type === 'borrow' && ()}
{tab.type === 'settings' && ()}
+ {tab.type === 'dashboard' && ()}
diff --git a/src/app/components/Tabs/index.tsx b/src/app/components/Tabs/index.tsx
index ef5eac4..e4887f2 100644
--- a/src/app/components/Tabs/index.tsx
+++ b/src/app/components/Tabs/index.tsx
@@ -4,9 +4,6 @@ import React, {
useMemo,
useState,
useRef,
- MutableRefObject,
- Ref,
- RefObject,
} from 'react';
import { on, off } from '../../util/EventHandler';
import { v4 } from 'uuid';
@@ -20,6 +17,7 @@ import Borrow from '../Borrow';
import Title from '../Title';
import Person from '../Person';
import Settings from '../Settings';
+import Dashboard from '../Dashboard';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
@@ -47,7 +45,6 @@ const Tabs: React.FC = () => {
const [, setAction] = useState('list');
const globalSave = useRef(null);
-
const lastTab = useCallback((): Tab => {
return tabItems[tabItems.length - 1];
}, [tabItems]);
@@ -166,6 +163,10 @@ const Tabs: React.FC = () => {
handleCreateTab('settings', Actions.update, {});
}, [handleCreateTab]);
+ const dashboardTab = useCallback(() => {
+ handleCreateTab('dashboard', Actions.create, {});
+ }, [handleCreateTab]);
+
const quickSearch = useCallback(() => {
setOpen((oldState) => !oldState);
}, []);
@@ -184,6 +185,7 @@ const Tabs: React.FC = () => {
{ event: 'titleTab', handler: titleTab },
{ event: 'settingsTab', handler: settingsTab },
{ event: 'quickSearch', handler: quickSearch },
+ { event: 'dashboardTab', handler: dashboardTab },
{ event: 'save', handler: save },
],
[
@@ -193,6 +195,7 @@ const Tabs: React.FC = () => {
titleTab,
settingsTab,
quickSearch,
+ dashboardTab,
save,
]
);
@@ -281,6 +284,9 @@ const Tabs: React.FC = () => {
{tab.type === 'settings' && (
)}
+ {tab.type === 'dashboard' && (
+
+ )}
)
)}
diff --git a/src/app/util/AppEventHandler.ts b/src/app/util/AppEventHandler.ts
index fb68c78..15c595f 100644
--- a/src/app/util/AppEventHandler.ts
+++ b/src/app/util/AppEventHandler.ts
@@ -18,6 +18,7 @@ export default class {
registerCallbacks(): void {
window.api.on(AppEvent.languageChange, this.languageChange.bind(this));
+ this.forward(AppEvent.dashboardTab);
this.forward(AppEvent.borrowTab);
this.forward(AppEvent.personTab);
this.forward(AppEvent.titleTab);
diff --git a/src/common/AppEvent.ts b/src/common/AppEvent.ts
index a929eae..c53588f 100644
--- a/src/common/AppEvent.ts
+++ b/src/common/AppEvent.ts
@@ -1,5 +1,6 @@
export enum AppEvent {
languageChange = 'languageChange',
+ dashboardTab = 'dashboardTab',
borrowTab = 'borrowTab',
personTab = 'personTab',
titleTab = 'titleTab',
diff --git a/src/electron/Main.ts b/src/electron/Main.ts
index 481615a..201c360 100644
--- a/src/electron/Main.ts
+++ b/src/electron/Main.ts
@@ -18,6 +18,7 @@ import I18NextAdapter from './infra/i18n/I18NextAdapter';
import I18nAdapter from './data/protocols/I18n/I18n';
import Resource from './data/protocols/Resource/Resource';
import EntitiesConfigs from './database/EntitiesConfigs';
+import { Repository } from './data/protocols';
export default class Main {
private connection: Connection;
@@ -105,8 +106,15 @@ export default class Main {
listener.listenerName,
async (event: IpcMainEvent, content: Event[]) => {
try {
+ let repository: Repository;
+ if (content[0] === undefined) {
+ repository = repositoryFactory.make(listener.repositoryName);
+ event.returnValue = await repository.execute();
+ return;
+ }
+
const { value, entity } = content[0];
- const repository = repositoryFactory.make(
+ repository = repositoryFactory.make(
listener.repositoryName,
entity
);
diff --git a/src/electron/data/protocols/Menu/MenuActionHandler.ts b/src/electron/data/protocols/Menu/MenuActionHandler.ts
index 04203d0..788b5d7 100644
--- a/src/electron/data/protocols/Menu/MenuActionHandler.ts
+++ b/src/electron/data/protocols/Menu/MenuActionHandler.ts
@@ -3,6 +3,7 @@ import { BrowserWindow, MenuItem } from 'electron';
type ElectronWindow = BrowserWindow | undefined;
export interface MenuActionHandler {
+ showDashboard: (menuItem: MenuItem, win: ElectronWindow) => void;
newBorrow: (menuItem: MenuItem, win: ElectronWindow) => void;
newPerson: (menuItem: MenuItem, win: ElectronWindow) => void;
newTitle: (menuItem: MenuItem, win: ElectronWindow) => void;
diff --git a/src/electron/data/protocols/db/Repository.ts b/src/electron/data/protocols/db/Repository.ts
index 9aa2bf2..b1e7dfc 100644
--- a/src/electron/data/protocols/db/Repository.ts
+++ b/src/electron/data/protocols/db/Repository.ts
@@ -5,5 +5,5 @@ import typeORM from 'typeorm';
export interface Repository {
repository: typeORM.Repository;
getInstance(): RepositoryBase;
- execute(content: unknown): Promise;
+ execute(content?: unknown): Promise;
}
diff --git a/src/electron/infra/db/RepositoryBase.ts b/src/electron/infra/db/RepositoryBase.ts
index 880f334..39ed955 100644
--- a/src/electron/infra/db/RepositoryBase.ts
+++ b/src/electron/infra/db/RepositoryBase.ts
@@ -10,7 +10,7 @@ export default class RepositoryBase implements Repository {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- public async execute(content: unknown): Promise {
+ public async execute(content?: unknown): Promise {
throw new Error('Must be implemented on children classes.');
}
}
diff --git a/src/electron/infra/db/factories/RepositoryFactory.ts b/src/electron/infra/db/factories/RepositoryFactory.ts
index 15f34b4..3f88ae7 100644
--- a/src/electron/infra/db/factories/RepositoryFactory.ts
+++ b/src/electron/infra/db/factories/RepositoryFactory.ts
@@ -20,7 +20,12 @@ export default class RepositoryFactory {
});
}
- public make(repository: string, entity: string): Repository {
+ public make(repository: string, entity?: string): Repository {
+ if (!entity) {
+ const dynamicRepository = this.products[repository].getInstance();
+ return dynamicRepository;
+ }
+
const typeOrmRepository = this.connection.getRepository(entity);
const dynamicRepository = this.products[repository].getInstance(typeOrmRepository);
diff --git a/src/electron/infra/db/repositories/dashboard/ActiveBorrowsRepository.ts b/src/electron/infra/db/repositories/dashboard/ActiveBorrowsRepository.ts
new file mode 100644
index 0000000..86a23fe
--- /dev/null
+++ b/src/electron/infra/db/repositories/dashboard/ActiveBorrowsRepository.ts
@@ -0,0 +1,35 @@
+import { getConnection } from 'typeorm';
+import RepositoryBase from '../../RepositoryBase';
+
+export class ActiveBorrowsRepository extends RepositoryBase {
+ private static instance: ActiveBorrowsRepository = null;
+
+ static repositoryName = 'ActiveBorrows';
+
+ private constructor() {
+ super();
+ this.repository = getConnection().getRepository('Borrow');
+ }
+
+ public static getInstance(): ActiveBorrowsRepository {
+ if (!ActiveBorrowsRepository.instance) {
+ ActiveBorrowsRepository.instance = new ActiveBorrowsRepository();
+ }
+
+ return ActiveBorrowsRepository.instance;
+ }
+
+ public async execute(): Promise {
+ try {
+ return await this.repository.count({
+ where: {
+ returnedAt: null,
+ isReservation: false,
+ },
+ });
+ } catch (err) {
+ console.log(err);
+ throw err;
+ }
+ }
+}
diff --git a/src/electron/infra/db/repositories/dashboard/OverdueBorrowsRepository.ts b/src/electron/infra/db/repositories/dashboard/OverdueBorrowsRepository.ts
new file mode 100644
index 0000000..24b9d83
--- /dev/null
+++ b/src/electron/infra/db/repositories/dashboard/OverdueBorrowsRepository.ts
@@ -0,0 +1,38 @@
+import RepositoryBase from '../../RepositoryBase';
+import { getConnection, LessThan } from 'typeorm';
+import { DateUtils } from 'typeorm/util/DateUtils';
+
+export class OverdueBorrowsRepository extends RepositoryBase {
+ private static instance: OverdueBorrowsRepository = null;
+
+ static repositoryName = 'OverdueBorrows';
+
+ private constructor() {
+ super();
+ this.repository = getConnection().getRepository('Borrow');
+ }
+
+ public static getInstance(): OverdueBorrowsRepository {
+ if (!OverdueBorrowsRepository.instance) {
+ OverdueBorrowsRepository.instance = new OverdueBorrowsRepository();
+ }
+ return OverdueBorrowsRepository.instance;
+ }
+
+ public async execute(): Promise {
+ try {
+ return await this.repository.count({
+ where: {
+ returnedAt: null,
+ estimatedReturn: LessThan(
+ DateUtils.mixedDateToUtcDatetimeString(new Date())
+ ),
+ isReservation: false,
+ },
+ });
+ } catch (err) {
+ console.log(err);
+ throw err;
+ }
+ }
+}
diff --git a/src/electron/infra/db/repositories/dashboard/RegisteredPeopleRepository.ts b/src/electron/infra/db/repositories/dashboard/RegisteredPeopleRepository.ts
new file mode 100644
index 0000000..e31134c
--- /dev/null
+++ b/src/electron/infra/db/repositories/dashboard/RegisteredPeopleRepository.ts
@@ -0,0 +1,30 @@
+import RepositoryBase from '../../RepositoryBase';
+import { getConnection } from 'typeorm';
+
+export class RegisteredPeopleRepository extends RepositoryBase {
+ private static instance: RegisteredPeopleRepository = null;
+
+ static repositoryName = 'RegisteredPeople';
+
+ private constructor() {
+ super();
+ this.repository = getConnection().getRepository('User');
+ }
+
+ public static getInstance(): RegisteredPeopleRepository {
+ if (!RegisteredPeopleRepository.instance) {
+ RegisteredPeopleRepository.instance = new RegisteredPeopleRepository();
+ }
+
+ return RegisteredPeopleRepository.instance;
+ }
+
+ public async execute(): Promise {
+ try {
+ return await this.repository.count();
+ } catch (err) {
+ console.log(err);
+ throw err;
+ }
+ }
+}
diff --git a/src/electron/infra/db/repositories/dashboard/RegisteredSamplesRepository.ts b/src/electron/infra/db/repositories/dashboard/RegisteredSamplesRepository.ts
new file mode 100644
index 0000000..1eaa7b6
--- /dev/null
+++ b/src/electron/infra/db/repositories/dashboard/RegisteredSamplesRepository.ts
@@ -0,0 +1,30 @@
+import RepositoryBase from '../../RepositoryBase';
+import { getConnection } from 'typeorm';
+
+export class RegisteredSamplesRepository extends RepositoryBase {
+ private static instance: RegisteredSamplesRepository = null;
+
+ static repositoryName = 'RegisteredSamples';
+
+ private constructor() {
+ super();
+ this.repository = getConnection().getRepository('TitlePublisher');
+ }
+
+ public static getInstance(): RegisteredSamplesRepository {
+ if (!RegisteredSamplesRepository.instance) {
+ RegisteredSamplesRepository.instance = new RegisteredSamplesRepository();
+ }
+
+ return RegisteredSamplesRepository.instance;
+ }
+
+ public async execute(): Promise {
+ try {
+ return await this.repository.count();
+ } catch (err) {
+ console.log(err);
+ throw err;
+ }
+ }
+}
diff --git a/src/electron/infra/db/repositories/index.ts b/src/electron/infra/db/repositories/index.ts
index 01cf22b..03ae29f 100644
--- a/src/electron/infra/db/repositories/index.ts
+++ b/src/electron/infra/db/repositories/index.ts
@@ -23,3 +23,7 @@ export * from './user/ChangePasswordRepository';
export * from './user/UserCreateRepository';
export * from './user/UserLoginRepository';
export * from './user/UserUpdateRepository';
+export * from './dashboard/RegisteredSamplesRepository';
+export * from './dashboard/RegisteredPeopleRepository';
+export * from './dashboard/ActiveBorrowsRepository';
+export * from './dashboard/OverdueBorrowsRepository';
diff --git a/src/electron/infra/listeners/ListenersConfigs.ts b/src/electron/infra/listeners/ListenersConfigs.ts
index d6fcfde..a901010 100644
--- a/src/electron/infra/listeners/ListenersConfigs.ts
+++ b/src/electron/infra/listeners/ListenersConfigs.ts
@@ -39,6 +39,11 @@ export default class ListenersConfigs {
{ listenerName: 'changePassword', repositoryName: 'ChangePassword' },
{ listenerName: 'globalSearch', repositoryName: 'GlobalSearch' },
+
+ { listenerName: 'regiteredSamples', repositoryName: 'RegisteredSamples' },
+ { listenerName: 'regiteredPeople', repositoryName: 'RegisteredPeople' },
+ { listenerName: 'overdueBorrows', repositoryName: 'OverdueBorrows' },
+ { listenerName: 'activeBorrows', repositoryName: 'ActiveBorrows' },
];
return products;
diff --git a/src/electron/infra/menu/DefaultMenu.ts b/src/electron/infra/menu/DefaultMenu.ts
index 3eb3940..c7ce47e 100644
--- a/src/electron/infra/menu/DefaultMenu.ts
+++ b/src/electron/infra/menu/DefaultMenu.ts
@@ -16,6 +16,12 @@ export default class DefaultMenu implements MenuBuildTemplate {
{
label: this.i18nAdapter.translate('menu.file.label'),
submenu: [
+ {
+ label: this.i18nAdapter.translate('menu.file.showDashboard'),
+ accelerator: 'Ctrl+D',
+ click: this.actionHandler.showDashboard,
+ },
+ { type: 'separator' },
{
label: this.i18nAdapter.translate('menu.file.newBorrow'),
accelerator: 'Ctrl+B',
diff --git a/src/electron/infra/menu/NativeMenuActionHandler.ts b/src/electron/infra/menu/NativeMenuActionHandler.ts
index 5f211af..97e7104 100644
--- a/src/electron/infra/menu/NativeMenuActionHandler.ts
+++ b/src/electron/infra/menu/NativeMenuActionHandler.ts
@@ -16,6 +16,12 @@ export default class NativeMenuActionHandlers implements MenuActionHandler {
this.showLogs = this.showLogs.bind(this);
}
+ public showDashboard(_menuItem: MenuItem, win: ElectronWindow): void {
+ if (win) {
+ win.webContents.send(AppEvent.dashboardTab);
+ }
+ }
+
public newBorrow(_menuItem: MenuItem, win: ElectronWindow): void {
if (win) {
win.webContents.send(AppEvent.borrowTab, actionCreate);
diff --git a/src/locales/en-US/common.json b/src/locales/en-US/common.json
index 114e6a2..8234b9f 100644
--- a/src/locales/en-US/common.json
+++ b/src/locales/en-US/common.json
@@ -4,6 +4,7 @@
"menu": {
"file": {
"label": "&File",
+ "showDashboard": "Show Dashboard",
"newBorrow": "New Borrow",
"newPerson": "New Person",
"newTitle": "New Title",
@@ -62,6 +63,13 @@
"of": "of",
"itemsPerPage": "Items per page"
},
+ "dashboard": {
+ "label": "Dashboard",
+ "overdueBorrows": "Overdue borrows",
+ "activeBorrows": "Active borrows",
+ "registeredSamples": "Registered samples",
+ "registeredPeople": "Registered People"
+ },
"borrow": {
"label": "Borrow",
"borrow": "Borrow",
diff --git a/src/locales/pt-BR/common.json b/src/locales/pt-BR/common.json
index 2637a8a..580e18f 100644
--- a/src/locales/pt-BR/common.json
+++ b/src/locales/pt-BR/common.json
@@ -4,6 +4,7 @@
"menu": {
"file": {
"label": "&Arquivo",
+ "showDashboard": "Exibir o Dashboard",
"newBorrow": "Novo Empréstimo",
"newPerson": "Nova Pessoa",
"newTitle": "Novo Título",
@@ -62,6 +63,13 @@
"of": "de",
"itemsPerPage": "Itens por página"
},
+ "dashboard": {
+ "label": "Dashboard",
+ "overdueBorrows": "Empréstimos atrasados",
+ "activeBorrows": "Empréstimos ativos",
+ "registeredSamples": "Exemplares cadastrados",
+ "registeredPeople": "Pessoas cadastradas"
+ },
"borrow": {
"label": "Empréstimo",
"borrow": "Empréstimo",
diff --git a/yarn.lock b/yarn.lock
index 4282e30..7c23891 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1012,6 +1012,13 @@
"@babel/helper-validator-option" "^7.16.7"
"@babel/plugin-transform-typescript" "^7.16.7"
+"@babel/runtime@^7.1.2":
+ version "7.18.9"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
+ integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.16.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5"
@@ -3532,6 +3539,11 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
+classnames@^2.2.5:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
+ integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
+
clean-css@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d"
@@ -4084,6 +4096,11 @@ css-to-react-native@^3.0.0:
css-color-keywords "^1.0.0"
postcss-value-parser "^4.0.2"
+css-unit-converter@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
+ integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==
+
css-what@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe"
@@ -4128,6 +4145,67 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
+"d3-array@2 - 3", "d3-array@2.10.0 - 3":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.0.tgz#15bf96cd9b7333e02eb8de8053d78962eafcff14"
+ integrity sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==
+ dependencies:
+ internmap "1 - 2"
+
+"d3-color@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
+ integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
+
+"d3-format@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641"
+ integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
+
+"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
+ integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
+ dependencies:
+ d3-color "1 - 3"
+
+"d3-path@1 - 3":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e"
+ integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==
+
+d3-scale@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396"
+ integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==
+ dependencies:
+ d3-array "2.10.0 - 3"
+ d3-format "1 - 3"
+ d3-interpolate "1.2.0 - 3"
+ d3-time "2.1.1 - 3"
+ d3-time-format "2 - 4"
+
+d3-shape@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556"
+ integrity sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==
+ dependencies:
+ d3-path "1 - 3"
+
+"d3-time-format@2 - 4":
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a"
+ integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
+ dependencies:
+ d3-time "1 - 3"
+
+"d3-time@1 - 3", "d3-time@2.1.1 - 3":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975"
+ integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==
+ dependencies:
+ d3-array "2 - 3"
+
dargs@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc"
@@ -4193,6 +4271,11 @@ decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+decimal.js-light@^2.4.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934"
+ integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==
+
decimal.js@^10.2.1:
version "10.3.1"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
@@ -4414,6 +4497,13 @@ dom-converter@^0.2.0:
dependencies:
utila "~0.4"
+dom-helpers@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
+ integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
@@ -4990,7 +5080,7 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
-eventemitter3@^4.0.0:
+eventemitter3@^4.0.0, eventemitter3@^4.0.1:
version "4.0.7"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
@@ -5148,6 +5238,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+fast-equals@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-2.0.4.tgz#3add9410585e2d7364c2deeb6a707beadb24b927"
+ integrity sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w==
+
fast-glob@^3.1.1:
version "3.2.7"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
@@ -6282,6 +6377,11 @@ internal-slot@^1.0.3:
has "^1.0.3"
side-channel "^1.0.4"
+"internmap@1 - 2":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
+ integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
+
ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@@ -7404,7 +7504,7 @@ lodash.truncate@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
-lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
+lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -8956,7 +9056,7 @@ react-icons@^4.3.1:
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca"
integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==
-react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
+react-is@^16.10.2, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, 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==
@@ -8966,7 +9066,7 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
-react-lifecycles-compat@^3.0.0:
+react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
@@ -8981,6 +9081,13 @@ react-modal@^3.14.4:
react-lifecycles-compat "^3.0.0"
warning "^4.0.3"
+react-resize-detector@^7.1.2:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-7.1.2.tgz#8ef975dd8c3d56f9a5160ac382ef7136dcd2d86c"
+ integrity sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw==
+ dependencies:
+ lodash "^4.17.21"
+
react-router-dom@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.1.tgz#32ec81829152fbb8a7b045bf593a22eadf019bec"
@@ -9009,6 +9116,14 @@ react-select@^5.2.1:
prop-types "^15.6.0"
react-transition-group "^4.3.0"
+react-smooth@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.1.tgz#74c7309916d6ccca182c4b30c8992f179e6c5a05"
+ integrity sha512-Own9TA0GPPf3as4vSwFhDouVfXP15ie/wIHklhyKBH5AN6NFtdk0UpHBnonV11BtqDkAWlt40MOUc+5srmW7NA==
+ dependencies:
+ fast-equals "^2.0.0"
+ react-transition-group "2.9.0"
+
react-spinners-kit@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/react-spinners-kit/-/react-spinners-kit-1.9.1.tgz#516a7de8e80702def006be481062382ab3c38066"
@@ -9037,6 +9152,16 @@ react-table@^7.7.0:
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.7.0.tgz#e2ce14d7fe3a559f7444e9ecfe8231ea8373f912"
integrity sha512-jBlj70iBwOTvvImsU9t01LjFjy4sXEtclBovl3mTiqjz23Reu0DKnRza4zlLtOPACx6j2/7MrQIthIK1Wi+LIA==
+react-transition-group@2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
+ integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==
+ dependencies:
+ dom-helpers "^3.4.0"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+ react-lifecycles-compat "^3.0.4"
+
react-transition-group@^4.3.0:
version "4.4.2"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
@@ -9173,6 +9298,30 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
+recharts-scale@^0.4.4:
+ version "0.4.5"
+ resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9"
+ integrity sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==
+ dependencies:
+ decimal.js-light "^2.4.1"
+
+recharts@^2.1.13:
+ version "2.1.13"
+ resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.1.13.tgz#61801acf3e13896b07dc6a8b38cbdd648480d0b7"
+ integrity sha512-9VWu2nzExmfiMFDHKqRFhYlJVmjzQGVKH5rBetXR4EuyEXuu3Y6cVxQuNEdusHhbm4SoPPrVDCwlBdREL3sQPA==
+ dependencies:
+ classnames "^2.2.5"
+ d3-interpolate "^3.0.1"
+ d3-scale "^4.0.2"
+ d3-shape "^3.1.0"
+ eventemitter3 "^4.0.1"
+ lodash "^4.17.19"
+ react-is "^16.10.2"
+ react-resize-detector "^7.1.2"
+ react-smooth "^2.0.1"
+ recharts-scale "^0.4.4"
+ reduce-css-calc "^2.1.8"
+
redent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -9189,6 +9338,14 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
+reduce-css-calc@^2.1.8:
+ version "2.1.8"
+ resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03"
+ integrity sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==
+ dependencies:
+ css-unit-converter "^1.1.1"
+ postcss-value-parser "^3.3.0"
+
redux@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104"