roles and team
parent
73aad4727d
commit
61d01eedc7
|
@ -45,16 +45,16 @@ export default function App() {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
dispatch(setUserAuthenticated(true));
|
|
||||||
dispatch(setPrimaryColor(`#${response.Organization.PrimaryColor}`));
|
dispatch(setPrimaryColor(`#${response.Organization.PrimaryColor}`));
|
||||||
dispatch(setLogoUrl(response.Organization.LogoUrl));
|
dispatch(setLogoUrl(response.Organization.LogoUrl));
|
||||||
dispatch(setBannerUrl(response.Organization.BannerUrl));
|
dispatch(setBannerUrl(response.Organization.BannerUrl));
|
||||||
}
|
dispatch(setUserAuthenticated(true));
|
||||||
} catch (error) {}
|
|
||||||
})();
|
|
||||||
|
|
||||||
webSocketService.connect();
|
webSocketService.connect();
|
||||||
webSocketService.setHandler(WebSocketMessageHandler, dispatch);
|
webSocketService.setHandler(WebSocketMessageHandler, dispatch);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
})();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
webSocketService.disconnect();
|
webSocketService.disconnect();
|
||||||
|
|
|
@ -214,6 +214,7 @@ export function SideMenuContent() {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Flex justify="center" style={{ paddingBottom: 24, width: "100%" }}>
|
<Flex justify="center" style={{ paddingBottom: 24, width: "100%" }}>
|
||||||
|
{appLogoUrl !== null && (
|
||||||
<img
|
<img
|
||||||
src={`${Constants.STATIC_CONTENT_ADDRESS}${
|
src={`${Constants.STATIC_CONTENT_ADDRESS}${
|
||||||
appLogoUrl || Constants.DEMO_LOGO_URL
|
appLogoUrl || Constants.DEMO_LOGO_URL
|
||||||
|
@ -221,6 +222,7 @@ export function SideMenuContent() {
|
||||||
alt="logo"
|
alt="logo"
|
||||||
style={{ height: 80 }}
|
style={{ height: 80 }}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Menu
|
<Menu
|
||||||
|
|
|
@ -6,8 +6,8 @@ export const appSlice = createSlice({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
userAuthenticated: null,
|
userAuthenticated: null,
|
||||||
primaryColor: "#111",
|
primaryColor: "#111",
|
||||||
logoUrl: "",
|
logoUrl: null,
|
||||||
bannerUrl: "",
|
bannerUrl: null,
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
setDarkMode: (state, action) => {
|
setDarkMode: (state, action) => {
|
||||||
|
|
|
@ -29,6 +29,21 @@ export const organizationApi = createApi({
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
updateTeamMemberRole: builder.mutation({
|
||||||
|
query: ({ memberId, roleId }) => ({
|
||||||
|
url: `organization/team/members/${memberId}/role`,
|
||||||
|
method: "PATCH",
|
||||||
|
body: {
|
||||||
|
RoleId: roleId,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
deleteTeamMember: builder.mutation({
|
||||||
|
query: (memberId) => ({
|
||||||
|
url: `organization/team/members/${memberId}`,
|
||||||
|
method: "DELETE",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
getOrganizationSettings: builder.query<OrganizationSettings, undefined>({
|
getOrganizationSettings: builder.query<OrganizationSettings, undefined>({
|
||||||
query: () => ({
|
query: () => ({
|
||||||
url: "organization/settings",
|
url: "organization/settings",
|
||||||
|
@ -60,25 +75,17 @@ export const organizationApi = createApi({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
/* createRole: builder.mutation({
|
|
||||||
query: (name) => ({
|
|
||||||
url: "organization/roles",
|
|
||||||
method: "POST",
|
|
||||||
body: {
|
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}), */
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
useGetTeamQuery,
|
useGetTeamQuery,
|
||||||
useCreateTeamMemberMutation,
|
useCreateTeamMemberMutation,
|
||||||
|
useUpdateTeamMemberRoleMutation,
|
||||||
|
useDeleteTeamMemberMutation,
|
||||||
useGetOrganizationSettingsQuery,
|
useGetOrganizationSettingsQuery,
|
||||||
useUpdateOrganizationSettingsMutation,
|
useUpdateOrganizationSettingsMutation,
|
||||||
useIsSubdomainAvailableMutation,
|
useIsSubdomainAvailableMutation,
|
||||||
useUpdateSubdomainMutation,
|
useUpdateSubdomainMutation,
|
||||||
useGetRolesQuery,
|
useGetRolesQuery,
|
||||||
// useCreateRoleMutation,
|
|
||||||
} = organizationApi;
|
} = organizationApi;
|
||||||
|
|
|
@ -6,8 +6,11 @@ import {
|
||||||
} from "core/reducers/appSlice";
|
} from "core/reducers/appSlice";
|
||||||
import { BrowserTabSession, Constants } from "core/utils/utils";
|
import { BrowserTabSession, Constants } from "core/utils/utils";
|
||||||
import { WebSocketReceivedMessagesCmds } from "core/utils/webSocket";
|
import { WebSocketReceivedMessagesCmds } from "core/utils/webSocket";
|
||||||
import { addTeamMember } from "features/Team/teamSlice";
|
import {
|
||||||
import { useDispatch } from "react-redux";
|
addTeamMember,
|
||||||
|
deleteTeamMember,
|
||||||
|
updateTeamMemberRole,
|
||||||
|
} from "features/Team/teamSlice";
|
||||||
|
|
||||||
interface WebSocketMessage {
|
interface WebSocketMessage {
|
||||||
Cmd: number;
|
Cmd: number;
|
||||||
|
@ -148,6 +151,12 @@ export function WebSocketMessageHandler(
|
||||||
case WebSocketReceivedMessagesCmds.TeamAddedMember:
|
case WebSocketReceivedMessagesCmds.TeamAddedMember:
|
||||||
dispatch(addTeamMember(Body));
|
dispatch(addTeamMember(Body));
|
||||||
break;
|
break;
|
||||||
|
case WebSocketReceivedMessagesCmds.TeamUpdatedMemberRole:
|
||||||
|
dispatch(updateTeamMemberRole(Body));
|
||||||
|
break;
|
||||||
|
case WebSocketReceivedMessagesCmds.TeamDeletedMember:
|
||||||
|
dispatch(deleteTeamMember(Body));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Unknown message type:", Cmd);
|
console.error("Unknown message type:", Cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ export interface TeamMember {
|
||||||
LastName: string;
|
LastName: string;
|
||||||
Email: string;
|
Email: string;
|
||||||
RoleId: string;
|
RoleId: string;
|
||||||
Status: string;
|
Online: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrganizationSettings {
|
export interface OrganizationSettings {
|
||||||
|
|
|
@ -8,6 +8,8 @@ enum WebSocketReceivedMessagesCmds {
|
||||||
SettingsUpdatedBanner = 3,
|
SettingsUpdatedBanner = 3,
|
||||||
SettingsUpdatedSubdomain = 4,
|
SettingsUpdatedSubdomain = 4,
|
||||||
TeamAddedMember = 5,
|
TeamAddedMember = 5,
|
||||||
|
TeamUpdatedMemberRole = 6,
|
||||||
|
TeamDeletedMember = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
export { WebSocketSendMessagesCmds, WebSocketReceivedMessagesCmds };
|
export { WebSocketSendMessagesCmds, WebSocketReceivedMessagesCmds };
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
import { FloatButton } from 'antd';
|
import { FloatButton } from "antd";
|
||||||
import { CommentOutlined } from '@ant-design/icons';
|
import { CommentOutlined } from "@ant-design/icons";
|
||||||
import { DeepChat } from 'deep-chat-react';
|
import { DeepChat } from "deep-chat-react";
|
||||||
|
|
||||||
function AiChat() {
|
function AiChat() {
|
||||||
const [visible, setVisible] = React.useState(false);
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
@ -9,14 +9,40 @@ function AiChat() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{visible ? (
|
{visible ? (
|
||||||
<div style={{ position: 'fixed', bottom: 100, right: 10, zIndex: 10000, maxWidth: '95vw', width: 500, height: 1000, maxHeight: 'calc(100vh - 165px)' }}>
|
<div
|
||||||
|
style={{
|
||||||
|
position: "fixed",
|
||||||
|
bottom: 100,
|
||||||
|
right: 10,
|
||||||
|
zIndex: 10000,
|
||||||
|
maxWidth: "95vw",
|
||||||
|
width: 500,
|
||||||
|
height: 1000,
|
||||||
|
maxHeight: "calc(100vh - 165px)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DeepChat
|
<DeepChat
|
||||||
style={{ width: '100%', height: '100%', borderRadius: 10, boxShadow: '0 0 10px rgba(0,0,0,0.1)', bottom: 0, position: 'absolute' }}
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
borderRadius: 10,
|
||||||
|
boxShadow: "0 0 10px rgba(0,0,0,0.1)",
|
||||||
|
bottom: 0,
|
||||||
|
position: "absolute",
|
||||||
|
}}
|
||||||
history={[
|
history={[
|
||||||
{ text: 'Show me a modern city', role: 'user' },
|
{ text: "Show me a modern city", role: "user" },
|
||||||
{ files: [{ src: 'https://test.ex.umbach.dev/api/statico/809fe37e-8c41-4a44-98d1-d9247affd531/67c763b6-ea67-4b49-9621-2f78b85eb180.png', type: 'image' }], role: 'ai' },
|
{
|
||||||
{ text: 'Whats on your mind?', role: 'user' },
|
files: [
|
||||||
{ text: 'Peace and tranquility', role: 'ai' },
|
{
|
||||||
|
src: "https://test.ex.umbach.dev/api/statico/809fe37e-8c41-4a44-98d1-d9247affd531/67c763b6-ea67-4b49-9621-2f78b85eb180.png",
|
||||||
|
type: "image",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
role: "ai",
|
||||||
|
},
|
||||||
|
{ text: "Whats on your mind?", role: "user" },
|
||||||
|
{ text: "Peace and tranquility", role: "ai" },
|
||||||
]}
|
]}
|
||||||
></DeepChat>
|
></DeepChat>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +51,7 @@ function AiChat() {
|
||||||
<FloatButton
|
<FloatButton
|
||||||
icon={<CommentOutlined />}
|
icon={<CommentOutlined />}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => console.log('onClick')}
|
onClick={() => console.log("onClick")}
|
||||||
style={{ zIndex: 10000 }}
|
style={{ zIndex: 10000 }}
|
||||||
onClickCapture={() => {
|
onClickCapture={() => {
|
||||||
setVisible(!visible);
|
setVisible(!visible);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Checkbox, Collapse, Form } from "antd";
|
import { Avatar, Checkbox, Collapse, Form, Tooltip } from "antd";
|
||||||
import HeaderBar from "../../core/components/Header";
|
import HeaderBar from "../../core/components/Header";
|
||||||
import MyBanner from "../../shared/components/MyBanner";
|
import MyBanner from "../../shared/components/MyBanner";
|
||||||
import { MyContainer } from "../../shared/components/MyContainer";
|
import { MyContainer } from "../../shared/components/MyContainer";
|
||||||
|
@ -142,6 +142,30 @@ function RoleComponent({ role }: { role: Role }) {
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
extra: (
|
||||||
|
<>
|
||||||
|
{role.Users.length > 0 && (
|
||||||
|
<Avatar.Group
|
||||||
|
size="small"
|
||||||
|
max={{
|
||||||
|
count: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{role.Users.map((user, index) => (
|
||||||
|
<Tooltip
|
||||||
|
key={index}
|
||||||
|
title={`${user.FirstName} ${user.LastName}`}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Avatar style={{ backgroundColor: "#f56a00" }}>
|
||||||
|
{user.FirstName[0]}
|
||||||
|
</Avatar>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
</Avatar.Group>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -60,7 +60,7 @@ function GeneralCard({
|
||||||
isLoading,
|
isLoading,
|
||||||
}: { data?: OrganizationSettings; isLoading?: boolean } = {}) {
|
}: { data?: OrganizationSettings; isLoading?: boolean } = {}) {
|
||||||
const [form] = useForm<GeneralFieldType>();
|
const [form] = useForm<GeneralFieldType>();
|
||||||
const { success } = useMessage();
|
const { success, error: errorMessage } = useMessage();
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const debounceRef = useRef<null | NodeJS.Timeout>(null);
|
const debounceRef = useRef<null | NodeJS.Timeout>(null);
|
||||||
|
@ -86,6 +86,7 @@ function GeneralCard({
|
||||||
success("Settings updated successfully!");
|
success("Settings updated successfully!");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
errorMessage("Failed to update settings!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,26 +2,44 @@ import MyTable from "shared/components/MyTable";
|
||||||
import HeaderBar from "core/components/Header";
|
import HeaderBar from "core/components/Header";
|
||||||
import MyBanner from "shared/components/MyBanner";
|
import MyBanner from "shared/components/MyBanner";
|
||||||
import { MyContainer } from "shared/components/MyContainer";
|
import { MyContainer } from "shared/components/MyContainer";
|
||||||
import { Button, Flex } from "antd";
|
import { Badge, Button, Flex, Popconfirm, Select, Space } from "antd";
|
||||||
import { UserAddOutlined } from "@ant-design/icons";
|
import { UserAddOutlined } from "@ant-design/icons";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { Constants } from "core/utils/utils";
|
import { Constants } from "core/utils/utils";
|
||||||
import { useGetTeamQuery } from "core/services/organization";
|
import {
|
||||||
|
useDeleteTeamMemberMutation,
|
||||||
|
useGetTeamQuery,
|
||||||
|
useUpdateTeamMemberRoleMutation,
|
||||||
|
} from "core/services/organization";
|
||||||
import MyErrorResult from "shared/components/MyResult";
|
import MyErrorResult from "shared/components/MyResult";
|
||||||
import { useEffect } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { setTeamMembers, teamMembers } from "./teamSlice";
|
import { setTeamMembers, teamMembers } from "./teamSlice";
|
||||||
import { tmpRoleNames } from "features/Roles";
|
import { tmpRoleNames } from "features/Roles";
|
||||||
|
import {
|
||||||
|
addWebSocketReconnectListener,
|
||||||
|
removeWebSocketReconnectListener,
|
||||||
|
} from "core/services/websocketService";
|
||||||
|
import { useMessage } from "core/context/MessageContext";
|
||||||
|
|
||||||
const TeamList: React.FC = () => {
|
const TeamList: React.FC = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const { success, error: errorMessage } = useMessage();
|
||||||
|
|
||||||
const dataTeamMembers = useSelector(teamMembers);
|
const dataTeamMembers = useSelector(teamMembers);
|
||||||
|
|
||||||
const { data, error, isLoading } = useGetTeamQuery(undefined, {
|
const [selectedRoleId, setSelectedRoleId] = useState<string | undefined>();
|
||||||
|
|
||||||
|
const { data, error, isLoading, refetch } = useGetTeamQuery(undefined, {
|
||||||
refetchOnMountOrArgChange: true,
|
refetchOnMountOrArgChange: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [reqUpdateTeamMemberRole, { isLoading: loadingUpdateTeamMemberRole }] =
|
||||||
|
useUpdateTeamMemberRoleMutation();
|
||||||
|
|
||||||
|
const [reqDeleteTeamMember, { isLoading: loadingDeleteTeamMember }] =
|
||||||
|
useDeleteTeamMemberMutation();
|
||||||
|
|
||||||
const getTableContent = () => {
|
const getTableContent = () => {
|
||||||
let items = [
|
let items = [
|
||||||
{
|
{
|
||||||
|
@ -53,6 +71,67 @@ const TeamList: React.FC = () => {
|
||||||
title: "Actions",
|
title: "Actions",
|
||||||
dataIndex: "actions",
|
dataIndex: "actions",
|
||||||
key: "actions",
|
key: "actions",
|
||||||
|
render: (_: any, record: any) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Popconfirm
|
||||||
|
title="Change role to"
|
||||||
|
onConfirm={async () => {
|
||||||
|
try {
|
||||||
|
await reqUpdateTeamMemberRole({
|
||||||
|
memberId: record.key,
|
||||||
|
roleId: selectedRoleId,
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
success("Role updated successfully");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
errorMessage("Error updating role");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
okButtonProps={{ loading: loadingUpdateTeamMemberRole }}
|
||||||
|
description={
|
||||||
|
<Select
|
||||||
|
style={{ width: 150 }}
|
||||||
|
defaultValue={record.role}
|
||||||
|
value={selectedRoleId}
|
||||||
|
onChange={(value) => setSelectedRoleId(value)}
|
||||||
|
>
|
||||||
|
{Object.keys(tmpRoleNames).map((key) => (
|
||||||
|
<Select.Option key={key} value={key}>
|
||||||
|
{tmpRoleNames[key]}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => setSelectedRoleId(record.role)}
|
||||||
|
>
|
||||||
|
Change role
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
|
||||||
|
<Popconfirm
|
||||||
|
title="Confirm deletion of team member"
|
||||||
|
okButtonProps={{
|
||||||
|
loading: loadingDeleteTeamMember,
|
||||||
|
}}
|
||||||
|
onConfirm={async () => {
|
||||||
|
try {
|
||||||
|
await reqDeleteTeamMember(record.key).unwrap();
|
||||||
|
|
||||||
|
success("Team member deleted successfully");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
errorMessage("Error deleting team member");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button type="link">Delete</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -71,10 +150,17 @@ const TeamList: React.FC = () => {
|
||||||
lastName: item.LastName,
|
lastName: item.LastName,
|
||||||
email: item.Email,
|
email: item.Email,
|
||||||
role: tmpRoleNames[item.RoleId],
|
role: tmpRoleNames[item.RoleId],
|
||||||
status: item.Status,
|
status: (
|
||||||
|
<Badge
|
||||||
|
status={item.Online ? "success" : "error"}
|
||||||
|
text={item.Online ? "Online" : "Offline"}
|
||||||
|
/>
|
||||||
|
),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
items.sort((a, b) => a.role.localeCompare(b.role));
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +170,12 @@ const TeamList: React.FC = () => {
|
||||||
dispatch(setTeamMembers(data));
|
dispatch(setTeamMembers(data));
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
addWebSocketReconnectListener(refetch);
|
||||||
|
|
||||||
|
return () => removeWebSocketReconnectListener(refetch);
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (error) return <MyErrorResult />;
|
if (error) return <MyErrorResult />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -18,12 +18,31 @@ export const teamSlice = createSlice({
|
||||||
setTeamMembers: (state, action) => {
|
setTeamMembers: (state, action) => {
|
||||||
state.teamMembers = action.payload;
|
state.teamMembers = action.payload;
|
||||||
},
|
},
|
||||||
|
updateTeamMemberRole: (state, action) => {
|
||||||
|
const member = state.teamMembers.find(
|
||||||
|
(member) => member.Id === action.payload.MemberId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (member) {
|
||||||
|
member.RoleId = action.payload.RoleId;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteTeamMember: (state, action) => {
|
||||||
|
state.teamMembers = state.teamMembers.filter(
|
||||||
|
(member) => member.Id !== action.payload
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectors: {
|
selectors: {
|
||||||
teamMembers: (state) => state.teamMembers,
|
teamMembers: (state) => state.teamMembers,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { addTeamMember, setTeamMembers } = teamSlice.actions;
|
export const {
|
||||||
|
addTeamMember,
|
||||||
|
setTeamMembers,
|
||||||
|
updateTeamMemberRole,
|
||||||
|
deleteTeamMember,
|
||||||
|
} = teamSlice.actions;
|
||||||
|
|
||||||
export const { teamMembers } = teamSlice.selectors;
|
export const { teamMembers } = teamSlice.selectors;
|
||||||
|
|
|
@ -20,6 +20,7 @@ export default function MyBanner({
|
||||||
position: "relative",
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{appBannerUrl !== null ? (
|
||||||
<img
|
<img
|
||||||
src={`${Constants.STATIC_CONTENT_ADDRESS}${
|
src={`${Constants.STATIC_CONTENT_ADDRESS}${
|
||||||
appBannerUrl || Constants.DEMO_BANNER_URL
|
appBannerUrl || Constants.DEMO_BANNER_URL
|
||||||
|
@ -32,6 +33,14 @@ export default function MyBanner({
|
||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: 228,
|
||||||
|
backgroundColor: "#000",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className={styles.gradientContainer}></div>
|
<div className={styles.gradientContainer}></div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue