Add Monitoring files in Python and Mui/React
This commit is contained in:
File diff suppressed because one or more lines are too long
2
vrpmdvfrontend/dist/index.html
vendored
2
vrpmdvfrontend/dist/index.html
vendored
@@ -22,7 +22,7 @@
|
||||
<title>
|
||||
Markus Lehr | VR Predictive Maintenance Device.
|
||||
</title>
|
||||
<script type="module" crossorigin src="/assets/index-40b528e3.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-a894fc13.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
||||
@@ -44,14 +44,17 @@ import { MonitoringList } from "./pages/monitorings/list";
|
||||
import { MonitoringCreate } from "./pages/monitorings/create";
|
||||
import { MonitoringEdit } from "./pages/monitorings/edit";
|
||||
import { VR_API_URL } from './env';
|
||||
import { MonDatafileList } from "./pages/monitorings/mondatfilelist";
|
||||
|
||||
|
||||
const API_URL = "https://api.fake-rest.refine.dev";
|
||||
|
||||
// Test URL
|
||||
//const MONITORINGS_API_URL = 'http://127.0.0.1:5000/vrpmdvapi/1_0';
|
||||
const MONITORINGS_API_URL = 'http://127.0.0.1:5000/vrpmdvapi/1_0';
|
||||
const MONITORINGFILES_API_URL = 'http://127.0.0.1:5000/vrpmdvapi/1_0';
|
||||
// Embedded URL
|
||||
const MONITORINGS_API_URL = '/vrpmdvapi/1_0';
|
||||
//const MONITORINGS_API_URL = '/vrpmdvapi/1_0';
|
||||
//const MONDATAFILES_API_URL = '/vrpmdvapi/1_0';
|
||||
// .get(`${API_URL}/exams`)
|
||||
|
||||
const MONITORINGSTATUS_API_URL = 'http://127.0.0.1:5000/vrpmdvapi/1_0';
|
||||
@@ -69,6 +72,7 @@ function App() {
|
||||
dataProvider={{
|
||||
default: dataProvider(API_URL),
|
||||
monitorings: dataProvider(MONITORINGS_API_URL),
|
||||
monitoringfiles: dataProvider(MONITORINGFILES_API_URL),
|
||||
}}
|
||||
notificationProvider={notificationProvider}
|
||||
authProvider={authProvider}
|
||||
@@ -79,11 +83,21 @@ function App() {
|
||||
list: "/monitorings",
|
||||
create: "/monitorings/create",
|
||||
edit: "/monitorings/edit/:id",
|
||||
// show: "/monitorings/datafiles/:id",
|
||||
meta: {
|
||||
canDelete: true,
|
||||
dataProviderName: "monitorings"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "monitoringfiles",
|
||||
list: "/monitoringfiles",
|
||||
meta: {
|
||||
canDelete: true,
|
||||
dataProviderName: "monitoringfiles"
|
||||
},
|
||||
},
|
||||
|
||||
]}
|
||||
options={{
|
||||
syncWithLocation: true,
|
||||
@@ -122,6 +136,10 @@ function App() {
|
||||
<Route index element={<MonitoringList />} />
|
||||
<Route path="create" element={<MonitoringCreate />} />
|
||||
<Route path="edit/:id" element={<MonitoringEdit />} />
|
||||
<Route path="datafiles/:id" element={<MonDatafileList />} />
|
||||
</Route>
|
||||
<Route path="/monitoringfiles">
|
||||
<Route index element={<MonDatafileList />} />
|
||||
</Route>
|
||||
<Route path="*" element={<ErrorComponent />} />
|
||||
</Route>
|
||||
|
||||
190
vrpmdvfrontend/src/hooks/data/usedownload.ts
Normal file
190
vrpmdvfrontend/src/hooks/data/usedownload.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
import React, { useState } from "react";
|
||||
import { QueryObserverResult, UseQueryOptions } from "@tanstack/react-query";
|
||||
import warnOnce from "warn-once";
|
||||
|
||||
import { useMeta, useList } from "@refinedev/core";
|
||||
|
||||
import {
|
||||
BaseRecord,
|
||||
GetListResponse,
|
||||
SuccessErrorNotification,
|
||||
MetaQuery,
|
||||
LiveModeProps,
|
||||
BaseKey,
|
||||
HttpError,
|
||||
Prettify,
|
||||
} from "@refinedev/core";
|
||||
import { useResource } from "@refinedev/core";
|
||||
import { pickNotDeprecated } from "@refinedev/core";
|
||||
import {
|
||||
useLoadingOvertime,
|
||||
UseLoadingOvertimeOptionsProps,
|
||||
UseLoadingOvertimeReturnType,
|
||||
} from "@refinedev/core";
|
||||
|
||||
export type useDownloadReturnType<
|
||||
TData extends BaseRecord = BaseRecord,
|
||||
TError extends HttpError = HttpError,
|
||||
> = {
|
||||
downloadResult: QueryObserverResult<GetListResponse<TData>, TError>;
|
||||
// // showId?: BaseKey;
|
||||
// setShowId: React.Dispatch<React.SetStateAction<BaseKey | undefined>>;
|
||||
} & UseLoadingOvertimeReturnType;
|
||||
|
||||
export type useDownloadProps<
|
||||
TQueryFnData extends BaseRecord = BaseRecord,
|
||||
TError extends HttpError = HttpError,
|
||||
TData extends BaseRecord = TQueryFnData,
|
||||
> = {
|
||||
/**
|
||||
* Resource name for API data interactions
|
||||
* @default Reads `:resource` from the URL
|
||||
*/
|
||||
resource?: string;
|
||||
/**
|
||||
* Data item ID for API data interactions
|
||||
* @default Reads `:id` from the URL
|
||||
*/
|
||||
id?: BaseKey;
|
||||
/**
|
||||
* react-query's [useQuery](https://tanstack.com/query/v4/docs/reference/useQuery) options
|
||||
*/
|
||||
queryOptions?: UseQueryOptions<
|
||||
GetListResponse<TQueryFnData>,
|
||||
TError,
|
||||
GetListResponse<TData>
|
||||
>;
|
||||
/**
|
||||
* Additional meta data to pass to the data provider's `getOne`
|
||||
*/
|
||||
// meta?: MetaQuery;
|
||||
// /**
|
||||
// * Additional meta data to pass to the data provider's `getOne`
|
||||
// * @deprecated `metaData` is deprecated with refine@4, refine will pass `meta` instead, however, we still support `metaData` for backward compatibility.
|
||||
// */
|
||||
metaData?: MetaQuery;
|
||||
/**
|
||||
* Target data provider name for API call to be made
|
||||
* @default `"default"`
|
||||
*/
|
||||
dataProviderName?: string;
|
||||
} & LiveModeProps &
|
||||
SuccessErrorNotification<
|
||||
GetListResponse<TData>,
|
||||
TError,
|
||||
Prettify<{ id?: BaseKey } & MetaQuery>
|
||||
> &
|
||||
UseLoadingOvertimeOptionsProps;
|
||||
|
||||
/**
|
||||
* `useDownload` hook allows you to fetch the desired record.
|
||||
* It uses `getList` method as query function from the dataProvider that is
|
||||
* passed to {@link https://refine.dev/docs/api-reference/core/components/refine-config/ `<Refine>`}.
|
||||
*
|
||||
* @see {@link https://refine.dev/docs/api-reference/core/hooks/show/useShow} for more details. => TODO ML: change to own link
|
||||
*
|
||||
* @typeParam TQueryFnData - Result data returned by the query function. Extends {@link https://refine.dev/docs/api-reference/core/interfaceReferences#baserecord `BaseRecord`}
|
||||
* @typeParam TError - Custom error object that extends {@link https://refine.dev/docs/api-reference/core/interfaceReferences#httperror `HttpError`}
|
||||
* @typeParam TData - Result data returned by the `select` function. Extends {@link https://refine.dev/docs/api-reference/core/interfaceReferences#baserecord `BaseRecord`}. Defaults to `TQueryFnData`
|
||||
*
|
||||
*/
|
||||
|
||||
export const useDownload = <
|
||||
TQueryFnData extends BaseRecord = BaseRecord,
|
||||
TError extends HttpError = HttpError,
|
||||
TData extends BaseRecord = TQueryFnData,
|
||||
>({
|
||||
resource: resourceFromProp,
|
||||
id,
|
||||
successNotification,
|
||||
errorNotification,
|
||||
//meta,
|
||||
metaData,
|
||||
liveMode,
|
||||
onLiveEvent,
|
||||
dataProviderName,
|
||||
queryOptions,
|
||||
overtimeOptions,
|
||||
}: useDownloadProps<TQueryFnData, TError, TData> = {}): useDownloadReturnType<
|
||||
TData,
|
||||
TError
|
||||
> => {
|
||||
const {
|
||||
resource,
|
||||
id: idFromRoute,
|
||||
identifier,
|
||||
} = useResource(resourceFromProp);
|
||||
const { identifier: inferredIdentifier } = useResource();
|
||||
const getMeta = useMeta();
|
||||
|
||||
const getDefaultId = () => {
|
||||
const idFromPropsOrRoute = id ?? idFromRoute;
|
||||
|
||||
if (resourceFromProp && resourceFromProp !== inferredIdentifier) {
|
||||
return id;
|
||||
}
|
||||
|
||||
return idFromPropsOrRoute;
|
||||
};
|
||||
const defaultId = getDefaultId();
|
||||
|
||||
//const [showId, setShowId] = useState<BaseKey | undefined>(defaultId);
|
||||
|
||||
// React.useEffect(() => {
|
||||
// setShowId(defaultId);
|
||||
// }, [defaultId]);
|
||||
|
||||
// const combinedMeta = getMeta({
|
||||
// resource,
|
||||
// meta: pickNotDeprecated(meta, metaData),
|
||||
// });
|
||||
|
||||
warnOnce(
|
||||
Boolean(resourceFromProp) && !id,
|
||||
`[useShow]: resource: "${identifier}", id: ${id} \n\nIf you don't use the \`setShowId\` method to set the \`showId\`, you should pass the \`id\` prop to \`useShow\`. Otherwise, \`useShow\` will not be able to infer the \`id\` from the current URL. \n\nSee https://refine.dev/docs/api-reference/core/hooks/show/useShow/#resource`,
|
||||
);
|
||||
|
||||
|
||||
// const downloadResult = () : QueryObserverResult<GetListResponse<TData>, TError> => {
|
||||
// const res = useList<TQueryFnData, TError, TData>({
|
||||
// resource: identifier,
|
||||
// successNotification,
|
||||
// errorNotification,
|
||||
// metaData: metaData,
|
||||
// liveMode,
|
||||
// onLiveEvent,
|
||||
// dataProviderName,
|
||||
// });
|
||||
|
||||
// return { res };
|
||||
// };
|
||||
|
||||
|
||||
const downloadResult = useList<TQueryFnData, TError, TData>({
|
||||
resource: identifier,
|
||||
|
||||
// queryOptions: {
|
||||
// enabled: showId !== undefined,
|
||||
// ...queryOptions,
|
||||
// },
|
||||
successNotification,
|
||||
errorNotification,
|
||||
metaData: metaData,
|
||||
liveMode,
|
||||
onLiveEvent,
|
||||
dataProviderName,
|
||||
});
|
||||
|
||||
|
||||
|
||||
const { elapsedTime } = useLoadingOvertime({
|
||||
isLoading: downloadResult.isFetching,
|
||||
interval: overtimeOptions?.interval,
|
||||
onInterval: overtimeOptions?.onInterval,
|
||||
});
|
||||
|
||||
return {
|
||||
downloadResult,
|
||||
overtime: { elapsedTime },
|
||||
};
|
||||
};
|
||||
24
vrpmdvfrontend/src/pages/monitorings/downloadbutton
Normal file
24
vrpmdvfrontend/src/pages/monitorings/downloadbutton
Normal file
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
useModal,
|
||||
} from "@refinedev/core";
|
||||
|
||||
import Button from "@refinedev/mui";
|
||||
|
||||
|
||||
export const DownloadButton = () => {
|
||||
const { visible, show, close } = useModal();
|
||||
|
||||
return (
|
||||
<Button>
|
||||
Download
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// {visible && (
|
||||
// <YourModalComponent>
|
||||
// <p>Dummy Modal Content</p>
|
||||
// <button onClick={close}>Close Modal</button>
|
||||
// </YourModalComponent>
|
||||
// )}
|
||||
@@ -147,6 +147,7 @@ export const MonitoringList = () => {
|
||||
return (
|
||||
<>
|
||||
<EditButton hideText recordItemId={row.id} />
|
||||
<ShowButton hideText recordItemId={row.id} />
|
||||
<DeleteButton hideText recordItemId={row.id} />
|
||||
</>
|
||||
);
|
||||
|
||||
261
vrpmdvfrontend/src/pages/monitorings/mondatfilelist.tsx
Normal file
261
vrpmdvfrontend/src/pages/monitorings/mondatfilelist.tsx
Normal file
@@ -0,0 +1,261 @@
|
||||
import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
|
||||
import { Download, Delete } from "@mui/icons-material";
|
||||
|
||||
import {
|
||||
DateField,
|
||||
DeleteButton,
|
||||
EditButton,
|
||||
List,
|
||||
MarkdownField,
|
||||
NumberField,
|
||||
ShowButton,
|
||||
useDataGrid,
|
||||
} from "@refinedev/mui";
|
||||
|
||||
import React from "react";
|
||||
import { IMonitoring, IMonitoringFile } from "./monitorings.types";
|
||||
//import { MonitoringStatus } from "./status/monitoringstatus";
|
||||
// import { MonitoringStatusEditChip } from "./status/monitoringstatusedit";
|
||||
import { useUpdate } from "@refinedev/core";
|
||||
import Button from "@mui/material/Button/Button";
|
||||
import Stack from "@mui/material/Stack/Stack";
|
||||
|
||||
|
||||
export const MonDatafileList = () => {
|
||||
const dataProvider = "monitoringfiles";
|
||||
//const dataProvider = "monitorings";
|
||||
const { dataGridProps } = useDataGrid<IMonitoringFile>({
|
||||
syncWithLocation: true,
|
||||
dataProviderName: dataProvider,
|
||||
pagination: {
|
||||
mode: "client",
|
||||
pageSize: 10,
|
||||
},
|
||||
});
|
||||
|
||||
const [selectedRowKeys, setSelectedRowKeys] = React.useState<GridRowSelectionModel>([]);
|
||||
const hasSelected = selectedRowKeys.length > 0;
|
||||
|
||||
|
||||
// const updateSelectedItems = () => {
|
||||
// mutate(
|
||||
// {
|
||||
// resource: "posts",
|
||||
// ids: selectedRowKeys.map(String),
|
||||
// values: {
|
||||
// status: "approved",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// onSuccess: () => {
|
||||
// setSelectedRowKeys([]);
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
// };
|
||||
|
||||
// const { data: categoryData, isLoading: categoryIsLoading } = useMany({
|
||||
// resource: "categories",
|
||||
// ids:
|
||||
// dataGridProps?.rows
|
||||
// ?.map((item: any) => item?.category?.id)
|
||||
// .filter(Boolean) ?? [],
|
||||
// queryOptions: {
|
||||
// enabled: !!dataGridProps?.rows,
|
||||
// },
|
||||
// });
|
||||
|
||||
const { mutate } = useUpdate();
|
||||
|
||||
//dataGridProps.disableRowSelectionOnClick: true;
|
||||
|
||||
const columns = React.useMemo<GridColDef<IMonitoringFile>[]>(
|
||||
() => [
|
||||
{
|
||||
field: "name",
|
||||
flex: 1,
|
||||
headerName: "Name",
|
||||
type:"string",
|
||||
minWidth: 250,
|
||||
},
|
||||
{
|
||||
field: "timestamp",
|
||||
flex: 1,
|
||||
headerName: "Timestamp",
|
||||
minWidth: 30,
|
||||
renderCell: function render({ value }) {
|
||||
let d = new Date();
|
||||
const unixtime = new Date(value);
|
||||
//return <DateField value={unixtime} />;
|
||||
return <DateField value={unixtime} format={'DD-MM-YYYY hh:mm:ss A'}/>;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: "samplerate",
|
||||
flex: 0.3,
|
||||
headerName: "Samplerate/Hz",
|
||||
renderCell: function render({ row }) {
|
||||
return (
|
||||
<NumberField
|
||||
value={row.samplerate}
|
||||
options={{
|
||||
minimumIntegerDigits: 1,
|
||||
minimumFractionDigits:0,
|
||||
maximumFractionDigits: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: "sampleperiod",
|
||||
flex: 0.3,
|
||||
headerName: "Period/s",
|
||||
renderCell: function render({ row }) {
|
||||
return (
|
||||
<NumberField
|
||||
value={row.sampleperiod}
|
||||
options={{
|
||||
minimumIntegerDigits: 1,
|
||||
minimumFractionDigits:1,
|
||||
maximumFractionDigits: 3,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: "downtime",
|
||||
flex: 0.3,
|
||||
headerName: "Downtime/s",
|
||||
renderCell: function render({ row }) {
|
||||
return (
|
||||
<NumberField
|
||||
value={row.downtime}
|
||||
options={{
|
||||
minimumIntegerDigits: 1,
|
||||
minimumFractionDigits:1,
|
||||
maximumFractionDigits: 3,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: "actions",
|
||||
headerName: "Actions",
|
||||
sortable: false,
|
||||
renderCell: function render({ row }) {
|
||||
return (
|
||||
<>
|
||||
<ShowButton hideText recordItemId={row.id} />
|
||||
<DeleteButton hideText recordItemId={row.id} />
|
||||
</>
|
||||
);
|
||||
},
|
||||
align: "center",
|
||||
headerAlign: "center",
|
||||
minWidth: 80,
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<List
|
||||
cardProps={{ sx: { paddingX: { xs: 2, md: 0 } } }}
|
||||
cardHeaderProps={{
|
||||
subheader: hasSelected && (
|
||||
<Stack direction="row">
|
||||
<Button
|
||||
startIcon={<Download color="success" />}
|
||||
onClick={() => updateSelectedItems("approved")}
|
||||
>
|
||||
Download
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<Delete color="error" />}
|
||||
onClick={() => updateSelectedItems("rejected")}
|
||||
>
|
||||
{t("buttons.rejectAll")}
|
||||
</Button>
|
||||
</Stack>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<DataGrid
|
||||
{...dataGridProps}
|
||||
columns={columns}
|
||||
autoHeight
|
||||
checkboxSelection
|
||||
onRowSelectionModelChange={(newSelectionModel) => {
|
||||
setSelectedRowKeys(newSelectionModel);
|
||||
}}
|
||||
rowSelectionModel={selectedRowKeys}
|
||||
/>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
<List
|
||||
cardProps={{ sx: { paddingX: { xs: 2, md: 0 } } }}
|
||||
cardHeaderProps={{
|
||||
subheader: hasSelected && (
|
||||
<Stack direction="row">
|
||||
<Button
|
||||
startIcon={<Download color="success" />}
|
||||
onClick={() => updateSelectedItems("approved")}
|
||||
>
|
||||
{t("buttons.acceptAll")}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<Delete color="error" />}
|
||||
onClick={() => updateSelectedItems("rejected")}
|
||||
>
|
||||
{t("buttons.rejectAll")}
|
||||
</Button>
|
||||
</Stack>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<DataGrid
|
||||
{...dataGridProps}
|
||||
columns={columns}
|
||||
autoHeight
|
||||
checkboxSelection
|
||||
onRowSelectionModelChange={(newSelectionModel) => {
|
||||
setSelectedRowKeys(newSelectionModel);
|
||||
}}
|
||||
rowSelectionModel={selectedRowKeys}
|
||||
/>
|
||||
</List>
|
||||
);
|
||||
*/
|
||||
|
||||
|
||||
// onRowSelectionModelChange={(newSelectionModel) => {
|
||||
// setSelectedRowKeys(newSelectionModel);
|
||||
// }}
|
||||
// rowSelectionModel={selectedRowKeys}
|
||||
|
||||
|
||||
// {
|
||||
// field: "monstate",
|
||||
// headerName: t("orders.fields.status"),
|
||||
// width: 124,
|
||||
// renderCell: function render({ row }) {
|
||||
// return <MonitoringStatus status={row.monstate} />;
|
||||
// },
|
||||
// },
|
||||
|
||||
|
||||
// renderEditCell: function render({ row }) {
|
||||
// return <MonitoringStatusEditChip value={row.status} />;
|
||||
// },
|
||||
|
||||
|
||||
@@ -11,6 +11,16 @@ export interface IMonitoring {
|
||||
owner: string;
|
||||
status: "off" | "started" | "stopped";//MonitoringStatus;
|
||||
}
|
||||
|
||||
|
||||
export interface IMonitoringFile {
|
||||
id: string;
|
||||
name: string;
|
||||
samplerate: number;
|
||||
sampleperiod: number;
|
||||
downtime: number;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
//string;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user