Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modal-user-id #6

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion backend/src/controllers/DashboardBackendController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
DASHBOARD_API_UPDATE_MY_WORKSPACE_USER_WORKSPACE_ID,
DASHBOARD_API_UPDATE_MY_WORKSPACE_USER_PATH,
DASHBOARD_API_UPDATE_MY_WORKSPACE_USER_USER_ID,
VALID_ADMIN_DOMAINS
VALID_ADMIN_DOMAINS,
DASHBOARD_API_GET_MY_WORKSPACE_USER_BY_PROFILE_PATH
} from "../fi/hg/dashboard/constants/dashboard-api";

import {
Expand Down Expand Up @@ -161,6 +162,64 @@ export class DashboardBackendController {
}
}

// *********** WORSKPACE USER PROFILE ***********

/**
* Returns profile for a workspace
*
* @param token
* @param parentIdString
*/
@GetMapping(DASHBOARD_API_GET_MY_WORKSPACE_USER_BY_PROFILE_PATH)
public static async getMyWorkspaceUserByProfile(
@RequestHeader(DASHBOARD_AUTHORIZATION_HEADER_NAME, {
required: true
})
token: string,
@PathVariable(DASHBOARD_API_GET_MY_WORKSPACE_USER_LIST_WORKSPACE_ID, {required: true})
parentIdString: string
): Promise<User | ResponseEntity<ErrorDTO>> {
try {

if ( !token ) {
LOG.warn(`Warning! No authentication token provided.`);
return ResponseEntity.internalServerError<ErrorDTO>().body(
createErrorDTO('Access denied', 403)
);
}

const workspaceId: string = trim(parentIdString ?? '');
LOG.debug(`getMyWorkspaceUserList: workspaceId: `, workspaceId);

const email: string | undefined = JwtService.decodePayloadSubject(token);
if ( !email ) {
LOG.warn(`Warning! Token did not have an email address.`, token);
return ResponseEntity.internalServerError<ErrorDTO>().body(
createErrorDTO('Access denied', 403)
);
}

if ( !this._emailTokenService.verifyToken(email, token, true) ) {
LOG.debug(`getMyWorkspaceUserList: Access denied for email: `, email, token);
return ResponseEntity.internalServerError<ErrorDTO>().body(
createErrorDTO('Access denied', 403)
);
}

const userList: User[] = await this._backend.getUserListForWorkspace(workspaceId);

const profiles: User[] = userList.filter(user => user.email === email);

return profiles[0];

} catch (err) {
LOG.error(`getMyWorkspaceUserList: ERROR: `, err);
return ResponseEntity.internalServerError<ErrorDTO>().body(
createErrorDTO('Internal Server Error', 500)
);
}
}


// *********** WORKSPACES ***********

Expand Down
2 changes: 1 addition & 1 deletion backend/src/fi/hg/dashboard
13 changes: 8 additions & 5 deletions frontend/src/components/common/layout/appMenu/AppMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,34 @@

import { APP_MENU_CLASS_NAME } from "../../../../constants/appClassName";
import { NavLink } from "react-router-dom";
import {
USER_LIST_ROUTE
} from "../../../../constants/route";
import {
T_APP_HEADER_NAV_USERS
} from "../../../../constants/translation";
import { useCallback, MouseEvent } from "react";
import { useEmailAuthSession } from "../../../../fi/hg/frontend/hooks/useEmailAuthSession";
import { SetProfileMenuOpenCallback } from "../../../../fi/hg/frontend/hooks/useDropdownToggleWithoutWindowSizeAndScroll";
import { TranslationFunction } from "../../../../fi/hg/core/types/TranslationFunction";
import {useCurrentWorkspaceId} from "../../../../hooks/workspace/useCurrentWorkspaceId";
import {LogService} from "../../../../fi/hg/core/LogService";
import {getWorkspaceUserListRoute, MY_WORKSPACE_LIST_ROUTE} from "../../../../constants/route";
import "./AppMenu.scss";

export interface MenuProps {
readonly t: TranslationFunction;
readonly className?: string;
readonly changeMenuState: SetProfileMenuOpenCallback;
}

const LOG = LogService.createLogger('AppMenu');
export function AppMenu (props: MenuProps) {

const t = props?.t;
const className = props?.className;
const setMenuOpen = props.changeMenuState;
const session = useEmailAuthSession();

const workspaceId = useCurrentWorkspaceId();
const workspaceUserListRoute = workspaceId ? getWorkspaceUserListRoute(workspaceId): MY_WORKSPACE_LIST_ROUTE;

const closeMenuCallback = useCallback(
(event: MouseEvent<HTMLDivElement>) => {
if ( event ) {
Expand Down Expand Up @@ -66,7 +69,7 @@ export function AppMenu (props: MenuProps) {

<NavLink
className={`${APP_MENU_CLASS_NAME}-content-nav-item`}
to={USER_LIST_ROUTE}
to={workspaceUserListRoute}
>{t(T_APP_HEADER_NAV_USERS)}</NavLink>

</nav>
Expand Down
10 changes: 7 additions & 3 deletions frontend/src/components/common/layout/appNav/AppNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import { APP_NAV_CLASS_NAME } from "../../../../constants/appClassName";
import { TranslationFunction } from "../../../../fi/hg/core/types/TranslationFunction";
import { NavLink } from "react-router-dom";
import { ABOUT_ROUTE, USER_LIST_ROUTE } from "../../../../constants/route";
import {ABOUT_ROUTE, getWorkspaceUserListRoute, MY_WORKSPACE_LIST_ROUTE} from "../../../../constants/route";
import { T_APP_HEADER_NAV_HOME, T_APP_HEADER_NAV_USERS } from "../../../../constants/translation";
import "./AppNav.scss";
import { Icon } from "../../../../fi/hg/frontend/components/icon/Icon";
import { HomeIcon, UserListIcon } from "../../../../assets/icons";
import {useCurrentWorkspaceId} from "../../../../hooks/workspace/useCurrentWorkspaceId";
import "./AppNav.scss";

export interface AppNavProps {
readonly t : TranslationFunction;
Expand All @@ -19,6 +20,9 @@ export function AppNav (props: AppNavProps) {
const t = props?.t;
const className = props?.className;

const workspaceId = useCurrentWorkspaceId();
const workspaceUserListRoute = workspaceId ? getWorkspaceUserListRoute(workspaceId): MY_WORKSPACE_LIST_ROUTE;

return (
<nav className={
APP_NAV_CLASS_NAME
Expand All @@ -38,7 +42,7 @@ export function AppNav (props: AppNavProps) {

<NavLink
className={`${APP_NAV_CLASS_NAME}-section-item`}
to={USER_LIST_ROUTE}
to={workspaceUserListRoute}
><Icon><UserListIcon /></Icon> <span className={`${APP_NAV_CLASS_NAME}-section-item-text`}>{t(T_APP_HEADER_NAV_USERS)}</span></NavLink>

</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { CLOSE_APP_MODAL_BUTTON_CLASS_NAME } from "../../../../constants/appClassName";
import { Button } from "../../../../fi/hg/frontend/components/button/Button";
import { ButtonStyle } from "../../../../fi/hg/core/frontend/button/ButtonStyle";
import { useAppCallback } from "../../../../hooks/modal/useAppCallback";
import {useAppNavigateCallback} from "../../../../hooks/modal/useAppNavigateCallback";
import "./CloseAppModalButton.scss";

export interface CloseAppModalButtonProps {
Expand All @@ -12,7 +12,7 @@ export interface CloseAppModalButtonProps {

export function CloseAppModalButton (props: CloseAppModalButtonProps) {
const className = props?.className;
const closeModalCallback = useAppCallback();
const closeModalCallback = useAppNavigateCallback();
return (
<Button
className={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// Copyright (c) 2022. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.
// Copyright (c) 2023. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.

import { useAppCallback } from "../../../../hooks/modal/useAppCallback";
import { AppModalType } from "../../../../types/AppModalType";
import { ButtonStyle } from "../../../../fi/hg/core/frontend/button/ButtonStyle";
import { Button } from "../../../../fi/hg/frontend/components/button/Button";
import { OPEN_APP_MODAL_BUTTON_CLASS_NAME } from "../../../../constants/appClassName";
import { ReactNode } from "react";
import {useAppWithRouteCallback} from "../../../../hooks/modal/useAppWithRouteCallback";
import "./OpenAppModalButton.scss";

export interface OpenAppModalButtonProps {
readonly className ?: string;
readonly modal ?: AppModalType | undefined;
readonly id ?: string | undefined;
readonly parentId ?: string | undefined;
readonly children ?: ReactNode;
readonly style ?: ButtonStyle;
}
Expand All @@ -20,8 +21,9 @@ export function OpenAppModalButton (props: OpenAppModalButtonProps) {
const className = props?.className;
const modal = props?.modal;
const id = props?.id;
const parentId = props?.parentId;
const style = props?.style ?? ButtonStyle.LINK;
const openAddUserModalCallback = useAppCallback(modal, id);
const openAddUserModalCallback = useAppWithRouteCallback(modal, parentId, id);
return (
<Button
className={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.
// Copyright (c) 2023. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.

import { OpenAppModalButton } from "../../modal/openAppModalButton/OpenAppModalButton";
import { AppModalType } from "../../../../types/AppModalType";
Expand All @@ -9,18 +9,20 @@ import { ButtonStyle } from "../../../../fi/hg/core/frontend/button/ButtonStyle"
export interface OpenEditUserModalButtonProps {
readonly id : string;
readonly style ?: ButtonStyle;
readonly parentId: string;
}

export function OpenEditUserModalButton (
props: OpenEditUserModalButtonProps
) {
const id = props?.id;
const parentId = props?.parentId;
const style = props?.style ?? ButtonStyle.LINK;
return (
<OpenAppModalButton
modal={AppModalType.EDIT_USER_MODAL}
id={id}
parentId={parentId}
style={style}
><Icon><EditIcon /></Icon></OpenAppModalButton>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.
// Copyright (c) 2023. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.

import { Icon } from "../../../../fi/hg/frontend/components/icon/Icon";
import { SignInIcon } from "../../../../assets/icons";
Expand All @@ -7,6 +7,8 @@ import { ReactNode, useCallback } from "react";
import { WorkspaceService } from "../../../../services/WorkspaceService";
import { Workspace } from "../../../../fi/hg/dashboard/types/Workspace";
import { ButtonStyle } from "../../../../fi/hg/core/frontend/button/ButtonStyle";
import {RouteService} from "../../../../fi/hg/frontend/services/RouteService";
import {getWorkspaceAboutRoute, MY_WORKSPACE_LIST_ROUTE} from "../../../../constants/route";

export interface SelectWorkspaceButtonProps {
readonly className?: string;
Expand All @@ -18,12 +20,17 @@ export function SelectWorkspaceButton (props: SelectWorkspaceButtonProps) {
const className = props?.className;
const workspace = props?.workspace;
const children = props?.children;

const workspaceAboutRoute = workspace ? getWorkspaceAboutRoute(workspace.id): MY_WORKSPACE_LIST_ROUTE;

const onClick = useCallback(
() => {
WorkspaceService.setCurrentWorkspace(workspace);
WorkspaceService.setCurrentWorkspace(workspace).then(()=>{
RouteService.setRoute(workspaceAboutRoute);
});
},
[
workspace
workspace, workspaceAboutRoute
]
);
return (
Expand All @@ -33,6 +40,6 @@ export function SelectWorkspaceButton (props: SelectWorkspaceButtonProps) {
className ? className : ''
}
click={onClick}
><Icon><SignInIcon /></Icon> {children}</Button>
><Icon><SignInIcon /></Icon>{children}</Button>
);
}
}
31 changes: 16 additions & 15 deletions frontend/src/components/dashboardApp/DashboardApp.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
// Copyright (c) 2022. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.
// Copyright (c) 2023. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.

import {
Navigate,
Outlet,
useRoutes
} from "react-router-dom";
import {
INDEX_ROUTE,
LOGIN_INDEX_ROUTE,
MY_PROFILE_INDEX_ROUTE,
NOT_FOUND_ROUTE,
USER_LIST_ROUTE,
USER_ROUTE,
ABOUT_ROUTE,
MY_WORKSPACE_LIST_ROUTE, MY_INDEX_ROUTE
MY_WORKSPACE_LIST_ROUTE, MY_INDEX_ROUTE, WORKSPACE_INDEX_ROUTE
} from "../../constants/route";
import { LogService } from "../../fi/hg/core/LogService";
import { useEmailAuthSession } from "../../fi/hg/frontend/hooks/useEmailAuthSession";
Expand All @@ -22,14 +21,14 @@ import { LoginView } from "../views/login/LoginView";
import { AboutView } from "../views/about/AboutView";
import { DARK_MAIN_LAYOUT_CLASS_NAME, DASHBOARD_APP_CLASS_NAME } from "../../constants/appClassName";
import { useLanguageService } from "../../fi/hg/frontend/hooks/useLanguageService";
import { UserView } from "../views/user/item/UserView";
import { UserListView } from "../views/user/list/UserListView";
import { WorkspaceListView } from "../views/workspace/list/WorkspaceListView";
import { useRouteServiceWithNavigate } from "../../fi/hg/frontend/hooks/useRouteServiceWithNavigate";
import { LayoutComponent } from "../../types/DashboardLayout";
import "./DashboardApp.scss";
import { useAppModal } from "../../hooks/modal/useAppModal";
import { AppModalContainer } from "../common/layout/appModalContainer/AppModalContainer";
import {EditUserModal} from "../modals/user/editUserModal/EditUserModal";
import "./DashboardApp.scss";

const LOG = LogService.createLogger('DashboardApp');

Expand Down Expand Up @@ -82,7 +81,7 @@ export function DashboardApp (
};

const mainRoutes = {
path: INDEX_ROUTE,
path: WORKSPACE_INDEX_ROUTE,
element: (
<MainLayout t={t}>
<WorkspaceLayout t={t}>
Expand All @@ -93,10 +92,11 @@ export function DashboardApp (
),
children: [
{path: ABOUT_ROUTE, element: <AboutView t={t} />},
{path: USER_LIST_ROUTE, element: <UserListView t={t} />},
{path: USER_ROUTE, element: <UserView t={t} />},
{path: '*', element: <Navigate to={ABOUT_ROUTE} />},
{path: NOT_FOUND_ROUTE, element: <Navigate to={ABOUT_ROUTE} />}
{path: USER_LIST_ROUTE, element: <UserListView t={t} />,
children:[
{path:USER_ROUTE, element: <EditUserModal t={t} />}
]},
{path: WORKSPACE_INDEX_ROUTE, element: <Navigate to={MY_WORKSPACE_LIST_ROUTE} />}
]
};

Expand All @@ -112,14 +112,16 @@ export function DashboardApp (
),
children: [
{path: MY_WORKSPACE_LIST_ROUTE, element: <WorkspaceListView t={t} />},
{path: MY_PROFILE_INDEX_ROUTE, element: <ProfileView t={t} />}
{path: MY_PROFILE_INDEX_ROUTE, element: <ProfileView t={t} />},
{path: '*', element: <Navigate to={ABOUT_ROUTE} />},
{path: MY_INDEX_ROUTE, element: <Navigate to={WORKSPACE_INDEX_ROUTE} />}
]
};

const main = useRoutes(
[
mainRoutes
, profileRoutes
mainRoutes,
profileRoutes
]
);

Expand All @@ -129,10 +131,9 @@ export function DashboardApp (
]
);

return <div className={DASHBOARD_APP_CLASS_NAME}>

return <div className={DASHBOARD_APP_CLASS_NAME}>
{ isLoggedIn ? main : login}

</div>;

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

& > .edit-user-modal-header-close-button {
box-sizing: border-box;
padding: 0;
margin: 0;
flex-shrink: 0;
}
Expand Down
Loading