Реализация виджета на frontend-е

This commit is contained in:
Pavel Gnedov 2025-02-07 19:12:34 +07:00
parent 77352a497b
commit 8479b6d68d
3 changed files with 152 additions and 1 deletions

View file

@ -24,7 +24,7 @@
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"start": "BROWSER=none react-scripts start --open=false",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"

View file

@ -0,0 +1,146 @@
import React from 'react';
import * as DashboardStoreNs from '../dashboard-store';
import { observer } from 'mobx-react-lite';
import { DebugInfo } from '../../misc-components/debug-info';
import { Instance, onSnapshot, types } from 'mobx-state-tree';
export const DailyEccmV2Data = types.model({
id: types.string,
dashboardId: types.string,
widgetId: types.string,
datetime: types.number,
datetimeFormatted: types.string,
reportIssues: types.array(types.frozen()),
issuesMetrics: types.frozen(),
latest: types.boolean,
});
export const DailyEccmV2Store = types
.model({
data: DailyEccmV2Data,
})
.actions((self) => ({
setData(data: any) {
self.data = data;
},
}));
export type IDailyEccmV2Store = Instance<typeof DailyEccmV2Store>;
export const DailyEccmV2 = observer(
(props: { store: IDailyEccmV2Store }): JSX.Element => {
const dashboardId = props.store?.data?.dashboardId;
const widgetId = props.store?.data?.widgetId;
const keyPrefix = `dashboard-${dashboardId}-widget-${widgetId}`;
const issuesByStatusCount: Record<string, any> =
props.store?.data?.issuesMetrics?.issuesByStatusCount ?? {};
const issuesByVersionsCount: Record<string, any> =
props.store?.data?.issuesMetrics?.issuesByVersionsCount ?? {};
const issuesByUsername: Record<string, any> =
props.store?.data?.issuesMetrics?.issuesByUsername ?? {};
const byStatusLi: JSX.Element[] = [];
Object.keys(issuesByStatusCount).forEach((status) => {
let byStatusHint: JSX.Element;
const byVersion = issuesByStatusCount[status]?.byVersion;
const keyPrefixForCurrentStatusBlock = `${keyPrefix}-issuesByStatusCount-${status}`;
if (byVersion && Object.keys(byVersion).length > 0) {
const byVersionSimple = Object.keys(byVersion).reduce(
(acc: Record<string, number>, version) => {
acc[version] = byVersion[version].count;
return acc;
},
{} as Record<string, number>,
);
byStatusHint = (
<span
key={`${keyPrefixForCurrentStatusBlock}-byVersionHint`}
style={{ marginLeft: '10px', color: 'lightgray' }}
>
(Версии: {JSON.stringify(byVersionSimple)})
</span>
);
} else {
byStatusHint = <></>;
}
byStatusLi.push(
<li key={`${keyPrefixForCurrentStatusBlock}`}>
{status}: {issuesByStatusCount[status].count} {byStatusHint}
</li>,
);
});
const byVersionsLi: JSX.Element[] = [];
Object.keys(issuesByVersionsCount).forEach((version) => {
const byStatus = issuesByVersionsCount[version].byStatus;
const keyPrefixForCurrentVersionBlock = `${keyPrefix}-issuesByVersionsCount-${version}`;
let byStatusHint: JSX.Element = <></>;
if (byStatus && Object.keys(byStatus).length > 0) {
const byStatusSimple = Object.keys(byStatus).reduce((acc, status) => {
acc[status] = byStatus[status].count;
return acc;
}, {} as Record<string, number>);
byStatusHint = (
<span
style={{ marginLeft: '10px', color: 'lightgray' }}
key={`${keyPrefixForCurrentVersionBlock}-byStatusHint`}
>
(Статусы: {JSON.stringify(byStatusSimple)})
</span>
);
}
byVersionsLi.push(
<li key={keyPrefixForCurrentVersionBlock}>
{version}: {issuesByVersionsCount[version].count} {byStatusHint}
</li>,
);
});
return (
<div>
<h1>Daily ECCM V2</h1>
<p>Дата выгрузки: {props.store?.data?.datetimeFormatted}</p>
<p>Метрики:</p>
<ul>
<li>
Простые счётчики:
<ul>
<li>
По статусам:
<ul>{byStatusLi}</ul>
</li>
<li>
По версиям:
<ul>{byVersionsLi}</ul>
</li>
</ul>
</li>
</ul>
<DebugInfo value={JSON.stringify(props.store?.data, null, 2)} />
</div>
);
},
);
export type Props = {
store: DashboardStoreNs.IWidget;
};
export const DailyEccmV2Widget = observer((props: Props): JSX.Element => {
const dailyEccmV2Store = DailyEccmV2Store.create();
onSnapshot(props.store, (storeState) => {
if (storeState.data) {
dailyEccmV2Store.setData(storeState.data);
}
});
return (
<>
<DailyEccmV2 store={dailyEccmV2Store} />
</>
);
});

View file

@ -6,6 +6,7 @@ import * as KanbanWidgetNs from './kanban';
import { DebugInfo } from '../../misc-components/debug-info';
import * as IssuesListNs from './issues-list';
import * as CalendarNextEventsNs from './calendar-next-events';
import * as DailyEccmV2 from './daily-eccm-v2';
export type Props = {
store: Instance<typeof DashboardStoreNs.Widget>;
@ -26,6 +27,10 @@ export const WidgetFactory = observer((props: Props): JSX.Element => {
return <CalendarNextEventsNs.CalendarNextEvents store={props.store} />;
}
if (type === 'daily_eccm_v2') {
return <DailyEccmV2.DailyEccmV2 store={props.store} />;
}
return (
<div>
<div>Unknown widget</div>