Skip to content

Commit

Permalink
Implement marking users offline in users view (#1112)
Browse files Browse the repository at this point in the history
* Fix the issue (#958)

* Revert "Fix the issue (#958)"

This reverts commit 2dee8af.

* Add external authorization to Chatbot

* Update .guard

Fix missing quotes & broken step

* Implement marking users offline in users view

* Remove unintentionally commited changes

---------

Co-authored-by: Igor Krupenja <igor.krupenja@gmail.com>
Co-authored-by: Ahmed yasser <26207361+1AhmedYasser@users.noreply.github.com>
Co-authored-by: Varmo <101868197+varmoh@users.noreply.github.com>
Co-authored-by: RayDNoper <alar.floren@bpw-consulting.com>
  • Loading branch information
5 people authored Jan 15, 2025
1 parent ee03278 commit 0873038
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 64 deletions.
7 changes: 1 addition & 6 deletions GUI/src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,14 @@ import { AUTHORITY } from 'types/authorities';
import { useCookies } from 'react-cookie';
import { useDing } from 'hooks/useAudio';
import './Header.scss';
import { CustomerSupportActivityDTO } from 'types/customerSupportActivity';

type CustomerSupportActivity = {
idCode: string;
active: true;
status: string;
};

type CustomerSupportActivityDTO = {
customerSupportActive: boolean;
customerSupportStatus: 'offline' | 'idle' | 'online';
customerSupportId: string;
};

const statusColors: Record<string, string> = {
idle: '#FFB511',
online: '#308653',
Expand Down
193 changes: 137 additions & 56 deletions GUI/src/pages/Settings/SettingsUsers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import {FC, useEffect, useMemo, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {useMutation} from '@tanstack/react-query';
import {ColumnFiltersState, createColumnHelper, PaginationState, Row, SortingState,} from '@tanstack/react-table';
import {AxiosError} from 'axios';
import {MdOutlineDeleteOutline, MdOutlineEdit} from 'react-icons/md';
import {apiDev} from 'services/api';
import {Button, Card, DataTable, Dialog, Icon, Track} from 'components';
import {User, UserSearchFilters} from 'types/user';
import {deleteUser} from 'services/users';
import {useToast} from 'hooks/useToast';
import { FC, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import {
ColumnFiltersState,
PaginationState,
Row,
SortingState,
createColumnHelper,
} from '@tanstack/react-table';
import { AxiosError } from 'axios';
import { MdOutlineEdit, MdOutlineDeleteOutline } from 'react-icons/md';
import { apiDev } from 'services/api';
import { Button, Card, DataTable, Dialog, Icon, Track } from 'components';
import { User, UserSearchFilters } from 'types/user';
import { deleteUser } from 'services/users';
import { useToast } from 'hooks/useToast';
import UserModal from './UserModal';
import {ROLES} from 'utils/constants';
import { ROLES } from 'utils/constants';
import withAuthorization from 'hoc/with-authorization';
import useStore from "../../../store";
import { CustomerSupportActivityDTO } from 'types/customerSupportActivity';
import useStore from '../../../store';

const SettingsUsers: FC = () => {
const { t } = useTranslation();
const toast = useToast();
const queryClient = useQueryClient();

const userInfo = useStore((state) => state.userInfo);
const [newUserModal, setNewUserModal] = useState(false);
const [changeStatusDialog, setChangeStatusDialog] = useState(false);
const [editableRow, setEditableRow] = useState<User | null>(null);
const [deletableRow, setDeletableRow] = useState<string | number | null>(
null
Expand Down Expand Up @@ -60,12 +70,12 @@ const SettingsUsers: FC = () => {
};

useEffect(() => {
getUsers(pagination, sorting, columnFilters);
getUsers(pagination, sorting, columnFilters);
}, []);

useEffect(() => {
fetchData()
}, [userInfo?.idCode]);
useEffect(() => {
fetchData();
}, [userInfo?.idCode]);

const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
Expand All @@ -75,38 +85,39 @@ const SettingsUsers: FC = () => {
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const columnHelper = createColumnHelper<User>();

const fetchData = async () => {
try {
const response = await apiDev.get('/accounts/get-page-preference', {
params: {user_id: userInfo?.idCode, page_name: window.location.pathname},
});
if (response.data.pageResults !== undefined) {
updatePagePreference(response.data.pageResults)
} else {
getUsers(pagination, sorting, columnFilters);
}
} catch (err) {
console.error('Failed to fetch data');
}
};

const updatePagePreference = (pageResults: number): void => {
const updatedPagination = { ...pagination, pageSize: pageResults };
setPagination(updatedPagination);
getUsers(updatedPagination, sorting, columnFilters);
const fetchData = async () => {
try {
const response = await apiDev.get('/accounts/get-page-preference', {
params: {
user_id: userInfo?.idCode,
page_name: window.location.pathname,
},
});
if (response.data.pageResults !== undefined) {
updatePagePreference(response.data.pageResults);
} else {
getUsers(pagination, sorting, columnFilters);
}
} catch (err) {
console.error('Failed to fetch data');
}
};

const updatePageSize = useMutation({
mutationFn: (data: {
page_results: number;
}) => {
return apiDev.post('accounts/update-page-preference', {
user_id: userInfo?.idCode,
page_name: window.location.pathname,
page_results: data.page_results,
});
}
});
const updatePagePreference = (pageResults: number): void => {
const updatedPagination = { ...pagination, pageSize: pageResults };
setPagination(updatedPagination);
getUsers(updatedPagination, sorting, columnFilters);
};

const updatePageSize = useMutation({
mutationFn: (data: { page_results: number }) => {
return apiDev.post('accounts/update-page-preference', {
user_id: userInfo?.idCode,
page_name: window.location.pathname,
page_results: data.page_results,
});
},
});

const deleteUserMutation = useMutation({
mutationFn: ({ id }: { id: string | number }) => deleteUser(id),
Expand All @@ -128,6 +139,34 @@ const SettingsUsers: FC = () => {
},
});

const customerSupportActivityMutation = useMutation({
mutationFn: (data: CustomerSupportActivityDTO) =>
apiDev.post('accounts/customer-support-activity', {
customerSupportActive: data.customerSupportActive,
customerSupportStatus: data.customerSupportStatus,
}),
onSuccess: async () => {
getUsers(pagination, sorting, columnFilters);
toast.open({
type: 'success',
title: t('global.notification'),
message: t('toast.success.userUpdated'),
});
setChangeStatusDialog(false);
},
onError: async (error: AxiosError) => {
await queryClient.invalidateQueries([
'accounts/customer-support-activity',
'prod',
]);
toast.open({
type: 'error',
title: t('global.notificationError'),
message: error.message,
});
},
});

const editView = (props: any) => (
<Button
appearance="text"
Expand Down Expand Up @@ -191,17 +230,29 @@ const SettingsUsers: FC = () => {
const customerSupportStatusView = (props: any) => {
const isIdle = props.getValue() === 'idle' ? '#FFB511' : '#D73E3E';
return (
<span
<Button
appearance="text"
onClick={() => {
if (props.getValue() === 'online' || props.getValue() === 'idle')
setChangeStatusDialog(true);
}}
style={{
marginLeft: 'auto',
marginRight: 'auto',
display: 'block',
width: 16,
height: 16,
borderRadius: '50%',
backgroundColor: props.getValue() === 'online' ? '#308653' : isIdle,
color: 'white',
}}
></span>
>
<span
style={{
marginLeft: 'auto',
marginRight: 'auto',
display: 'block',
width: 16,
height: 16,
borderRadius: '50%',
backgroundColor: props.getValue() === 'online' ? '#308653' : isIdle,
}}
></span>
</Button>
);
};

Expand Down Expand Up @@ -301,7 +352,7 @@ const SettingsUsers: FC = () => {
)
return;
setPagination(state);
updatePageSize.mutate({page_results: state.pageSize});
updatePageSize.mutate({ page_results: state.pageSize });
getUsers(state, sorting, columnFilters);
}}
sorting={sorting}
Expand Down Expand Up @@ -337,6 +388,36 @@ const SettingsUsers: FC = () => {
/>
)}

{changeStatusDialog && (
<Dialog
title={t('settings.users.userChangeStatusMessage')}
onClose={() => setChangeStatusDialog(false)}
footer={
<>
<Button
appearance="secondary"
onClick={() => setChangeStatusDialog(false)}
>
{t('global.no')}
</Button>
<Button
appearance="primary"
onClick={() => {
customerSupportActivityMutation.mutate({
customerSupportActive: false,
customerSupportStatus: 'offline',
});
}}
>
{t('global.yes')}
</Button>
</>
}
>
<p>{t('global.removeValidation')}</p>
</Dialog>
)}

{editableRow && (
<UserModal
user={editableRow}
Expand Down
5 changes: 5 additions & 0 deletions GUI/src/types/customerSupportActivity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type CustomerSupportActivityDTO = {
customerSupportActive: boolean;
customerSupportStatus: 'offline' | 'idle' | 'online';
customerSupportId: string;
};
3 changes: 2 additions & 1 deletion GUI/translations/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@
"invalidIdCode": "Invalid Id Code",
"idCodePlaceholder": "The personal identification number must start with a country prefix, (eg.EE12345678910)",
"choose": "Choose",
"userExists": "User Exists"
"userExists": "User Exists",
"userChangeStatusMessage": "Do you want to change the user status to away?"
},
"chat": {
"chatActive": "Chatbot active",
Expand Down
3 changes: 2 additions & 1 deletion GUI/translations/et/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@
"invalidIdCode": "Kehtetu isikukood",
"idCodePlaceholder": "Isikukood peab algama riigi eesliitega, (eg.EE12345678910)",
"choose": "Vali",
"userExists": "Kasutaja on olemas"
"userExists": "Kasutaja on olemas",
"userChangeStatusMessage": "Kas sa soovid kasutaja staatuseks muuta eemal?"
},
"chat": {
"chatActive": "Vestlusrobot aktiivne",
Expand Down

0 comments on commit 0873038

Please sign in to comment.