diff --git a/src/api/ManagementAPI.js b/src/api/ManagementAPI.js index 6f1e914..832e4ca 100644 --- a/src/api/ManagementAPI.js +++ b/src/api/ManagementAPI.js @@ -41,6 +41,18 @@ export const renameSetupKey = async (getAccessTokenSilently, keyId, newName) => "/api/setup-keys/" + keyId) } + +export const createSetupKey = async (getAccessTokenSilently, name, type, expiresIn) => { + return callApi( + "POST", + {'Content-Type': 'application/json'}, + JSON.stringify({Name: name, Type: type, ExpiresIn: expiresIn}, (key, value) => { + if (value !== null) return value + }), + getAccessTokenSilently, + "/api/setup-keys") +} + export const getPeers = async (getAccessTokenSilently) => { return callApi("GET", {}, null, getAccessTokenSilently, "/api/peers") } diff --git a/src/components/NewSetupKeyDialog.js b/src/components/NewSetupKeyDialog.js new file mode 100644 index 0000000..dd756b1 --- /dev/null +++ b/src/components/NewSetupKeyDialog.js @@ -0,0 +1,239 @@ +import {Fragment, useEffect, useState} from 'react' +import {Dialog, RadioGroup, Transition} from '@headlessui/react' +import {XIcon} from '@heroicons/react/outline' +import {ExclamationCircleIcon, QuestionMarkCircleIcon} from '@heroicons/react/solid' +import PropTypes from "prop-types"; + +const types = [ + {name: 'Reusable', description: 'This type of a setup key allows to setup multiple machine', value: 'reusable'}, + {name: 'One-off', description: 'This key can be used only once', value: 'one-off'}, +] + +function classNames(...classes) { + return classes.filter(Boolean).join(' ') +} + +const NewSetupKeyDialog = ({show, closeCallback}) => { + const [open, setOpen] = useState(show) + const [keyName, setKeyName] = useState("") + const [selectedType, setSelectedType] = useState(types[0]) + + useEffect(() => { + setOpen(show) + setKeyName("") + setSelectedType(types[0]) + }, [show]); + + return ( + + { + closeCallback(true, null, null, null) + }}> +
+ + +
+ +
+
+
+ {/* Header */} +
+
+
+ New + setup + key +

+ Setup keys allow you to enroll new peers +

+
+ +
+ +
+
+
+
+ +
+ +
+
+ +
+
+ setKeyName(event.target.value)} + /> +
+
+
+
+

+ The name of the key can't be empty. +

+
+ +
+ +
+
+
+ Type + +
+
+ + Privacy + setting +
+ {types.map((setting, settingIdx) => ( + + classNames( + settingIdx === 0 ? 'squared-tl-md squared-tr-md' : '', + settingIdx === types.length - 1 ? 'squared-bl-md squared-br-md' : '', + checked ? 'bg-gray-50 border-gray-200 z-10' : 'border-gray-200', + 'relative border p-4 flex cursor-pointer focus:outline-none' + ) + } + > + {({active, checked}) => ( + <> + + ))} +
+
+
+ +
+
+
+
+
+ + {/* Action buttons */} +
+
+ + +
+
+
+
+
+
+
+
+
+ ) +} + +NewSetupKeyDialog.propTypes = { + show: PropTypes.bool, + closeCallback: PropTypes.func, + /*text: PropTypes.string*/ +}; + +NewSetupKeyDialog.defaultProps = {}; + +export default NewSetupKeyDialog; \ No newline at end of file diff --git a/src/views/SetupKeys.js b/src/views/SetupKeys.js index dbc2d68..9915fe6 100644 --- a/src/views/SetupKeys.js +++ b/src/views/SetupKeys.js @@ -2,10 +2,12 @@ import React, {useEffect, useState} from "react"; import {useAuth0, withAuthenticationRequired} from "@auth0/auth0-react"; import Loading from "../components/Loading"; import {formatDate, timeAgo} from "../utils/common"; -import {getSetupKeys, revokeSetupKey} from "../api/ManagementAPI"; +import {createSetupKey, getSetupKeys, revokeSetupKey} from "../api/ManagementAPI"; import EditButton from "../components/EditButton"; import CopyText from "../components/CopyText"; import DeleteModal from "../components/DeleteDialog"; +import {PlusSmIcon as PlusSmIconSolid} from "@heroicons/react/solid"; +import NewSetupKeyDialog from "../components/NewSetupKeyDialog"; export const SetupKeysComponent = () => { @@ -14,10 +16,26 @@ export const SetupKeysComponent = () => { const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [showDeleteDialog, setShowDeleteDialog] = useState(false) + const [showNewKeyDialog, setShowNewKeyDialog] = useState(false) const [deleteDialogText, setDeleteDialogText] = useState("") const [deleteDialogTitle, setDeleteDialogTitle] = useState("") const [keyToRevoke, setKeyToRevoke] = useState(null) + const handleNewKeyClick = () => { + setShowNewKeyDialog(true) + } + + const newSetupKeyDialogCallback = (cancelled, name, type, expiresIn) => { + if (!cancelled) { + createSetupKey(getAccessTokenSilently, name, type, expiresIn) + .then(() => refresh()) + .catch(error => { + console.log(error) + }) + } + setShowNewKeyDialog(false) + } + const { getAccessTokenSilently, } = useAuth0(); @@ -85,6 +103,20 @@ export const SetupKeysComponent = () => { + +
+ + +