Skip to content

Commit

Permalink
add dropdown to apply roles in diffrent tenants
Browse files Browse the repository at this point in the history
  • Loading branch information
Chakravarthy7102 committed Nov 21, 2023
1 parent 1e3e97d commit 7c262d4
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 38 deletions.
1 change: 1 addition & 0 deletions build/asset-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"static/media/chevron-up-selected.svg": "/static/media/chevron-up-selected.svg",
"static/media/chevron-right.svg": "/static/media/chevron-right.svg",
"static/media/people.svg": "/static/media/people.svg",
"static/media/arrow-down.svg": "/static/media/arrow-down.svg",
"static/media/hamburger-menu.svg": "/static/media/hamburger-menu.svg",
"static/media/provider-facebook.svg": "/static/media/provider-facebook.svg",
"static/media/Union-yellow.png": "/static/media/Union-yellow.png",
Expand Down
2 changes: 1 addition & 1 deletion build/static/css/main.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/css/main.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/js/bundle.js.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions build/static/media/arrow-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 8 additions & 6 deletions src/api/userroles/user/roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ export const useUserRolesService = () => {

const addRoleToUser = async (
userId: string,
role: string
role: string,
tenantId: string
): Promise<
| {
status: "OK" | "UNKNOWN_ROLE_ERROR";
}
| undefined
> => {
const response = await fetchData({
url: getApiUrl("/api/userroles/user/roles"),
url: getApiUrl("/api/userroles/user/roles", tenantId),
method: "PUT",
config: {
body: JSON.stringify({
Expand All @@ -55,9 +56,9 @@ export const useUserRolesService = () => {
return undefined;
};

const getRolesForUser = async (userId: string): Promise<UserRolesResponse | undefined> => {
const getRolesForUser = async (userId: string, tenantId: string): Promise<UserRolesResponse | undefined> => {
const response = await fetchData({
url: getApiUrl("/api/userroles/user/roles"),
url: getApiUrl("/api/userroles/user/roles", tenantId),
method: "GET",
query: {
userId,
Expand All @@ -74,7 +75,8 @@ export const useUserRolesService = () => {

const removeUserRole = async (
userId: string,
role: string
role: string,
tenantId: string
): Promise<
| {
status: "OK";
Expand All @@ -85,7 +87,7 @@ export const useUserRolesService = () => {
| undefined
> => {
const response = await fetchData({
url: getApiUrl("/api/userroles/user/roles"),
url: getApiUrl("/api/userroles/user/roles", tenantId),
method: "DELETE",
query: {
userId,
Expand Down
3 changes: 3 additions & 0 deletions src/assets/arrow-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import "./assets/ST_icon_dark_theme.svg";
import "./assets/ST_icon_light_theme.svg";
import "./assets/Union-yellow.png";
import "./assets/Union.png";
import "./assets/arrow-down.svg";
import "./assets/auth-background-portrait.png";
import "./assets/auth-background.png";
import "./assets/auth-method.svg";
Expand Down
47 changes: 47 additions & 0 deletions src/ui/components/select/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useState } from "react";
import { ReactComponent as ArrowDown } from "../../../assets/arrow-down.svg";

import "./select.scss";

type SelectProps = {
options: { value: string; name: string }[];
selectedOption: string;
onOptionSelect: (value: string) => void;
};
export default function Select({ onOptionSelect, options, selectedOption }: SelectProps) {
const [showOptions, setShowOptions] = useState(false);
return (
<div
className="select-container"
onMouseLeave={() => setShowOptions(false)}
onMouseEnter={() => setShowOptions(true)}>
<div className="select-action">
{selectedOption}{" "}
<ArrowDown
color="#000"
style={{ rotate: showOptions ? "180deg" : undefined }}
/>
</div>
{showOptions ? (
<div className="select-dropdown-wrapper">
<div className="select-dropdown">
{options.map((option) => {
return (
<div
className="select-item"
key={option.value}
onClick={(e) => {
e.stopPropagation();
onOptionSelect(option.value);
setShowOptions(false);
}}>
{option.name}
</div>
);
})}
</div>
</div>
) : null}
</div>
);
}
53 changes: 53 additions & 0 deletions src/ui/components/select/select.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.select-container {
position: relative;
cursor: pointer;

.select-action {
display: flex;
width: 210px;
height: 36px;
padding: 9px 13px;
justify-content: space-between;
align-items: center;
gap: 10px;
flex-shrink: 0;

border-radius: 6px;
border: 1px solid #e5e5e5;
background: #fff;

color: #222;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.select-dropdown-wrapper {
padding-top: 5px;
z-index: 5;
position: absolute;
width: 100%;

.select-dropdown {
background: #fff;
border-radius: 6px;
background: #fff;
box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);

.select-item {
cursor: pointer;
padding: 12px;
color: #222;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;

&:hover {
background: #f0f0f0;
width: 100%;
}
}
}
}
}
18 changes: 15 additions & 3 deletions src/ui/components/userDetail/userDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { GetUserInfoResult, UpdateUserInformationResponse, useUserService } from
import useMetadataService from "../../../api/user/metadata";
import useSessionsForUserService from "../../../api/user/sessions";
import { UserRolesResponse, useUserRolesService } from "../../../api/userroles/user/roles";
import { getImageUrl, getRecipeNameFromid } from "../../../utils";
import { getImageUrl, getRecipeNameFromid, getSelectedTenantId } from "../../../utils";
import { getTenantsObjectsForIds } from "../../../utils/user";
import { PopupContentContext } from "../../contexts/PopupContentContext";
import { User, UserRecipeType } from "../../pages/usersList/types";
Expand Down Expand Up @@ -57,6 +57,7 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
const [shouldShowLoadingOverlay, setShowLoadingOverlay] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState(false);
const [userRolesData, setUserRolesData] = useState<UserRolesResponse | undefined>(undefined);
const [currentlySelectedTenantId, setCurrentlySelectedTenantId] = useState(getSelectedTenantId() ?? "public");

const { getUser, updateUserInformation } = useUserService();
const { getUserMetaData } = useMetadataService();
Expand Down Expand Up @@ -154,7 +155,8 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
}, []);

async function fetchUserRoles() {
const response = await getRolesForUser(user);
setUserRolesData(undefined);
const response = await getRolesForUser(user, currentlySelectedTenantId);
if (response !== undefined) {
setUserRolesData(response);
} else {
Expand Down Expand Up @@ -196,6 +198,10 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
void fetchData();
}, []);

useEffect(() => {
void fetchUserRoles();
}, [currentlySelectedTenantId]);

if (userDetail === undefined || userRolesData === undefined || isLoading) {
return (
<div className="user-detail-page-loader">
Expand Down Expand Up @@ -272,7 +278,13 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
<UserDetailInfoGrid {...props} />

<UserRolesList
userRolesData={userRolesData}
key={currentlySelectedTenantId}
currentlySelectedTenantId={currentlySelectedTenantId}
onTenantIdChange={(tenantId: string) => {
setCurrentlySelectedTenantId(tenantId);
}}
isFeatureEnabled={userRolesData.status !== "FEATURE_NOT_ENABLED_ERROR"}
roles={userRolesData.status === "OK" ? userRolesData.roles : []}
userId={user}
/>

Expand Down
37 changes: 29 additions & 8 deletions src/ui/components/userDetail/userRoles/UserRolesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,23 @@ import Badge from "../../badge";
import { LayoutPanel } from "../../layout/layoutPanel";
import { UserRolesListHeader } from "./UserRolesListHeader";

import { UserRolesResponse } from "../../../../api/userroles/user/roles";
import Alert from "../../alert";
import Select from "../../select";
import AssignRolesDialog from "../../userroles/components/dialogs/AssignRoles";
import DeleteUserRoleDialog from "../../userroles/components/dialogs/DeleteUserRole";
import { useUserDetailContext } from "../context/UserDetailContext";
import "./userRolesList.scss";

type UserRolesListProps = {
currentlySelectedTenantId: string;
userId: string;
userRolesData: UserRolesResponse;
roles: string[];
isFeatureEnabled: boolean;
onTenantIdChange: (tenantId: string) => void;
};

export default function UserRolesList(props: UserRolesListProps) {
const { userRolesData, userId } = props;
const roles = userRolesData.status === "OK" ? userRolesData.roles : [];
const { roles, isFeatureEnabled, userId } = props;

const [assignedRoles, setAssignedRoles] = useState<string[]>(roles);

Expand All @@ -42,20 +45,36 @@ export default function UserRolesList(props: UserRolesListProps) {

const [isEditing, setIsEditing] = useState(false);

const { userDetail } = useUserDetailContext();
const tenantIdsThatUserIsPartOf = userDetail.details.tenantIds;

return (
<LayoutPanel
header={
<UserRolesListHeader
setIsEditing={setIsEditing}
isEditing={isEditing}
isFeatureEnabled={userRolesData.status !== "FEATURE_NOT_ENABLED_ERROR"}
isFeatureEnabled={isFeatureEnabled}
/>
}
headerBorder>
}>
<>
<div className="user-roles-list-wrapper">
{userRolesData.status !== "FEATURE_NOT_ENABLED_ERROR" ? (
{isFeatureEnabled ? (
<>
<div className="select-tenantId-container">
All roles assigned to the user for tenant:{" "}
{tenantIdsThatUserIsPartOf.length > 1 ? (
<Select
onOptionSelect={props.onTenantIdChange}
options={tenantIdsThatUserIsPartOf.map((id) => {
return { name: id, value: id };
})}
selectedOption={props.currentlySelectedTenantId}
/>
) : (
<span>{props.currentlySelectedTenantId}</span>
)}
</div>
{isEditing ? (
<div className="roles-list-container">
{assignedRoles.map((role) => {
Expand Down Expand Up @@ -109,6 +128,7 @@ export default function UserRolesList(props: UserRolesListProps) {
</div>
{showAddRoleDialog ? (
<AssignRolesDialog
currentlySelectedTenantId={props.currentlySelectedTenantId}
userId={userId}
assignedRoles={assignedRoles}
setAssignedRoles={setAssignedRoles}
Expand All @@ -117,6 +137,7 @@ export default function UserRolesList(props: UserRolesListProps) {
) : null}
{showDeleteRoleDialog && roleToDelete !== undefined ? (
<DeleteUserRoleDialog
currentlySelectedTenantId={props.currentlySelectedTenantId}
roleToDelete={roleToDelete}
userId={userId}
assignedRoles={assignedRoles}
Expand Down
14 changes: 12 additions & 2 deletions src/ui/components/userDetail/userRoles/userRolesList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
gap: 14px;
flex-wrap: wrap;
align-items: center;
border-top: 1px solid var(--color-border);
padding-top: 20px;
margin-top: 20px;

.no-roles-found {
padding: 20px 0px;
Expand Down Expand Up @@ -45,18 +48,25 @@
}
}

.subtext {
.select-tenantId-container {
color: var(--color-secondary-text);
font-size: 12px;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 23px;

display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
margin-top: -32px;

& > span {
font-weight: 500;
}

@media (max-width: 440px) {
font-size: 12px;
line-height: 18px;
}
}
Expand Down
Loading

0 comments on commit 7c262d4

Please sign in to comment.