1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-19 00:15:43 +01:00

refactor: misc type improvements (#945)

* refactor: improve ChangePassword types

* refactor: improve usePagination types

* refactor: improve UsersList types
This commit is contained in:
olav 2022-05-04 08:14:49 +02:00 committed by GitHub
parent 73d2b73955
commit 7b60ef2aa6
5 changed files with 51 additions and 74 deletions

View File

@ -1,6 +1,6 @@
import { useState } from 'react'; import React, { useState } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import { Avatar, TextField, Typography } from '@mui/material'; import { Avatar, TextField, Typography, Alert } from '@mui/material';
import { trim } from 'component/common/util'; import { trim } from 'component/common/util';
import { modalStyles } from 'component/admin/users/util'; import { modalStyles } from 'component/admin/users/util';
import { Dialogue } from 'component/common/Dialogue/Dialogue'; import { Dialogue } from 'component/common/Dialogue/Dialogue';
@ -8,42 +8,35 @@ import PasswordChecker from 'component/user/common/ResetPasswordForm/PasswordChe
import { useThemeStyles } from 'themes/themeStyles'; import { useThemeStyles } from 'themes/themeStyles';
import PasswordMatcher from 'component/user/common/ResetPasswordForm/PasswordMatcher/PasswordMatcher'; import PasswordMatcher from 'component/user/common/ResetPasswordForm/PasswordMatcher/PasswordMatcher';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { Alert } from '@mui/material';
import { IUser } from 'interfaces/user'; import { IUser } from 'interfaces/user';
interface IChangePasswordProps { interface IChangePasswordProps {
showDialog: boolean; showDialog: boolean;
closeDialog: () => void; closeDialog: () => void;
changePassword: (user: IUser, password: string) => Promise<Response>; changePassword: (userId: number, password: string) => Promise<Response>;
user: Partial<IUser>; user: IUser;
} }
const ChangePassword = ({ const ChangePassword = ({
showDialog, showDialog,
closeDialog, closeDialog,
changePassword, changePassword,
user = {}, user,
}: IChangePasswordProps) => { }: IChangePasswordProps) => {
const [data, setData] = useState({}); const [data, setData] = useState<Record<string, string>>({});
const [error, setError] = useState<Record<string, string>>({}); const [error, setError] = useState<Record<string, string>>({});
const [validPassword, setValidPassword] = useState(false); const [validPassword, setValidPassword] = useState(false);
const { classes: themeStyles } = useThemeStyles(); const { classes: themeStyles } = useThemeStyles();
// @ts-expect-error const updateField: React.ChangeEventHandler<HTMLInputElement> = event => {
const updateField = e => {
setError({}); setError({});
setData({ setData({ ...data, [event.target.name]: trim(event.target.value) });
...data,
[e.target.name]: trim(e.target.value),
});
}; };
// @ts-expect-error const submit = async (event: React.SyntheticEvent) => {
const submit = async e => { event.preventDefault();
e.preventDefault();
if (!validPassword) { if (!validPassword) {
// @ts-expect-error
if (!data.password || data.password.length < 8) { if (!data.password || data.password.length < 8) {
setError({ setError({
password: password:
@ -51,7 +44,6 @@ const ChangePassword = ({
}); });
return; return;
} }
// @ts-expect-error
if (!(data.password === data.confirm)) { if (!(data.password === data.confirm)) {
setError({ confirm: 'Passwords does not match' }); setError({ confirm: 'Passwords does not match' });
return; return;
@ -59,20 +51,19 @@ const ChangePassword = ({
} }
try { try {
// @ts-expect-error await changePassword(user.id, data.password);
await changePassword(user, data.password);
setData({}); setData({});
closeDialog(); closeDialog();
} catch (error) { } catch (error: unknown) {
// @ts-expect-error const msg =
const msg = error.message || 'Could not update password'; (error instanceof Error && error.message) ||
'Could not update password';
setError({ general: msg }); setError({ general: msg });
} }
}; };
// @ts-expect-error const onCancel = (event: React.SyntheticEvent) => {
const onCancel = e => { event.preventDefault();
e.preventDefault();
setData({}); setData({});
closeDialog(); closeDialog();
}; };
@ -118,7 +109,6 @@ const ChangePassword = ({
</Typography> </Typography>
</div> </div>
<PasswordChecker <PasswordChecker
// @ts-expect-error
password={data.password} password={data.password}
callback={setValidPassword} callback={setValidPassword}
/> />
@ -126,7 +116,6 @@ const ChangePassword = ({
label="New password" label="New password"
name="password" name="password"
type="password" type="password"
// @ts-expect-error
value={data.password} value={data.password}
helperText={error.password} helperText={error.password}
onChange={updateField} onChange={updateField}
@ -137,7 +126,6 @@ const ChangePassword = ({
label="Confirm password" label="Confirm password"
name="confirm" name="confirm"
type="password" type="password"
// @ts-expect-error
value={data.confirm} value={data.confirm}
error={error.confirm !== undefined} error={error.confirm !== undefined}
helperText={error.confirm} helperText={error.confirm}
@ -146,9 +134,7 @@ const ChangePassword = ({
size="small" size="small"
/> />
<PasswordMatcher <PasswordMatcher
// @ts-expect-error started={Boolean(data.password && data.confirm)}
started={data.password && data.confirm}
// @ts-expect-error
matchingPasswords={data.password === data.confirm} matchingPasswords={data.password === data.confirm}
/> />
</form> </form>

View File

@ -39,13 +39,8 @@ const UsersList = ({ search }: IUsersListProps) => {
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const { users, roles, refetch, loading } = useUsers(); const { users, roles, refetch, loading } = useUsers();
const { setToastData, setToastApiError } = useToast(); const { setToastData, setToastApiError } = useToast();
const { const { removeUser, changePassword, userLoading, userApiErrors } =
removeUser, useAdminUsersApi();
changePassword,
validatePassword,
userLoading,
userApiErrors,
} = useAdminUsersApi();
const { hasAccess } = useContext(AccessContext); const { hasAccess } = useContext(AccessContext);
const { locationSettings } = useLocationSettings(); const { locationSettings } = useLocationSettings();
const [pwDialog, setPwDialog] = useState<{ open: boolean; user?: IUser }>({ const [pwDialog, setPwDialog] = useState<{ open: boolean; user?: IUser }>({
@ -87,12 +82,11 @@ const UsersList = ({ search }: IUsersListProps) => {
setPwDialog({ open: false }); setPwDialog({ open: false });
}; };
const onDeleteUser = async () => { const onDeleteUser = async (user: IUser) => {
try { try {
// @ts-expect-error await removeUser(user.id);
await removeUser(delUser);
setToastData({ setToastData({
title: `${delUser?.name} has been deleted`, title: `${user.name} has been deleted`,
type: 'success', type: 'success',
}); });
refetch(); refetch();
@ -131,7 +125,6 @@ const UsersList = ({ search }: IUsersListProps) => {
return page.map(user => { return page.map(user => {
return ( return (
<UserListItem <UserListItem
// @ts-expect-error
key={user.id} key={user.id}
user={user} user={user}
openPwDialog={openPwDialog} openPwDialog={openPwDialog}
@ -224,16 +217,17 @@ const UsersList = ({ search }: IUsersListProps) => {
inviteLink={inviteLink} inviteLink={inviteLink}
/> />
<ChangePassword <ConditionallyRender
showDialog={pwDialog.open} condition={Boolean(pwDialog.user)}
closeDialog={closePwDialog} show={() => (
// @ts-expect-error <ChangePassword
changePassword={changePassword} showDialog={pwDialog.open}
validatePassword={validatePassword} closeDialog={closePwDialog}
// @ts-expect-error changePassword={changePassword}
user={pwDialog.user} user={pwDialog.user!}
/>
)}
/> />
<ConditionallyRender <ConditionallyRender
condition={Boolean(delUser)} condition={Boolean(delUser)}
show={ show={
@ -241,7 +235,7 @@ const UsersList = ({ search }: IUsersListProps) => {
showDialog={delDialog} showDialog={delDialog}
closeDialog={closeDelDialog} closeDialog={closeDelDialog}
user={delUser!} user={delUser!}
removeUser={onDeleteUser} removeUser={() => onDeleteUser(delUser!)}
userLoading={userLoading} userLoading={userLoading}
userApiErrors={userApiErrors} userApiErrors={userApiErrors}
/> />

View File

@ -11,14 +11,12 @@ import { useStyles } from './FeatureToggleListNew.styles';
import FeatureToggleListNewItem from './FeatureToggleListNewItem/FeatureToggleListNewItem'; import FeatureToggleListNewItem from './FeatureToggleListNewItem/FeatureToggleListNewItem';
import usePagination from 'hooks/usePagination'; import usePagination from 'hooks/usePagination';
import loadingFeatures from './FeatureToggleListNewItem/loadingFeatures'; import loadingFeatures from './FeatureToggleListNewItem/loadingFeatures';
import { import { IFeatureToggleListItem } from 'interfaces/featureToggle';
IFeatureToggle,
IFeatureToggleListItem,
} from 'interfaces/featureToggle';
import PaginateUI from 'component/common/PaginateUI/PaginateUI'; import PaginateUI from 'component/common/PaginateUI/PaginateUI';
import StringTruncator from 'component/common/StringTruncator/StringTruncator'; import StringTruncator from 'component/common/StringTruncator/StringTruncator';
import { createGlobalStateHook } from 'hooks/useGlobalState'; import { createGlobalStateHook } from 'hooks/useGlobalState';
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext'; import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
interface IFeatureToggleListNewProps { interface IFeatureToggleListNewProps {
features: IFeatureToggleListItem[]; features: IFeatureToggleListItem[];
loading: boolean; loading: boolean;
@ -86,9 +84,10 @@ const FeatureToggleListNew = ({
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const { setAnnouncement } = useContext(AnnouncerContext); const { setAnnouncement } = useContext(AnnouncerContext);
const [sortOpt, setSortOpt] = useFeatureToggLeProjectSort(); const [sortOpt, setSortOpt] = useFeatureToggLeProjectSort();
const [sortedFeatures, setSortedFeatures] = useState(
sortList([...features], sortOpt) const [sortedFeatures, setSortedFeatures] = useState<
); IFeatureToggleListItem[]
>(sortList([...features], sortOpt));
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } = const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
usePagination(sortedFeatures, 50); usePagination(sortedFeatures, 50);
@ -156,7 +155,7 @@ const FeatureToggleListNew = ({
}); });
} }
return page.map((feature: IFeatureToggle) => { return page.map((feature: IFeatureToggleListItem) => {
return ( return (
<FeatureToggleListNewItem <FeatureToggleListNewItem
key={feature.name} key={feature.name}

View File

@ -36,13 +36,11 @@ const useAdminUsersApi = () => {
return makeRequest(req.caller, req.id); return makeRequest(req.caller, req.id);
}; };
const removeUser = async (user: IUserPayload) => { const removeUser = async (userId: number) => {
const requestId = 'removeUser'; const requestId = 'removeUser';
const req = createRequest( const req = createRequest(
`api/admin/user-admin/${user.id}`, `api/admin/user-admin/${userId}`,
{ { method: 'DELETE' },
method: 'DELETE',
},
requestId requestId
); );
@ -63,10 +61,10 @@ const useAdminUsersApi = () => {
return makeRequest(req.caller, req.id); return makeRequest(req.caller, req.id);
}; };
const changePassword = async (user: IUserPayload, password: string) => { const changePassword = async (userId: number, password: string) => {
const requestId = 'changePassword'; const requestId = 'changePassword';
const req = createRequest( const req = createRequest(
`api/admin/user-admin/${user.id}/change-password`, `api/admin/user-admin/${userId}/change-password`,
{ {
method: 'POST', method: 'POST',
body: JSON.stringify({ password }), body: JSON.stringify({ password }),

View File

@ -1,12 +1,12 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { paginate } from '../utils/paginate'; import { paginate } from 'utils/paginate';
const usePagination = ( const usePagination = <T>(
data: any[], data: T[],
limit: number, limit: number,
filterFunc?: (item: any) => boolean filterFunc?: (item: T) => boolean
) => { ) => {
const [paginatedData, setPaginatedData] = useState([[]]); const [paginatedData, setPaginatedData] = useState<T[][]>([[]]);
const [pageIndex, setPageIndex] = useState(0); const [pageIndex, setPageIndex] = useState(0);
useEffect(() => { useEffect(() => {