Добавлены все виджеты на дашборд
This commit is contained in:
parent
ae14189cd3
commit
a756677c89
11 changed files with 70 additions and 29 deletions
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 }}>
|
||||||
|
|
|
||||||
18
frontend/src/dashboard/widgets/issues-list.tsx
Normal file
18
frontend/src/dashboard/widgets/issues-list.tsx
Normal 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} />;
|
||||||
|
});
|
||||||
|
|
@ -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} />;
|
||||||
});
|
});
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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(':');
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue