/* * QQQ - Low-code Application Framework for Engineers. * Copyright (C) 2021-2022. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import {QException} from "@kingsrook/qqq-frontend-core/lib/exceptions/QException"; import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord"; import {QCriteriaOperator} from "@kingsrook/qqq-frontend-core/lib/model/query/QCriteriaOperator"; import {QFilterCriteria} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterCriteria"; import {QFilterOrderBy} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterOrderBy"; import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter"; import Alert from "@mui/material/Alert"; import Avatar from "@mui/material/Avatar"; import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import Chip from "@mui/material/Chip"; import Divider from "@mui/material/Divider"; import Grid from "@mui/material/Grid"; import Icon from "@mui/material/Icon"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemAvatar from "@mui/material/ListItemAvatar"; import ListItemText from "@mui/material/ListItemText"; import Modal from "@mui/material/Modal"; import Snackbar from "@mui/material/Snackbar"; import Tab from "@mui/material/Tab"; import Tabs from "@mui/material/Tabs"; import Typography from "@mui/material/Typography"; import React, {useReducer, useState} from "react"; import AceEditor from "react-ace"; import DataBagDataEditor, {DataBagDataEditorProps} from "qqq/components/databags/DataBagDataEditor"; import DataBagPreview from "qqq/components/databags/DataBagPreview"; import TabPanel from "qqq/components/misc/TabPanel"; import CustomWidthTooltip from "qqq/components/tooltips/CustomWidthTooltip"; import {LoadingState} from "qqq/models/LoadingState"; import DeveloperModeUtils from "qqq/utils/DeveloperModeUtils"; import Client from "qqq/utils/qqq/Client"; import ValueUtils from "qqq/utils/qqq/ValueUtils"; import "ace-builds/src-noconflict/mode-java"; import "ace-builds/src-noconflict/mode-javascript"; import "ace-builds/src-noconflict/mode-json"; import "ace-builds/src-noconflict/theme-github"; import "ace-builds/src-noconflict/ext-language_tools"; const qController = Client.getInstance(); // Declaring props types for ViewForm interface Props { dataBagId: number } DataBagViewer.defaultProps = { }; export default function DataBagViewer({dataBagId}: Props): JSX.Element { const [dataBagRecord, setDataBagRecord] = useState(null as QRecord); const [asyncLoadInited, setAsyncLoadInited] = useState(false); const [versionRecordList, setVersionRecordList] = useState(null as QRecord[]); const [selectedVersionRecord, setSelectedVersionRecord] = useState(null as QRecord); const [currentVersionId , setCurrentVersionId] = useState(null as number); const [notFoundMessage, setNotFoundMessage] = useState(null); const [selectedTab, setSelectedTab] = useState(0); const [editorProps, setEditorProps] = useState(null as DataBagDataEditorProps); const [successText, setSuccessText] = useState(null as string); const [failText, setFailText] = useState(null as string) const [, forceUpdate] = useReducer((x) => x + 1, 0); const [loadingSelectedVersion, _] = useState(new LoadingState(forceUpdate, "loading")); if (!asyncLoadInited) { setAsyncLoadInited(true); (async () => { try { const dataBagRecord = await qController.get("dataBag", dataBagId); setDataBagRecord(dataBagRecord); const criteria = [new QFilterCriteria("dataBagId", QCriteriaOperator.EQUALS, [dataBagId])]; const orderBys = [new QFilterOrderBy("sequenceNo", false)]; const filter = new QQueryFilter(criteria, orderBys, "AND", 0, 25); const versions = await qController.query("dataBagVersion", filter); console.log("Fetched versions:"); console.log(versions); setVersionRecordList(versions); if(versions && versions.length > 0) { setCurrentVersionId(versions[0].values.get("id")); const latestVersion = await qController.get("dataBagVersion", versions[0].values.get("id")); console.log("Fetched latestVersion:"); console.log(latestVersion); setSelectedVersionRecord(latestVersion); loadingSelectedVersion.setNotLoading(); forceUpdate(); } } catch (e) { if (e instanceof QException) { if ((e as QException).status === "404") { setNotFoundMessage("Data bag data could not be found."); return; } } setNotFoundMessage("Error loading data bag data: " + e); } })(); } const editData = (data: string) => { const editorProps = {} as DataBagDataEditorProps; editorProps.title = (data ? "Editing Contents of Data Bag: " : "Initializing Contents of Data Bag: ") + dataBagRecord?.values?.get("name"); editorProps.data = data; editorProps.dataBagId = dataBagId; setEditorProps(editorProps); }; const closeEditingScript = (event: object, reason: string, alert: string = null) => { if (reason === "backdropClick" || reason === "escapeKeyDown") { return; } if (reason === "saved") { setAsyncLoadInited(false); forceUpdate(); if (alert) { setSuccessText(alert); } } else if (reason === "failed") { setAsyncLoadInited(false); forceUpdate(); if (alert) { setFailText(alert); } } setEditorProps(null); }; const changeTab = (newValue: number) => { setSelectedTab(newValue); forceUpdate(); }; const selectVersion = (version: QRecord) => { (async () => { // fetch the full version setSelectedVersionRecord(version); loadingSelectedVersion.setLoading(); const selectedVersion = await qController.get("dataBagVersion", version.values.get("id")); console.log("Fetched selectedVersion:"); console.log(selectedVersion); setSelectedVersionRecord(selectedVersion); loadingSelectedVersion.setNotLoading(); forceUpdate(); })(); }; function getVersionsList(versionRecordList: QRecord[], selectedVersionRecord: QRecord) { return { (versionRecordList == null || versionRecordList.length == 0) ? There are not any versions of this data bag. : <> } { versionRecordList?.map((version: any) => ( selectVersion(version)}> {`${version.values.get("sequenceNo")}`} {currentVersionId == version?.values?.get("id") && } {version.values.get("commitMessage")} } secondary={ <> {ValueUtils.formatDateTime(version.values.get("createDate"))}
{version.values.get("author")} } />
)) }
; } let editButtonTooltip = ""; let editButtonText = "Create New Version"; if (currentVersionId) { if (currentVersionId === selectedVersionRecord?.values?.get("id")) { editButtonTooltip = "If you make any changes to this data bag, a new version will be created when you hit Save."; editButtonText = "Edit"; } else { editButtonTooltip = "If you want to make this previous Version active, bring up the Edit window, make any changes " + "to the old Version if they are needed, then click Save. A new Version will be created, and set as Current."; editButtonText = "Edit and Activate"; } } return ( { notFoundMessage ? {notFoundMessage} : { successText ? ( setSuccessText(null)} anchorOrigin={{vertical: "top", horizontal: "center"}}> setSuccessText(null)}> {successText} ) : ("") } { failText ? ( setFailText(null)} anchorOrigin={{vertical: "top", horizontal: "center"}}> setFailText(null)}> {failText} ) : ("") } <> changeTab(newValue)} variant="standard" > Versions {getVersionsList(versionRecordList, selectedVersionRecord)} { selectedVersionRecord ? Version {selectedVersionRecord.values.get("sequenceNo")} { currentVersionId === selectedVersionRecord.values.get("id") ? (<> (Current)) : <> } : <> } { loadingSelectedVersion.isNotLoading() && selectedVersionRecord && selectedVersionRecord.values.get("data") ? ( <> ) : null } { loadingSelectedVersion.isLoadingSlow() && Loading... } Versions {getVersionsList(versionRecordList, selectedVersionRecord)} Data Preview (Version {selectedVersionRecord?.values?.get("sequenceNo")}) {loadingSelectedVersion.isNotLoading() && selectedTab == 1 && selectedVersionRecord?.values?.get("data") && } {loadingSelectedVersion.isLoadingSlow() && Loading...} { editorProps && closeEditingScript(event, reason)}> } } ); }