diff --git a/dashboard/src/states/Dashboard/pages/Licenses/components/LicenseDialog/LicenseDialog.jsx b/dashboard/src/states/Dashboard/pages/Licenses/components/LicenseDialog/LicenseDialog.jsx
new file mode 100644
index 0000000..5ae1837
--- /dev/null
+++ b/dashboard/src/states/Dashboard/pages/Licenses/components/LicenseDialog/LicenseDialog.jsx
@@ -0,0 +1,172 @@
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Slide,
+ Stack
+} from "@mui/material";
+import {useContext, useEffect, useState} from "react";
+import {ProjectContext} from "@/states/Dashboard/contexts/Project";
+import {
+ AdminPanelSettings,
+ CalendarMonth,
+ Group,
+ Key,
+ TableChart
+} from "@mui/icons-material";
+import DialogField from "./components/DialogField";
+import LicenseKey from "./pages/LicenseKey";
+import Permissions from "./pages/Permissions";
+import Groups from "./pages/Groups";
+import MetaData from "./pages/MetaData";
+import {replaceLicenseDefaults} from "./pages/LicenseKey/util.js";
+import ExpirationDate from "./pages/ExpirationDate";
+import dayjs from "dayjs";
+import {patchRequest, putRequest} from "@/common/utils/RequestUtil.js";
+
+const TransitionWrapper = ({direction, in: inProp, children}) => {
+ return (
+
+
+ {children}
+
+
+ );
+};
+
+export const LicenseDialog = ({open, onClose, switchToEnd, editLicense, setEditLicense}) => {
+ const {currentProject} = useContext(ProjectContext);
+
+ const [currentPage, setCurrentPage] = useState("chooser");
+
+ const [licenseKey, setLicenseKey] = useState("");
+ const [expirationDate, setExpirationDate] = useState("");
+ const [permissions, setPermissions] = useState([]);
+ const [groups, setGroups] = useState([]);
+ const [metaData, setMetaData] = useState({});
+
+ useEffect(() => {
+ if (!open) return;
+ setCurrentPage("chooser");
+
+ if (editLicense) {
+ console.log(editLicense)
+ setLicenseKey(editLicense.key);
+ setExpirationDate(editLicense.expirationDate);
+ setPermissions(editLicense.permissions);
+ setGroups(editLicense.groups);
+ setMetaData(editLicense.meta);
+ } else {
+ setLicenseKey(replaceLicenseDefaults(currentProject.defaults.licenseKey));
+ setExpirationDate(currentProject.defaults.expirationDate);
+ setPermissions(currentProject.defaults.permissions);
+ setGroups(currentProject.defaults.groups);
+ setMetaData({});
+ }
+ }, [open]);
+
+ const goBack = () => {
+ setCurrentPage("chooser");
+ };
+
+ const closeDialog = () => {
+ setEditLicense(null);
+ onClose();
+ }
+
+ const createLicense = async () => {
+ try {
+ closeDialog();
+ const {key} = await putRequest(`/license/${currentProject.id}`, {key: licenseKey,
+ expirationDate: new Date(expirationDate).getTime() === 0 ? 0 : expirationDate, permissions,
+ groups, meta: metaData});
+ switchToEnd(key);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ const patchLicense = async () => {
+ try {
+ closeDialog();
+ await patchRequest(`/license/${currentProject.id}/${encodeURIComponent(editLicense.key)}`,
+ {key: licenseKey, expirationDate: new Date(expirationDate).getTime() === 0 ? 0 : expirationDate,
+ permissions, groups, meta: metaData});
+ switchToEnd(licenseKey);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/dashboard/src/states/Dashboard/pages/Licenses/components/LicenseDialog/index.js b/dashboard/src/states/Dashboard/pages/Licenses/components/LicenseDialog/index.js
new file mode 100644
index 0000000..a602f8a
--- /dev/null
+++ b/dashboard/src/states/Dashboard/pages/Licenses/components/LicenseDialog/index.js
@@ -0,0 +1 @@
+export {LicenseDialog as default} from "./LicenseDialog.jsx";
\ No newline at end of file