From a36e0e3b1eb924e8769f52b6f037fdc17ff952e4 Mon Sep 17 00:00:00 2001 From: Johnnadel Salita Uy Date: Tue, 5 Mar 2024 13:25:18 +0100 Subject: [PATCH] Refactor pages (#88) * Refactor Tab properties across pages * Refactor TeamDetail Tab properties * Destructure prepData across all pages Add conditional rendering to FormattedTableColumn * More refactoring in TeamDetail and TODO comments * . --- src/components/FormattedTableColumn.tsx | 16 +++-- src/pages/TeamDetail/TeamDetail.tsx | 70 ++++++++++---------- src/pages/TeamMembers/TeamMembers.tsx | 88 +++++++++++++------------ src/pages/TeamOverview/TeamOverview.tsx | 66 +++++++++---------- src/pages/UserProfile/UserProfile.tsx | 30 +++------ 5 files changed, 132 insertions(+), 138 deletions(-) diff --git a/src/components/FormattedTableColumn.tsx b/src/components/FormattedTableColumn.tsx index a987b608..9beb1a38 100644 --- a/src/components/FormattedTableColumn.tsx +++ b/src/components/FormattedTableColumn.tsx @@ -1,9 +1,9 @@ import { Text, Link } from '@statisticsnorway/ssb-component-library' interface FormattedTableColumnProps { - href: string - linkText: string - text: string + href?: string + linkText?: string + text?: string } const FormattedTableColumn = (props: FormattedTableColumnProps) => { @@ -12,11 +12,13 @@ const FormattedTableColumn = (props: FormattedTableColumnProps) => { return ( <> - - {linkText} - + {href && linkText && ( + + {linkText} + + )} - {text} + {text && {text}} ) } diff --git a/src/pages/TeamDetail/TeamDetail.tsx b/src/pages/TeamDetail/TeamDetail.tsx index 49b18749..37f83280 100644 --- a/src/pages/TeamDetail/TeamDetail.tsx +++ b/src/pages/TeamDetail/TeamDetail.tsx @@ -17,19 +17,24 @@ import PageSkeleton from '../../components/PageSkeleton/PageSkeleton' import { Skeleton } from '@mui/material' import FormattedTableColumn from '../../components/FormattedTableColumn' -const TeamDetail = () => { - const defaultActiveTab = { - title: 'Teammedlemmer', - path: 'team', - } +const TEAM_USERS_TAB = { + title: 'Teammedlemmer', + path: 'team', +} - const [activeTab, setActiveTab] = useState(defaultActiveTab) +const SHARED_BUCKETS_TAB = { + title: 'Delte data', + path: 'sharedBuckets', +} + +const TeamDetail = () => { + const [activeTab, setActiveTab] = useState(TEAM_USERS_TAB) const { setBreadcrumbTeamDetailDisplayName } = useContext(DaplaCtrlContext) const [error, setError] = useState() const [loadingTeamData, setLoadingTeamData] = useState(true) const [teamDetailData, setTeamDetailData] = useState() - const [teamDetailTableTitle, setTeamDetailTableTitle] = useState(defaultActiveTab.title) + const [teamDetailTableTitle, setTeamDetailTableTitle] = useState(TEAM_USERS_TAB.title) const [teamDetailTableData, setTeamDetailTableData] = useState() const { teamId } = useParams<{ teamId: string }>() @@ -37,8 +42,9 @@ const TeamDetail = () => { const prepTeamData = useCallback( (response: TeamDetailData): TableData['data'] => { const teamDetailTab = (activeTab as TabProps)?.path ?? activeTab - if (teamDetailTab === 'sharedBuckets') { - const sharedBuckets = (response['sharedBuckets'] as SharedBuckets).items + const sharedBucketsTab = SHARED_BUCKETS_TAB.path + if (teamDetailTab === sharedBucketsTab) { + const sharedBuckets = (response[sharedBucketsTab] as SharedBuckets).items if (!sharedBuckets) return [] return sharedBuckets.map(({ short_name, bucket_name, metrics }) => { @@ -52,25 +58,25 @@ const TeamDetail = () => { } }) } else { - const teamUsers = (response['team'] as Team).users + const teamUsers = (response[TEAM_USERS_TAB.path] as Team).users if (!teamUsers) return [] - return teamUsers.map((user) => { + return teamUsers.map(({ display_name, principal_name, section_name, groups }) => { return { - id: formatDisplayName(user.display_name), + id: formatDisplayName(display_name), navn: ( ), - seksjon: user.section_name, // Makes section name searchable and sortable in table by including the field - gruppe: user.groups + seksjon: section_name, // Makes section name searchable and sortable in table by including the field + gruppe: groups ?.filter((group) => group.uniform_name.startsWith((response.team as Team).uniform_name)) .map((group) => getGroupType(group.uniform_name)) .join(', '), - epost: user?.principal_name, + epost: principal_name, } }) } @@ -101,10 +107,10 @@ const TeamDetail = () => { const handleTabClick = (tab: string) => { setActiveTab(tab) - if (tab === defaultActiveTab.path) { - setTeamDetailTableTitle(defaultActiveTab.title) + if (tab === TEAM_USERS_TAB.path) { + setTeamDetailTableTitle(TEAM_USERS_TAB.title) } else { - setTeamDetailTableTitle('Delte data') + setTeamDetailTableTitle(SHARED_BUCKETS_TAB.title) } } @@ -120,9 +126,9 @@ const TeamDetail = () => { if (error) return renderErrorAlert() if (loadingTeamData) return - if (teamDetailTableData) { + if (teamDetailData && teamDetailTableData) { const teamOverviewTableHeaderColumns = - activeTab === 'sharedBuckets' + activeTab === SHARED_BUCKETS_TAB.path ? [ { id: 'navn', @@ -154,24 +160,22 @@ const TeamDetail = () => { <> - {teamDetailData ? (teamDetailData.team as Team).uniform_name : ''} - - - {teamDetailData ? formatDisplayName((teamDetailData.team as Team).manager?.display_name ?? '') : ''} + {(teamDetailData.team as Team).uniform_name ?? ''} - {teamDetailData ? (teamDetailData.team as Team).section_name : ''} + {formatDisplayName((teamDetailData.team as Team).manager?.display_name ?? '')} + {(teamDetailData.team as Team).section_name ?? ''} diff --git a/src/pages/TeamMembers/TeamMembers.tsx b/src/pages/TeamMembers/TeamMembers.tsx index 78408f09..76483dea 100644 --- a/src/pages/TeamMembers/TeamMembers.tsx +++ b/src/pages/TeamMembers/TeamMembers.tsx @@ -1,26 +1,32 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { useCallback, useEffect, useState } from 'react' -import { Dialog, Text, Link, Tabs, Divider } from '@statisticsnorway/ssb-component-library' +import { Dialog, Tabs, Divider } from '@statisticsnorway/ssb-component-library' import { TabProps } from '../../@types/pageTypes' import PageLayout from '../../components/PageLayout/PageLayout' import Table, { TableData } from '../../components/Table/Table' import PageSkeleton from '../../components/PageSkeleton/PageSkeleton' -import { fetchAllTeamMembersData, TeamMembersData, User } from '../../services/teamMembers' +import { fetchAllTeamMembersData, TeamMembersData } from '../../services/teamMembers' import { formatDisplayName } from '../../utils/utils' import { ApiError, fetchUserInformationFromAuthToken } from '../../utils/services' +import FormattedTableColumn from '../../components/FormattedTableColumn' -const TeamMembers = () => { - const defaultActiveTab = { - title: 'Mine teammedlemmer', - path: 'myUsers', - } +const MY_USERS_TAB = { + title: 'Mine teammedlemmer', + path: 'myUsers', +} - const [activeTab, setActiveTab] = useState(defaultActiveTab) +const ALL_USERS_TAB = { + title: 'Alle teammedlemmer', + path: 'allUsers', +} + +const TeamMembers = () => { + const [activeTab, setActiveTab] = useState(MY_USERS_TAB) const [teamMembersData, setTeamMembersData] = useState() const [teamMembersTableData, setTeamMembersTableData] = useState() - const [teamMembersTableTitle, setTeamMembersTableTitle] = useState(defaultActiveTab.title) + const [teamMembersTableTitle, setTeamMembersTableTitle] = useState(MY_USERS_TAB.title) const [error, setError] = useState() const [loading, setLoading] = useState(true) @@ -28,19 +34,27 @@ const TeamMembers = () => { (response: TeamMembersData): TableData['data'] => { const teamMember = (activeTab as TabProps)?.path ?? activeTab - return response[teamMember].users.map((teamMember) => ({ - id: formatDisplayName(teamMember.display_name), - navn: renderUserNameColumn(teamMember), - team: teamMember.teams.length, - epost: teamMember.principal_name, - data_admin_roller: teamMember.groups.filter((group) => group.uniform_name.endsWith('data-admins')).length, - seksjon: teamMember.section_name, // Makes section name searchable and sortable in table by including the field - seksjonsleder: formatDisplayName( - teamMember.section_manager && teamMember.section_manager.length > 0 - ? teamMember.section_manager[0].display_name - : 'Seksjonsleder ikke funnet' - ), - })) + return response[teamMember].users.map( + ({ display_name, principal_name, section_name, section_manager, teams, groups }) => ({ + id: formatDisplayName(display_name), + navn: ( + + ), + team: teams.length, + epost: principal_name, + data_admin_roller: groups.filter((group) => group.uniform_name.endsWith('data-admins')).length, + seksjon: section_name, // Makes section name searchable and sortable in table by including the field + seksjonsleder: formatDisplayName( + section_manager && section_manager.length > 0 + ? section_manager[0].display_name + : 'Seksjonsleder ikke funnet' // TODO: Should be handled in services + ), + }) + ) }, [activeTab] ) @@ -72,26 +86,13 @@ const TeamMembers = () => { const handleTabClick = (tab: string) => { setActiveTab(tab) - if (tab === defaultActiveTab.path) { - setTeamMembersTableTitle(defaultActiveTab.title) + if (tab === MY_USERS_TAB.path) { + setTeamMembersTableTitle(MY_USERS_TAB.title) } else { - setTeamMembersTableTitle('Alle teammedlemmer') + setTeamMembersTableTitle(ALL_USERS_TAB.title) } } - const renderUserNameColumn = (user: User) => { - return ( - <> - - - {user.display_name} - - - {user.section_name && {user.section_name}} - - ) - } - const renderErrorAlert = () => { return ( @@ -128,13 +129,16 @@ const TeamMembers = () => { <> diff --git a/src/pages/TeamOverview/TeamOverview.tsx b/src/pages/TeamOverview/TeamOverview.tsx index 978e0aea..6daacfc8 100644 --- a/src/pages/TeamOverview/TeamOverview.tsx +++ b/src/pages/TeamOverview/TeamOverview.tsx @@ -1,38 +1,44 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { useCallback, useEffect, useState } from 'react' -import { Dialog, Text, Link, Tabs, Divider } from '@statisticsnorway/ssb-component-library' +import { Dialog, Tabs, Divider } from '@statisticsnorway/ssb-component-library' import { TabProps } from '../../@types/pageTypes' import PageLayout from '../../components/PageLayout/PageLayout' import Table, { TableData } from '../../components/Table/Table' import PageSkeleton from '../../components/PageSkeleton/PageSkeleton' -import { fetchTeamOverviewData, TeamOverviewData, Team } from '../../services/teamOverview' +import { fetchTeamOverviewData, TeamOverviewData } from '../../services/teamOverview' import { formatDisplayName } from '../../utils/utils' import { ApiError, fetchUserInformationFromAuthToken } from '../../utils/services' +import FormattedTableColumn from '../../components/FormattedTableColumn' -const TeamOverview = () => { - const defaultActiveTab = { - title: 'Mine team', - path: 'myTeams', - } +const MY_TEAMS_TAB = { + title: 'Mine team', + path: 'myTeams', +} - const [activeTab, setActiveTab] = useState(defaultActiveTab) +const ALL_TEAMS_TAB = { + title: 'Alle teams', + path: 'allTeams', +} + +const TeamOverview = () => { + const [activeTab, setActiveTab] = useState(MY_TEAMS_TAB) const [teamOverviewData, setTeamOverviewData] = useState() const [teamOverviewTableData, setTeamOverviewTableData] = useState() - const [teamOverviewTableTitle, setTeamOverviewTableTitle] = useState(defaultActiveTab.title) + const [teamOverviewTableTitle, setTeamOverviewTableTitle] = useState(MY_TEAMS_TAB.title) const [error, setError] = useState() const [loading, setLoading] = useState(true) const prepTeamData = useCallback( (response: TeamOverviewData): TableData['data'] => { const teamTab = (activeTab as TabProps)?.path ?? activeTab - return response[teamTab].teams.map((team) => ({ - id: team.uniform_name, - seksjon: team.section_name, // Makes section name searchable and sortable in table by including the field - navn: renderTeamNameColumn(team), - teammedlemmer: team.users.length, - ansvarlig: formatDisplayName(team.manager.display_name), + return response[teamTab].teams.map(({ uniform_name, section_name, users, manager }) => ({ + id: uniform_name, + seksjon: section_name, // Makes section name searchable and sortable in table by including the field + navn: , + teammedlemmer: users.length, + ansvarlig: formatDisplayName(manager.display_name), })) }, [activeTab] @@ -65,26 +71,13 @@ const TeamOverview = () => { const handleTabClick = (tab: string) => { setActiveTab(tab) - if (tab === defaultActiveTab.path) { - setTeamOverviewTableTitle(defaultActiveTab.title) + if (tab === MY_TEAMS_TAB.path) { + setTeamOverviewTableTitle(MY_TEAMS_TAB.title) } else { - setTeamOverviewTableTitle('Alle teams') + setTeamOverviewTableTitle(ALL_TEAMS_TAB.title) } } - const renderTeamNameColumn = (team: Team) => { - return ( - <> - - - {team.uniform_name} - - - {team.section_name && {team.section_name}} - - ) - } - const renderErrorAlert = () => { return ( @@ -117,13 +110,16 @@ const TeamOverview = () => { <> diff --git a/src/pages/UserProfile/UserProfile.tsx b/src/pages/UserProfile/UserProfile.tsx index 37c1c3b7..137420d0 100644 --- a/src/pages/UserProfile/UserProfile.tsx +++ b/src/pages/UserProfile/UserProfile.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-hooks/exhaustive-deps */ import styles from './userprofile.module.scss' -import { Dialog, Text, Link, LeadParagraph } from '@statisticsnorway/ssb-component-library' +import { Dialog, Text, LeadParagraph } from '@statisticsnorway/ssb-component-library' import Table, { TableData } from '../../components/Table/Table' import PageLayout from '../../components/PageLayout/PageLayout' @@ -11,11 +11,12 @@ import { useCallback, useContext, useEffect, useState } from 'react' import { DaplaCtrlContext } from '../../provider/DaplaCtrlProvider' import { getGroupType, formatDisplayName } from '../../utils/utils' -import { getUserProfileTeamData, TeamsData, Team } from '../../services/userProfile' +import { getUserProfileTeamData, TeamsData } from '../../services/userProfile' import { useParams } from 'react-router-dom' import { Skeleton } from '@mui/material' import { ApiError } from '../../utils/services' +import FormattedTableColumn from '../../components/FormattedTableColumn' const UserProfile = () => { const { setBreadcrumbUserProfileDisplayName } = useContext(DaplaCtrlContext) @@ -27,17 +28,17 @@ const UserProfile = () => { const prepTeamData = useCallback( (response: TeamsData): TableData['data'] => { - return response.teams.map((team) => ({ - id: team.uniform_name, - seksjon: team.section_name, // Makes section name searchable and sortable in table by including the field - navn: renderTeamNameColumn(team), + return response.teams.map(({ uniform_name, section_name, groups, manager }) => ({ + id: uniform_name, + seksjon: section_name, // Makes section name searchable and sortable in table by including the field + navn: , gruppe: principalName - ? team.groups + ? groups ?.filter((group) => group.users.some((user) => user.principal_name === principalName)) // Filter groups based on principalName presence .map((group) => getGroupType(group.uniform_name)) .join(', ') : 'INGEN FUNNET', - ansvarlig: formatDisplayName(team.manager.display_name), + ansvarlig: formatDisplayName(manager.display_name), })) }, [userProfileData] @@ -59,19 +60,6 @@ const UserProfile = () => { }) }, [principalName, setBreadcrumbUserProfileDisplayName]) - const renderTeamNameColumn = (team: Team) => { - return ( - <> - - - {team.uniform_name} - - - {team.section_name && {team.section_name}} - - ) - } - const renderErrorAlert = () => { return (