From 4b8c00f2a7e46f58be98584e580e171cd65ffc70 Mon Sep 17 00:00:00 2001 From: Leon <> Date: Wed, 2 Feb 2022 13:22:10 +0200 Subject: [PATCH] edit page - insert data bug --- .../Modals/AddUserModal/AddUserModal.sass | 1 - .../Modals/AddUserModal/AddUserModal.tsx | 24 +++++++++------ .../AddWorkspaceModal/AddWorkspaceModal.tsx | 2 +- .../Pages/SettingsPage/SettingsPage.sass | 4 ++- .../components/SettingsModal/SettingModal.tsx | 2 +- .../SettingsModal/SettingsModal.sass | 2 +- .../components/UI/FilterableTableAction.tsx | 5 ++-- ui/src/components/UI/Table.tsx | 18 ++++++++---- .../UI/style/FilterableTableAction.sass | 7 ++--- ui/src/components/UI/style/Table.sass | 13 ++++++++- .../components/UserSettings/UserSettings.sass | 10 ++----- .../components/UserSettings/UserSettings.tsx | 15 +++++----- ui/src/helpers/FormService.ts | 8 +++++ ui/src/helpers/Utils.ts | 5 ++++ ui/src/helpers/api.js | 29 +++++++++++++++++++ 15 files changed, 103 insertions(+), 42 deletions(-) create mode 100644 ui/src/helpers/FormService.ts create mode 100644 ui/src/helpers/Utils.ts diff --git a/ui/src/components/Modals/AddUserModal/AddUserModal.sass b/ui/src/components/Modals/AddUserModal/AddUserModal.sass index 1ef2939f4..5b33cbc3d 100644 --- a/ui/src/components/Modals/AddUserModal/AddUserModal.sass +++ b/ui/src/components/Modals/AddUserModal/AddUserModal.sass @@ -48,7 +48,6 @@ & .user__email width : 300px - height: 30px; box-sizing: border-box; & .user__role diff --git a/ui/src/components/Modals/AddUserModal/AddUserModal.tsx b/ui/src/components/Modals/AddUserModal/AddUserModal.tsx index 76f7778ee..cb6e31962 100644 --- a/ui/src/components/Modals/AddUserModal/AddUserModal.tsx +++ b/ui/src/components/Modals/AddUserModal/AddUserModal.tsx @@ -1,4 +1,4 @@ -import { Button, FormControl, IconButton, InputAdornment, InputLabel, MenuItem, OutlinedInput,Select } from '@material-ui/core'; +import { Button, FormControl, IconButton, InputAdornment, InputLabel, MenuItem, OutlinedInput,Select, TextField } from '@material-ui/core'; import { FC, useEffect, useState } from 'react'; import Api from '../../../helpers/api'; @@ -8,6 +8,10 @@ import {toast} from "react-toastify"; import SelectList from '../../UI/SelectList'; import './AddUserModal.sass'; import spinner from "../../assets/spinner.svg"; +import {FormService} from "../../../helpers/FormService" +import {RouterRoutes} from "../../../helpers/routes"; +import {Utils} from "../../../helpers/Utils" + export type UserData = { role:string; @@ -25,6 +29,7 @@ interface AddUserModalProps { } const api = Api.getInstance(); +const fromService = new FormService() export const AddUserModal: FC = ({isOpen, onCloseModal, userData, isEditMode,onUserChange}) => { @@ -127,7 +132,7 @@ export const AddUserModal: FC = ({isOpen, onCloseModal, userD const mapTokenToLink = (token) => { - return`${window.location.origin}/${token}` + return`${window.location.origin}/${RouterRoutes.SETUP}/${token}` } const generateLink = async() => { @@ -170,7 +175,7 @@ export const AddUserModal: FC = ({isOpen, onCloseModal, userD - + {} @@ -214,9 +219,10 @@ export const AddUserModal: FC = ({isOpen, onCloseModal, userD placeholder={"User Email"} onChange={userNameChange} disabled={editMode}/> */} - User Name - + User email + + {/* {!fromService.isValidEmail(userDataModel?.username) && } */} {/* = ({isOpen, onCloseModal, userD {/* className='user__role u-input-padding' */} {/* classes={{ select : 'u-input-padding' }} */} - + User role @@ -244,7 +250,7 @@ export const AddUserModal: FC = ({isOpen, onCloseModal, userD

WORKSPACE ACCESS

-
+
setSearchValue(event.target.value)}/>
diff --git a/ui/src/components/Modals/AddWorkspaceModal/AddWorkspaceModal.tsx b/ui/src/components/Modals/AddWorkspaceModal/AddWorkspaceModal.tsx index cfcfb5fd9..5a6fdc747 100644 --- a/ui/src/components/Modals/AddWorkspaceModal/AddWorkspaceModal.tsx +++ b/ui/src/components/Modals/AddWorkspaceModal/AddWorkspaceModal.tsx @@ -105,7 +105,7 @@ const AddWorkspaceModal: FC = ({isOpen,onCloseModal, work

TAP SETTINGS

-
+
setSearchValue(event.target.value)}/>
diff --git a/ui/src/components/Pages/SettingsPage/SettingsPage.sass b/ui/src/components/Pages/SettingsPage/SettingsPage.sass index 2a697e7a5..630b2ffbd 100644 --- a/ui/src/components/Pages/SettingsPage/SettingsPage.sass +++ b/ui/src/components/Pages/SettingsPage/SettingsPage.sass @@ -38,4 +38,6 @@ height: 100vh; &__container @include tab-container - \ No newline at end of file + +.table-body-style + background: $main-background-color \ No newline at end of file diff --git a/ui/src/components/SettingsModal/SettingModal.tsx b/ui/src/components/SettingsModal/SettingModal.tsx index 0dfbb9ad1..97d8cf397 100644 --- a/ui/src/components/SettingsModal/SettingModal.tsx +++ b/ui/src/components/SettingsModal/SettingModal.tsx @@ -94,7 +94,7 @@ export const SettingsModal: React.FC = ({isOpen, onClose, is spinner
: <>
-
+
setSearchValue(event.target.value)}/>
diff --git a/ui/src/components/SettingsModal/SettingsModal.sass b/ui/src/components/SettingsModal/SettingsModal.sass index 2b27914aa..2ef27871f 100644 --- a/ui/src/components/SettingsModal/SettingsModal.sass +++ b/ui/src/components/SettingsModal/SettingsModal.sass @@ -13,7 +13,7 @@ .namespacesSettingsContainer border-radius: 4px - padding: 20px 0 + .searchNamespace width: 300px diff --git a/ui/src/components/UI/FilterableTableAction.tsx b/ui/src/components/UI/FilterableTableAction.tsx index 3369c525c..cab7eeac3 100644 --- a/ui/src/components/UI/FilterableTableAction.tsx +++ b/ui/src/components/UI/FilterableTableAction.tsx @@ -16,9 +16,10 @@ export interface Props { buttonConfig : {onClick : () => void, text:string} rows: any[]; cols: ColsType[]; + bodyClass?: string; } -export const FilterableTableAction: React.FC = ({onRowDelete,onRowEdit, searchConfig, buttonConfig, rows, cols}) => { +export const FilterableTableAction: React.FC = ({onRowDelete,onRowEdit, searchConfig, buttonConfig, rows, cols, bodyClass}) => { const classes = useCommonStyles() @@ -57,7 +58,7 @@ export const FilterableTableAction: React.FC = ({onRowDelete,onRowEdit, s {buttonConfig.text}
-
+
); }; \ No newline at end of file diff --git a/ui/src/components/UI/Table.tsx b/ui/src/components/UI/Table.tsx index 53cae6679..9b98c5c4d 100644 --- a/ui/src/components/UI/Table.tsx +++ b/ui/src/components/UI/Table.tsx @@ -2,6 +2,7 @@ import React, {useEffect, useState} from "react"; import './style/Table.sass'; import Delete from '@material-ui/icons/Delete'; import Edit from '@material-ui/icons/Edit'; +import circleImg from '../assets/dotted-circle.svg'; export interface ColsType { field:string, @@ -9,6 +10,7 @@ export interface ColsType { header:string, width?:string, getCellClassName?:(field:string,value : any) => string + mapValue? : (val : any) => any }; interface TableProps { @@ -17,9 +19,10 @@ interface TableProps { onRowEdit : (any) => void; onRowDelete : (any) => void; noDataMeesage? : string; + bodyClass?: string; } -export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, noDataMeesage = "No Data Found"}) => { +export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, noDataMeesage = "No Data Found",bodyClass}) => { const [tableRows, updateTableRows] = useState(rows); @@ -48,12 +51,17 @@ export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, - + { ((tableRows == null) || (tableRows.length === 0)) ? - {/* No data Found -
{noDataMeesage}
*/} + +
+ No data Found +
{noDataMeesage}
+
+ + : @@ -63,7 +71,7 @@ export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, {cols.map((col,index) => { return - {rowData[col.field]} + {col.mapValue ? col.mapValue(rowData[col.field]) : rowData[col.field]} })} diff --git a/ui/src/components/UI/style/FilterableTableAction.sass b/ui/src/components/UI/style/FilterableTableAction.sass index 73ebe4d4c..8fbb9811e 100644 --- a/ui/src/components/UI/style/FilterableTableAction.sass +++ b/ui/src/components/UI/style/FilterableTableAction.sass @@ -1,15 +1,14 @@ @import '../../../variables.module' .filterable-table - - -.actions-header + +.actions-header display: flex; justify-content: space-between; &__search-box - width : 313px; + width: clamp(300px, 60%, 400px) &__action-button height: 100% \ No newline at end of file diff --git a/ui/src/components/UI/style/Table.sass b/ui/src/components/UI/style/Table.sass index 011e2cb42..d1fbbc2b9 100644 --- a/ui/src/components/UI/style/Table.sass +++ b/ui/src/components/UI/style/Table.sass @@ -30,13 +30,24 @@ justify-content: space-between; flex-direction: column; height: 95px; - overflow-y: auto; margin: 2%; align-items: center; align-content: center; padding-top: 3%; padding-bottom: 3%; + & td + width: 100% + + & .container + display: flex; + justify-content: space-between; + flex-direction: column; + height: 95px; + margin: 1%; + align-items: center; + align-content: center; + &-message font-style: normal; font-weight: 600; diff --git a/ui/src/components/UserSettings/UserSettings.sass b/ui/src/components/UserSettings/UserSettings.sass index 99a48aadc..8f63cc7f3 100644 --- a/ui/src/components/UserSettings/UserSettings.sass +++ b/ui/src/components/UserSettings/UserSettings.sass @@ -12,17 +12,11 @@ background: $bg_color color: $color border: $border + padding: 12px 19px; .status &--active @include status-base(rgba(111, 207, 151, 0.5), #247E4B, 1px solid #219653) &--pending - @include status-base(rgba(242, 201, 76, 0.5), #8C7325, 1px solid #F2994A) - -.alert--right.MuiSnackbar-root - display: flex; - justify-content: flex-end; - left: auto; - right: 1vw; - transform: unset; \ No newline at end of file + @include status-base(rgba(242, 201, 76, 0.5), #8C7325, 1px solid #F2994A) \ No newline at end of file diff --git a/ui/src/components/UserSettings/UserSettings.tsx b/ui/src/components/UserSettings/UserSettings.tsx index 9021c7074..07573fb38 100644 --- a/ui/src/components/UserSettings/UserSettings.tsx +++ b/ui/src/components/UserSettings/UserSettings.tsx @@ -6,6 +6,8 @@ import { UserData,AddUserModal } from "../Modals/AddUserModal/AddUserModal"; import Api from '../../helpers/api'; import { toast } from "react-toastify"; import ConfirmationModal from "../UI/Modals/ConfirmationModal"; +import {Utils} from "../../helpers/Utils" + interface Props { @@ -23,7 +25,7 @@ export const UserSettings : React.FC = ({}) => { const [usersRows, setUserRows] = useState([]); const [userData,userUserData] = useState({} as UserData) const cols : ColsType[] = [{field : "username",header:"User", width: '35%'}, - {field : "role",header:"Role"}, + {field : "role",header:"Role",mapValue : (val) => Utils.capitalizeFirstLetter(val)}, {field : "status",header:"Status",getCellClassName : (field, val) =>{ return val === InviteStatus.active ? "status--active" : "status--pending" }}] @@ -36,8 +38,9 @@ export const UserSettings : React.FC = ({}) => { // let users = [{username:"asd",role:"Admin",status:"Active",userId : "1"}, // {username:"asdasdasdasdasdasd",role:"User",status:"Active",userId : "2"}] let users = await api.getUsers() - const mappedUsers = users.map((user) => { - return {...user,status: capitalizeFirstLetter(user.status), role: capitalizeFirstLetter(user.role)} + const mappedUsers = users + .map((user) => { + return {...user,status: Utils.capitalizeFirstLetter(user.status), role: user.role} }) setUserRows(mappedUsers) } catch (e) { @@ -50,10 +53,6 @@ export const UserSettings : React.FC = ({}) => { getUserList(); },[]) - function capitalizeFirstLetter(string) { - return string.charAt(0).toUpperCase() + string.slice(1); - } - const filterFuncFactory = (searchQuery: string) => { return (row) => { return row.username.toLowerCase().includes(searchQuery.toLowerCase()) || @@ -103,7 +102,7 @@ export const UserSettings : React.FC = ({}) => { return (<> + buttonConfig={buttonConfig} rows={usersRows} cols={cols} bodyClass="table-body-style"> { setIsOpen(false);userUserData({} as UserData) } } diff --git a/ui/src/helpers/FormService.ts b/ui/src/helpers/FormService.ts new file mode 100644 index 000000000..81f4b76bf --- /dev/null +++ b/ui/src/helpers/FormService.ts @@ -0,0 +1,8 @@ +export class FormService{ + + EMAIL_REGEXP = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" + + isValidEmail = (email : string) => { + return new RegExp(this.EMAIL_REGEXP).test(email) + } +} \ No newline at end of file diff --git a/ui/src/helpers/Utils.ts b/ui/src/helpers/Utils.ts new file mode 100644 index 000000000..c13043b93 --- /dev/null +++ b/ui/src/helpers/Utils.ts @@ -0,0 +1,5 @@ +export class Utils{ + static capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + } +} \ No newline at end of file diff --git a/ui/src/helpers/api.js b/ui/src/helpers/api.js index 65349201c..620c89bee 100644 --- a/ui/src/helpers/api.js +++ b/ui/src/helpers/api.js @@ -48,6 +48,8 @@ export default class Api { return response.data; } + //#region User api + getUsers = async(filter = "") =>{ const response = await this.client.get(`/user/listUsers?usernameFilter=${filter}`); return response.data; @@ -68,6 +70,28 @@ export default class Api { return response.data; } + recoverUser = async(data) => { + const form = new FormData(); + form.append('password', data.password); + form.append('inviteToken', data.inviteToken); + + try { + const response = await this.client.post(`/user/recover`, form); + this.persistToken(response.data.token); + return response; + } catch (e) { + if (e.response.status === 400) { + const error = { + 'type': FormValidationErrorType, + 'messages': e.response.data + }; + throw error; + } else { + throw e; + } + } + } + inviteExistingUser = async(userId) =>{ const response = await this.client.post(`/user/${userId}/invite`); return response.data; @@ -78,6 +102,9 @@ export default class Api { return response.data; } + //#endregion + + //#region Workspace api getWorkspaces = async() =>{ const response = await this.client.get(`/workspace/`); return response.data; @@ -108,6 +135,8 @@ export default class Api { return response.data; } + //#endregion + analyzeStatus = async () => { const response = await this.client.get("/status/analyze"); return response.data;