feat: workspaces crud (resolves #15) (#19)

feat: workspaces crud (resolves #15)
This commit is contained in:
anusreesubash
2022-10-09 12:45:48 +05:30
committed by GitHub
parent f634839adb
commit b3a317dc4d
11 changed files with 285 additions and 27 deletions

View File

@@ -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 (
<Portal>
<Modal
size="sm"
title={"Add Workspace"}
confirmText='Add'
handleConfirm={onSubmit}
handleCancel={onClose}
>
<form className="bruno-form" onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="name" className="block font-semibold">Workpsace Name</label>
<input
id="workspace-name" type="text" name="name"
ref={inputRef}
className="block textbox mt-2 w-full"
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
onChange={formik.handleChange}
value={formik.values.name || ''}
/>
{formik.touched.name && formik.errors.name ? (
<div className="text-red-500">{formik.errors.name}</div>
) : null}
</div>
</form>
</Modal>
</Portal>
);
}
export default AddWorkspace;

View File

@@ -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;

View File

@@ -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 (
<Portal>
<StyledWrapper>
<Modal
size="sm"
title={"Delete Workspace"}
confirmText="Delete"
handleConfirm={onConfirm}
handleCancel={onClose}
>
Are you sure you want to delete <span className="font-semibold">{workspace.name}</span> ?
</Modal>
</StyledWrapper>
</Portal>
);
}
export default DeleteWorkspace;

View File

@@ -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 (
<Portal>
<Modal
size="sm"
title={"Rename Workspace"}
confirmText='Rename'
handleConfirm={onSubmit}
handleCancel={onClose}
>
<form className="bruno-form" onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="name" className="block font-semibold">Workpsace Name</label>
<input
id="workspace-name" type="text" name="name"
ref={inputRef}
className="block textbox mt-2 w-full"
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
onChange={formik.handleChange}
value={formik.values.name || ''}
/>
{formik.touched.name && formik.errors.name ? (
<div className="text-red-500">{formik.errors.name}</div>
) : null}
</div>
</form>
</Modal>
</Portal>
);
}
export default EditWorkspace;

View File

@@ -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;

View File

@@ -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 (
<StyledWrapper>
<div className="flex justify-between items-baseline mb-2" key={workspace.uid} >
<li>{workspace.name}</li>
<div className="flex gap-x-4" >
<IconEdit className="cursor-pointer" size={20} strokeWidth={1.5} onClick={() => setOpenEditModal(true)}/>
<IconTrash className="cursor-pointer" size={20} strokeWidth={1.5} onClick={() => setOpenDeleteModal(true)}/>
</div>
{openEditModal && <EditModal onClose={() => setOpenEditModal(false)} workspace={workspace} />}
{openDeleteModal && <DeleteModal onClose={() => setOpenDeleteModal(false)} workspace={workspace} />}
</div>
</StyledWrapper>
)
}
export default WorkspaceItem;

View File

@@ -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 (
<Modal
size="md"
title="Workspaces"
confirmText="Create"
handleConfirm={onSubmit}
confirmText={"+ New Workspace"}
handleConfirm={() => setOpenAddModal(true)}
handleCancel={onClose}
hideCancel={true}
>
<ul className="mb-2">
{workspaces && workspaces.length && workspaces.map((workspace) => (
<div className="flex justify-between items-baseline w-4/5 mb-2">
<li key={workspace.uid}>{workspace.name}</li>
<button
style={{backgroundColor: "var(--color-brand)"}}
className="flex items-center h-full text-white active:bg-blue-600 font-bold text-xs px-4 py-2 ml-2 uppercase rounded shadow hover:shadow-md outline-none focus:outline-none ease-linear transition-all duration-150"
onClick={() => console.log("delete")}
>
<span style={{marginLeft: 5}}>Delete</span>
</button>
</div>
))}
<ul className="mb-2" >
{workspaces && workspaces.length && workspaces.map((workspace) => (
<WorkspaceItem workspace={workspace} />
))}
</ul>
{openAddModal && <AddModal onClose={() => setOpenAddModal(false)}/>}
</Modal>
)