diff --git a/renderer/components/Modal/index.js b/renderer/components/Modal/index.js
index 58423f52..486f98e9 100644
--- a/renderer/components/Modal/index.js
+++ b/renderer/components/Modal/index.js
@@ -18,18 +18,18 @@ const ModalContent = ({children}) => (
);
-const ModalFooter = ({confirmText, cancelText, handleSubmit, handleCancel, confirmDisabled}) => {
+const ModalFooter = ({confirmText, cancelText, handleSubmit, handleCancel, confirmDisabled, hideCancel}) => {
confirmText = confirmText || 'Save';
cancelText = cancelText || 'Cancel';
return (
closeModal()} />
diff --git a/renderer/components/Portal/index.js b/renderer/components/Portal/index.js
new file mode 100644
index 00000000..9029fc17
--- /dev/null
+++ b/renderer/components/Portal/index.js
@@ -0,0 +1,8 @@
+import { createPortal } from 'react-dom';
+
+function Portal({ children, wrapperId }) {
+ wrapperId = wrapperId || "bruno-app-body";
+
+ return createPortal(children, document.getElementById(wrapperId));
+}
+export default Portal;
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/AddWorkspace/index.js b/renderer/components/Workspaces/WorkspaceConfigurer/AddWorkspace/index.js
new file mode 100644
index 00000000..da3f242c
--- /dev/null
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/AddWorkspace/index.js
@@ -0,0 +1,70 @@
+import React, { useEffect, useRef } from 'react';
+import Portal from "components/Portal/index";
+import Modal from "components/Modal/index";
+import { useFormik } from 'formik';
+import { addWorkspace } from 'providers/ReduxStore/slices/workspaces';
+import * as Yup from 'yup';
+import { useDispatch } from 'react-redux';
+
+const AddWorkspace = ({onClose}) => {
+ const dispatch = useDispatch();
+ const inputRef = useRef();
+ const formik = useFormik({
+ enableReinitialize: true,
+ initialValues: {
+ name: ""
+ },
+ validationSchema: Yup.object({
+ name: Yup.string()
+ .min(1, 'must be atleast 1 characters')
+ .max(30, 'must be 30 characters or less')
+ .required('name is required')
+ }),
+ onSubmit: (values) => {
+ dispatch(addWorkspace({name: values.name}));
+ onClose();
+ }
+ });
+
+ useEffect(() => {
+ if(inputRef && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [inputRef]);
+
+ const onSubmit = () => {
+ formik.handleSubmit();
+ }
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default AddWorkspace;
+
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/DeleteWorkspace/StyledWrapper.js b/renderer/components/Workspaces/WorkspaceConfigurer/DeleteWorkspace/StyledWrapper.js
new file mode 100644
index 00000000..48b87421
--- /dev/null
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/DeleteWorkspace/StyledWrapper.js
@@ -0,0 +1,15 @@
+import styled from 'styled-components';
+
+const Wrapper = styled.div`
+ button.submit {
+ color: white;
+ background-color: var(--color-background-danger) !important;
+ border: inherit !important;
+
+ &:hover {
+ border: inherit !important;
+ }
+ }
+`;
+
+export default Wrapper;
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/DeleteWorkspace/index.js b/renderer/components/Workspaces/WorkspaceConfigurer/DeleteWorkspace/index.js
new file mode 100644
index 00000000..79c94fb5
--- /dev/null
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/DeleteWorkspace/index.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import Portal from "components/Portal/index";
+import Modal from "components/Modal/index";
+import { deleteWorkspace } from 'providers/ReduxStore/slices/workspaces';
+import { useDispatch } from 'react-redux';
+import StyledWrapper from './StyledWrapper';
+
+const DeleteWorkspace = ({onClose, workspace}) => {
+ const dispatch = useDispatch();
+ const onConfirm = () =>{
+ dispatch(deleteWorkspace({workspaceUid: workspace.uid}))
+ onClose();
+ };
+
+ return (
+
+
+
+ Are you sure you want to delete {workspace.name} ?
+
+
+
+
+ );
+}
+
+export default DeleteWorkspace;
+
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/EditWorkspace/index.js b/renderer/components/Workspaces/WorkspaceConfigurer/EditWorkspace/index.js
new file mode 100644
index 00000000..b5880da5
--- /dev/null
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/EditWorkspace/index.js
@@ -0,0 +1,70 @@
+import React, { useEffect, useRef } from 'react';
+import Portal from "components/Portal/index";
+import Modal from "components/Modal/index";
+import { useFormik } from 'formik';
+import { renameWorkspace } from 'providers/ReduxStore/slices/workspaces';
+import * as Yup from 'yup';
+import { useDispatch } from 'react-redux';
+
+const EditWorkspace = ({onClose, workspace}) => {
+ const dispatch = useDispatch();
+ const inputRef = useRef();
+ const formik = useFormik({
+ enableReinitialize: true,
+ initialValues: {
+ name: workspace.name
+ },
+ validationSchema: Yup.object({
+ name: Yup.string()
+ .min(1, 'must be atleast 1 characters')
+ .max(30, 'must be 30 characters or less')
+ .required('name is required')
+ }),
+ onSubmit: (values) => {
+ dispatch(renameWorkspace({name: values.name, uid: workspace.uid}));
+ onClose();
+ }
+ });
+
+ useEffect(() => {
+ if(inputRef && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [inputRef]);
+
+ const onSubmit = () => {
+ formik.handleSubmit();
+ }
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default EditWorkspace;
+
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/WorkspaceItem/StyledWrapper.js b/renderer/components/Workspaces/WorkspaceConfigurer/WorkspaceItem/StyledWrapper.js
new file mode 100644
index 00000000..feada928
--- /dev/null
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/WorkspaceItem/StyledWrapper.js
@@ -0,0 +1,17 @@
+import styled from 'styled-components';
+
+const Wrapper = styled.div`
+ div {
+ padding: 4px 6px;
+ padding-left: 8px;
+ display: flex;
+ align-items: center;
+ border-radius: 3px;
+ }
+
+ div:hover {
+ background-color: #f4f4f4;
+ }
+`;
+
+export default Wrapper;
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/WorkspaceItem/index.js b/renderer/components/Workspaces/WorkspaceConfigurer/WorkspaceItem/index.js
new file mode 100644
index 00000000..cb1d3e84
--- /dev/null
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/WorkspaceItem/index.js
@@ -0,0 +1,27 @@
+import React, { useState } from "react";
+import EditModal from "../EditModal";
+import DeleteModal from "../DeleteModal";
+import { IconEdit, IconTrash } from "@tabler/icons";
+import StyledWrapper from "./StyledWrapper";
+
+const WorkspaceItem = ({workspace}) => {
+ const [openEditModal, setOpenEditModal] = useState(false);
+ const [openDeleteModal, setOpenDeleteModal] = useState(false);
+
+ return (
+
+
+
{workspace.name}
+
+ setOpenEditModal(true)}/>
+ setOpenDeleteModal(true)}/>
+
+ {openEditModal &&
setOpenEditModal(false)} workspace={workspace} />}
+ {openDeleteModal && setOpenDeleteModal(false)} workspace={workspace} />}
+
+
+ )
+
+}
+
+export default WorkspaceItem;
diff --git a/renderer/components/Workspaces/WorkspaceConfigurer/index.js b/renderer/components/Workspaces/WorkspaceConfigurer/index.js
index 25ea54d8..cf9fa4d1 100644
--- a/renderer/components/Workspaces/WorkspaceConfigurer/index.js
+++ b/renderer/components/Workspaces/WorkspaceConfigurer/index.js
@@ -1,36 +1,28 @@
import Modal from "components/Modal/index";
-import React from "react";
+import React, { useState } from "react";
import { useSelector } from "react-redux";
+import WorkspaceItem from "./WorkspaceItem/index";
+import AddModal from "./AddModal";
const WorkspaceConfigurer = ({onClose}) => {
const { workspaces } = useSelector((state) => state.workspaces);
-
- const onSubmit = () => {
- onClose();
- }
+ const [openAddModal, setOpenAddModal] = useState(false);
return (
setOpenAddModal(true)}
handleCancel={onClose}
+ hideCancel={true}
>
-
)
diff --git a/renderer/pages/_document.js b/renderer/pages/_document.js
index 11f6fdca..444a83b2 100644
--- a/renderer/pages/_document.js
+++ b/renderer/pages/_document.js
@@ -34,7 +34,7 @@ export default class MyDocument extends Document {
-
+
diff --git a/renderer/providers/ReduxStore/slices/workspaces.js b/renderer/providers/ReduxStore/slices/workspaces.js
index 2d9aa447..fa952e9b 100644
--- a/renderer/providers/ReduxStore/slices/workspaces.js
+++ b/renderer/providers/ReduxStore/slices/workspaces.js
@@ -1,4 +1,5 @@
-import { createSlice } from '@reduxjs/toolkit'
+import { createSlice } from '@reduxjs/toolkit';
+import { uuid } from 'utils/common';
const initialState = {
workspaces: [{
@@ -21,11 +22,33 @@ export const workspacesSlice = createSlice({
selectWorkspace: (state, action) => {
state.activeWorkspaceUid = action.payload.uid;
},
+ renameWorkspace: (state, action) => {
+ const { name, uid } = action.payload;
+ const { workspaces } = state;
+ const workspaceIndex = workspaces.findIndex(workspace => workspace.uid == uid);
+ workspaces[workspaceIndex].name = name;
+ },
+ deleteWorkspace: (state, action) => {
+ if(state.activeWorkspaceUid === action.payload.workspaceUid) {
+ throw new Error("User cannot delete current workspace");
+ }
+ state.workspaces = state.workspaces.filter((workspace) => workspace.uid !== action.payload.workspaceUid);
+ },
+ addWorkspace: (state, action) => {
+ const newWorkspace = {
+ uid: uuid(),
+ name: action.payload.name
+ }
+ state.workspaces.push(newWorkspace);
+ }
}
});
export const {
- selectWorkspace
+ selectWorkspace,
+ renameWorkspace,
+ deleteWorkspace,
+ addWorkspace
} = workspacesSlice.actions;
export default workspacesSlice.reducer;