Добавлены все виджеты на дашборд

This commit is contained in:
Pavel Gnedov 2023-11-03 20:18:22 +07:00
parent ae14189cd3
commit a756677c89
11 changed files with 70 additions and 29 deletions

View file

@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import { Instance, types } from 'mobx-state-tree'; import { IAnyModelType, Instance, types } from 'mobx-state-tree';
type _WidgetParams = Record<string, any> | null; type _WidgetParams = Record<string, any> | null;
@ -20,6 +20,7 @@ export const Widget = types
dataLoaderParams: types.maybe(DataLoaderParams), dataLoaderParams: types.maybe(DataLoaderParams),
loaded: false, loaded: false,
data: types.maybe(types.frozen<any>()), data: types.maybe(types.frozen<any>()),
dashboardId: types.maybe(types.string),
}) })
.actions((self) => { .actions((self) => {
return { return {
@ -36,6 +37,9 @@ export const Widget = types
self.loaded = true; self.loaded = true;
self.data = data; self.data = data;
}, },
setDashboardId: (dashboardId: string) => {
self.dashboardId = dashboardId;
},
}; };
}); });
@ -49,8 +53,6 @@ export function createWidgetStore(
widgetParams?: _WidgetParams, widgetParams?: _WidgetParams,
dataLoaderParams?: _DataLoaderParams, dataLoaderParams?: _DataLoaderParams,
): IWidget { ): IWidget {
// eslint-disable-next-line prefer-rest-params
console.debug('init new Widget store, params:', arguments);
return Widget.create({ return Widget.create({
id: id, id: id,
type: type, type: type,
@ -76,7 +78,6 @@ export const Dashboard = types
.actions((self) => { .actions((self) => {
return { return {
setData: (data: any) => { setData: (data: any) => {
console.debug('Dashboard store new data:', data); // DEBUG
if (data.widgets) { if (data.widgets) {
for (let i = 0; i < data.widgets.length; i++) { for (let i = 0; i < data.widgets.length; i++) {
const widget = data.widgets[i]; const widget = data.widgets[i];
@ -112,10 +113,8 @@ export const Dashboard = types
export type IDashboard = Instance<typeof Dashboard>; export type IDashboard = Instance<typeof Dashboard>;
export async function DashboardLoadData(store: IDashboard): Promise<void> { export async function DashboardLoadData(store: IDashboard): Promise<void> {
console.debug('DashboardLoadData store:', store); // DEBUG
const url = `${process.env.REACT_APP_BACKEND}api/dashboard/${store.id}`; const url = `${process.env.REACT_APP_BACKEND}api/dashboard/${store.id}`;
const resp = await axios.get(url); const resp = await axios.get(url);
console.debug('DashboardLoadData resp:', resp); // DEBUG
if (!resp.data) return; if (!resp.data) return;
store.setData(resp.data); store.setData(resp.data);
} }
@ -141,3 +140,15 @@ export async function LoadDataForWidget(
} }
return; return;
} }
export async function WidgetLoadData(widget: IWidget): Promise<void> {
if (!widget.dashboardId) return;
const url = `${process.env.REACT_APP_BACKEND}api/dashboard/${widget.dashboardId}/load-data/${widget.id}`;
const resp = await fetch(url);
if (resp && resp.ok) {
const data = await resp.json();
if (data?.data) {
widget.setData(data?.data);
}
}
}

View file

@ -3,7 +3,6 @@ import React from 'react';
import * as DashboardStoreNs from './dashboard-store'; import * as DashboardStoreNs from './dashboard-store';
import * as TopRightMenuNs from '../misc-components/top-right-menu'; import * as TopRightMenuNs from '../misc-components/top-right-menu';
import * as WidgetNs from './widget'; import * as WidgetNs from './widget';
import { DebugInfo } from '../misc-components/debug-info';
export type Props = { store: DashboardStoreNs.IDashboard }; export type Props = { store: DashboardStoreNs.IDashboard };
@ -13,11 +12,10 @@ export const Dashboard = observer((props: Props): JSX.Element => {
return <pre>Loading... {JSON.stringify(props.store)}</pre>; return <pre>Loading... {JSON.stringify(props.store)}</pre>;
} }
const debugInfo = JSON.stringify(props.store, null, ' ');
const topRightMenuStore = TopRightMenuNs.Store.create({ visible: false }); const topRightMenuStore = TopRightMenuNs.Store.create({ visible: false });
const widgets = props.store.data?.widgets.map((widget) => { const widgets = props.store.data?.widgets.map((widget) => {
widget.setDashboardId(props.store.id);
return <WidgetNs.Widget key={widget.id} store={widget}></WidgetNs.Widget>; return <WidgetNs.Widget key={widget.id} store={widget}></WidgetNs.Widget>;
}); });
@ -28,7 +26,6 @@ export const Dashboard = observer((props: Props): JSX.Element => {
<span>Дашборд - {props.store.data?.title || props.store.id}</span> <span>Дашборд - {props.store.data?.title || props.store.id}</span>
</TopRightMenuNs.TopRightMenu> </TopRightMenuNs.TopRightMenu>
{widgets} {widgets}
<DebugInfo value={debugInfo} />
</div> </div>
); );

View file

@ -79,13 +79,22 @@ export type Props = {
* } * }
*/ */
function onWidgetVisibleToggleClick(store: DashboardStoreNs.IWidget): void {
if (!store.loaded && store.dashboardId) {
DashboardStoreNs.WidgetLoadData(store);
}
store.toggle();
}
export const Widget = observer((props: Props): JSX.Element => { export const Widget = observer((props: Props): JSX.Element => {
const display = props.store.visible ? 'block' : 'none'; const display = props.store.visible ? 'block' : 'none';
return ( return (
<div> <div>
<div> <div>
<button onClick={() => props.store.toggle()}>Show/hide</button> <button onClick={() => onWidgetVisibleToggleClick(props.store)}>
Show/hide
</button>
<span>Title - {props.store.title}</span> <span>Title - {props.store.title}</span>
</div> </div>
<div style={{ display: display }}> <div style={{ display: display }}>

View file

@ -0,0 +1,18 @@
import { observer } from 'mobx-react-lite';
import React from 'react';
import * as DashboardStoreNs from '../dashboard-store';
import * as IssuesListBoardsNs from '../../issues-list-board/issues-list-boards';
import * as IssuesListBoardsStoreNs from '../../issues-list-board/store';
import { onSnapshot } from 'mobx-state-tree';
export type Props = {
store: DashboardStoreNs.IWidget;
};
export const IssuesList = observer((props: Props): JSX.Element => {
const store = IssuesListBoardsStoreNs.PageStore.create({ loaded: false });
onSnapshot(props.store, (state) => {
if (state?.data?.data) store.setData(state?.data?.data);
});
return <IssuesListBoardsNs.IssuesListBoards store={store} />;
});

View file

@ -8,10 +8,10 @@ export type Props = {
store: Instance<typeof DashboardStoreNs.Widget>; store: Instance<typeof DashboardStoreNs.Widget>;
}; };
export const KanbanByTree = observer((props: Props): JSX.Element => { export const Kanban = observer((props: Props): JSX.Element => {
const store = KanbanBoardsStoreNs.PageStore.create({ loaded: false }); const store = KanbanBoardsStoreNs.PageStore.create({ loaded: false });
onSnapshot(props.store, (state) => { onSnapshot(props.store, (state) => {
store.setData(state.data.data); if (state?.data?.data) store.setData(state?.data?.data);
}); });
return <KanbanBoardsNs.KanbanBoards store={store} />; return <KanbanBoardsNs.KanbanBoards store={store} />;
}); });

View file

@ -2,8 +2,9 @@ import React from 'react';
import * as DashboardStoreNs from '../dashboard-store'; import * as DashboardStoreNs from '../dashboard-store';
import { Instance } from 'mobx-state-tree'; import { Instance } from 'mobx-state-tree';
import { observer } from 'mobx-react-lite'; import { observer } from 'mobx-react-lite';
import * as KanbanByTreeWidgetNs from './kanban-by-tree'; import * as KanbanWidgetNs from './kanban';
import { DebugInfo } from '../../misc-components/debug-info'; import { DebugInfo } from '../../misc-components/debug-info';
import * as IssuesListNs from './issues-list';
export type Props = { export type Props = {
store: Instance<typeof DashboardStoreNs.Widget>; store: Instance<typeof DashboardStoreNs.Widget>;
@ -12,15 +13,18 @@ export type Props = {
export const WidgetFactory = observer((props: Props): JSX.Element => { export const WidgetFactory = observer((props: Props): JSX.Element => {
const type = props.store.type; const type = props.store.type;
switch (type) { if (type.startsWith('kanban_by_')) {
case 'kanban_by_tree': return <KanbanWidgetNs.Kanban store={props.store} />;
return <KanbanByTreeWidgetNs.KanbanByTree store={props.store} />; }
default:
if (type.startsWith('issues_list_')) {
return <IssuesListNs.IssuesList store={props.store} />;
}
return ( return (
<div> <div>
<div>Unknown widget</div> <div>Unknown widget</div>
<DebugInfo value={JSON.stringify(props.store, null, ' ')} /> <DebugInfo value={JSON.stringify(props.store, null, ' ')} />
</div> </div>
); );
}
}); });

View file

@ -64,7 +64,7 @@ export const IssuesListCard = observer((props: Props): JSX.Element => {
<span className={Css.timeBox}>{props.store.status.name}</span> <span className={Css.timeBox}>{props.store.status.name}</span>
<span> </span> <span> </span>
<span className={Css.priorityBox} style={priorityStyle}> <span className={Css.priorityBox} style={priorityStyle}>
{props.store.priority.name} {props.store?.priority?.name}
</span> </span>
</div> </div>
</div> </div>

View file

@ -30,9 +30,9 @@ export type IBoardStore = Instance<typeof BoardStore>;
export const PageStore = types export const PageStore = types
.model({ .model({
loaded: types.boolean, loaded: false,
type: types.string, type: '',
name: types.string, name: '',
data: types.maybeNull(types.array(BoardStore)), data: types.maybeNull(types.array(BoardStore)),
}) })
.actions((self) => { .actions((self) => {

View file

@ -60,6 +60,7 @@ export const PageStore = types
.actions((self) => { .actions((self) => {
return { return {
setData: (data: any) => { setData: (data: any) => {
console.debug('Kanban page store new data -', data); // DEBUG
self.data = data; self.data = data;
self.loaded = true; self.loaded = true;
}, },

View file

@ -13,6 +13,7 @@ const formatStringToCamelCase = (str: string): string => {
export const getStyleObjectFromString = ( export const getStyleObjectFromString = (
str: string, str: string,
): Record<string, string> => { ): Record<string, string> => {
if (!str) return {};
const style = {} as Record<string, string>; const style = {} as Record<string, string>;
str.split(';').forEach((el) => { str.split(';').forEach((el) => {
const [property, value] = el.split(':'); const [property, value] = el.split(':');

View file

@ -56,7 +56,7 @@ export class DashboardsDataService {
widget.dataLoaderParams, widget.dataLoaderParams,
cfg, cfg,
); );
if (loadRes.result) return { widget: widget, data: loadRes.error }; if (loadRes.result) return { widget: widget, data: loadRes.result };
throw createAppError('CANNOT_LOAD_DATA'); throw createAppError('CANNOT_LOAD_DATA');
} }