Skip to content

Commit

Permalink
feat: add workspace added
Browse files Browse the repository at this point in the history
  • Loading branch information
yp969803 committed Dec 23, 2023
1 parent 46cdf0e commit 03e0ac1
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 11 deletions.
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"eslint-config-prettier": "^9.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-query": "^3.39.3",
"react-redux": "^8.1.3",
"react-router-dom": "^6.16.0",
Expand Down
18 changes: 15 additions & 3 deletions src/app/api/file.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { BACKEND_URL } from 'envConstants';


export interface FileUpload{

message: string,
isSuccessful: boolean,
statusCode: number,

}




export const uploadIcon = async (
authorizationToken: string,
orgName: string,
file: File
) => {
):Promise<AxiosResponse<FileUpload>> => {
const url = BACKEND_URL + '/api/protected/file/upload/' + orgName;
const formData = new FormData();
formData.append('file', file);
const respnse = await axios.post(url, formData, {
const respnse = await axios.post<FileUpload>(url, formData, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${authorizationToken}`,
Expand Down
15 changes: 12 additions & 3 deletions src/app/api/organization.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { BACKEND_URL } from 'envConstants';

export interface organizationBody {
name: string;
description: string;
}


export interface AllOrgs{
organizations: {
id: number,
name: string,
description: string|null
}[]
}

export const deleteOrg = async (
authorizationToken: string,
orgName: string
Expand Down Expand Up @@ -195,9 +204,9 @@ export const getOrg = async (authorizationToken: string, orgName: string) => {
return respnse;
};

export const getAllOrgs = async (authorizationToken: string) => {
export const getAllOrgs = async (authorizationToken: string): Promise<AxiosResponse<AllOrgs>> => {
const url = BACKEND_URL + '/api/protected/org/getAllOrg';
const respnse = await axios.get(url, {
const respnse = await axios.get<AllOrgs>(url, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${authorizationToken}`,
Expand Down
12 changes: 10 additions & 2 deletions src/app/api/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ export interface UserData{
}



export interface AllUserData{
users: {
id: number,
username: string
}[]
}

export const getUser= async (authorizationToken: string):Promise<AxiosResponse<UserData>> => {
const url = BACKEND_URL + '/api/protected/user/getUser';

Expand All @@ -24,9 +32,9 @@ export const getUser= async (authorizationToken: string):Promise<AxiosResponse<U

};

export const getAllUser = async (authorizationToken: string) => {
export const getAllUser = async (authorizationToken: string):Promise<AxiosResponse<AllUserData>> => {
const url = BACKEND_URL + '/api/protected/user/all';
const respnse = await axios.get(url, {
const respnse = await axios.get<AllUserData>(url, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${authorizationToken}`,
Expand Down
3 changes: 2 additions & 1 deletion src/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import React from 'react';
import Navbar from 'app/components/navbar';
import BasicRoutes from 'app/routes/BasicRoutes';
import './index.scss';

import { Toaster } from 'react-hot-toast';
function App() {
return (
<>
<Navbar />
<BasicRoutes />
<Toaster/>
</>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/routes/BasicRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import AddProject from 'features/AddProject';
import Error from 'features/Error';
import WorkspaceView from 'features/workspace-view';
import Login from 'features/login';
import AddWorkspace from 'features/AddWorkspace';
const BasicRoutes = () => {
return (
<Routes>
Expand All @@ -14,6 +15,7 @@ const BasicRoutes = () => {
<Route path={'/addproject'} element={<AddProject />} />
<Route path={'/workspace-view'} element={<WorkspaceView />} />
<Route path={'/login'} element={<Login />} />
<Route path={'/addWorkspace'} element={<AddWorkspace />} />
<Route path={'/*'} element={<Error />} />
</Routes>
);
Expand Down
1 change: 1 addition & 0 deletions src/app/state/action-creators/usersActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export const setAllUsernames = (usernames: string[]) => {
});
};
};

188 changes: 188 additions & 0 deletions src/features/AddWorkspace/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { getAllUser, getUser } from 'app/api/user';
import React, { ChangeEvent, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQuery } from 'react-query';
import toast from 'react-hot-toast';
import { addOrg, getAllOrgs } from 'app/api/organization';
import { uploadIcon } from 'app/api/file';

const AddWorkspace = () => {
const navigate = useNavigate();
const token = localStorage.getItem('token');

const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [name, SetName] = useState<string | null>(null);
const [description, setDiscription] = useState<string | null>(null);
const [validName, setValidName] = useState<boolean>(false);

const [members, setMembers] = useState<string[]>([]);
const [memberName, setMemberName]=useState<string| null>(null);

const [users, setUsers] = useState<string[]>([]);
const [orgs, setOrgs] = useState<string[]>([]);

const dataFetch = async () => {
try {
if (token) {
const users_aray: string[] = [];
const org_aray: string[] = [];
const allUser = await getAllUser(token);
const allOrgs = await getAllOrgs(token);
allUser.data.users.forEach((user) => {
users_aray.push(user.username);
});

allOrgs.data.organizations.forEach((org) => {
org_aray.push(org.name);
});

setUsers(users_aray);
setOrgs(org_aray);
}
} catch (e) {}
};

const checklogin = async () => {
if (token != null) {
const userData = await getUser(token);
return userData.data
} else {
toast.error("Session expired")
navigate('/login');
}
};

const { data,isError } = useQuery({
queryFn: () => checklogin(),
queryKey: 'checkLogin',
});

if (isError) {
toast.error("Session expired")
navigate('/login');
}

const {} = useQuery({
queryFn: () => dataFetch(),
queryKey: 'allUsersAndAllOrgs',
});

const allowedFieTypes = ['image/jpeg', 'image/jpg', 'image/png'];

const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];

if (file) {
if (allowedFieTypes.includes(file.type)) {
setSelectedFile(file);
} else {
setSelectedFile(null);
toast.error('Invalid file type');
}
}
};

function valid_name(str: string): boolean {
// Define a regular expression for special characters (excluding letters, digits, and spaces)
const specialCharacters = /[^a-zA-Z0-9\s]/;

// Check if the string contains any special characters
return (
specialCharacters.test(str) &&
!str.endsWith('/userspace') &&
!orgs.includes(str)
);
}

const handleNameChange = (event: ChangeEvent<HTMLInputElement>) => {
SetName(event.target.value);

setValidName(() => valid_name(event.target.value));
};

const handleDesriptionChange = (event: ChangeEvent<HTMLInputElement>) => {
setDiscription(event.target.value);
};

const addMembers= ()=>{
if(memberName){
if(users.includes(memberName)&& memberName!=data?.message){
setMembers([...members,memberName])
setMemberName(null)
}
}
}


const SubmitHandler=async():Promise<void>=>{


if(validName&&description&&token&&name){
try{
const dataRes= await addOrg(token,{
name:name,
description:description
})

}catch(e){
toast.error('Try again!')
return
}
try{
if(selectedFile!=null){
const fileRes= uploadIcon(token, name, selectedFile)
}
navigate("/workspace-view")

}catch(e){
navigate("/workspace-view")
}
}else{
toast.error('Invalid inputs')
}


}

toast.promise(
SubmitHandler(),
{
loading: 'Saving Workspace',
success: <b>Workspace saved</b>,
error: <b>Could not save</b>,
}
);


return (
<div>
<input type='file' onChange={handleFileChange} />

<p>Selected File: {selectedFile?.name}</p>
<input
type='text'
value={name ? name : ''}
onChange={handleNameChange}
placeholder='Enter name'
/>
<input
type='text'
value={description ? description : ''}
onChange={handleDesriptionChange}
placeholder='Enter Description'
/>

<input
type='text'
value={memberName ? memberName : ''}
onChange={(e:ChangeEvent<HTMLInputElement>)=>{setMemberName(e.target.value)}}
placeholder='Enter membername'
/>
<button onClick={addMembers} disabled={memberName?!users.includes(memberName)&& memberName==data?.message:true}>Add Memeber</button>
<p>{members}</p>
<button onClick={SubmitHandler}>Submit</button>
</div>
);
};

export default AddWorkspace;
Loading

0 comments on commit 03e0ac1

Please sign in to comment.