Skip to content

Commit

Permalink
fix: organization view
Browse files Browse the repository at this point in the history
  • Loading branch information
majkshkurti committed Sep 24, 2024
1 parent be196e5 commit a0fe873
Show file tree
Hide file tree
Showing 18 changed files with 593 additions and 417 deletions.
19 changes: 13 additions & 6 deletions apps/web/app/[lng]/(dashboard)/datasets/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { GetDatasetSchema } from "@/lib/validations/layer";

import { AddLayerSourceType } from "@/types/common";

import { useAuthZ } from "@/hooks/auth/AuthZ";
import { useJobStatus } from "@/hooks/jobs/JobStatus";

import ContentSearchBar from "@/components/dashboard/common/ContentSearchbar";
Expand Down Expand Up @@ -55,6 +56,7 @@ const Datasets = () => {
isError: _isDatasetError,
} = useLayers(queryParams, datasetSchema);

const { isOrgEditor } = useAuthZ();
useJobStatus(mutate);

const [addDatasetModal, setAddDatasetModal] = useState<AddLayerSourceType | null>(null);
Expand Down Expand Up @@ -107,12 +109,14 @@ const Datasets = () => {
mb: 8,
}}>
<Typography variant="h6">{t("datasets")}</Typography>
<Button
disableElevation={true}
startIcon={<Icon iconName={ICON_NAME.PLUS} style={{ fontSize: 12 }} />}
onClick={handleAddDatasetClick}>
{t("add_dataset")}
</Button>
{isOrgEditor && (
<Button
disableElevation={true}
startIcon={<Icon iconName={ICON_NAME.PLUS} style={{ fontSize: 12 }} />}
onClick={handleAddDatasetClick}>
{t("add_dataset")}
</Button>
)}
<Menu
anchorEl={addDatasetAnchorEl}
sx={{
Expand Down Expand Up @@ -160,6 +164,8 @@ const Datasets = () => {
<Paper elevation={3} sx={{ backgroundImage: "none" }}>
<FoldersTreeView
queryParams={datasetSchema}
enableActions={isOrgEditor}
hideMyContent={!isOrgEditor}
setQueryParams={(params, teamId, organizationId) => {
const newQueryParams = { ...queryParams, page: 1 };
delete newQueryParams.team_id;
Expand All @@ -181,6 +187,7 @@ const Datasets = () => {
items={datasets?.items ?? []}
isLoading={isDatasetLoading}
type="layer"
enableActions={isOrgEditor}
onClick={(item) => {
if (item && item.id) {
router.push(`/datasets/${item.id}`);
Expand Down
24 changes: 16 additions & 8 deletions apps/web/app/[lng]/(dashboard)/projects/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { useTranslation } from "@/i18n/client";
import { useProjects } from "@/lib/api/projects";
import type { GetProjectsQueryParams } from "@/lib/validations/project";

import { useAuthZ } from "@/hooks/auth/AuthZ";

import ContentSearchBar from "@/components/dashboard/common/ContentSearchbar";
import FoldersTreeView from "@/components/dashboard/common/FoldersTreeView";
import TileGrid from "@/components/dashboard/common/TileGrid";
Expand All @@ -30,6 +32,7 @@ const Projects = () => {
const { projects, isLoading: isProjectLoading, isError: _isProjectError } = useProjects(queryParams);

const [openProjectModal, setOpenProjectModal] = useState(false);
const { isOrgEditor } = useAuthZ();

return (
<Container sx={{ py: 10, px: 10 }} maxWidth="xl">
Expand All @@ -42,14 +45,16 @@ const Projects = () => {
mb: 8,
}}>
<Typography variant="h6">{t("projects")}</Typography>
<Button
disableElevation={true}
startIcon={<Icon iconName={ICON_NAME.PLUS} style={{ fontSize: 12 }} />}
onClick={() => {
setOpenProjectModal(true);
}}>
{t("new_project")}
</Button>
{isOrgEditor && (
<Button
disableElevation={true}
startIcon={<Icon iconName={ICON_NAME.PLUS} style={{ fontSize: 12 }} />}
onClick={() => {
setOpenProjectModal(true);
}}>
{t("new_project")}
</Button>
)}
</Box>
<Grid container justifyContent="space-between" spacing={4}>
<Grid item xs={12}>
Expand All @@ -65,6 +70,8 @@ const Projects = () => {
<Paper elevation={3}>
<FoldersTreeView
queryParams={queryParams}
enableActions={isOrgEditor}
hideMyContent={!isOrgEditor}
setQueryParams={(params, teamId, organizationId) => {
const newQueryParams = { ...params, page: 1 };
delete newQueryParams?.["team_id"];
Expand All @@ -83,6 +90,7 @@ const Projects = () => {
<TileGrid
view={view}
items={projects?.items ?? []}
enableActions={isOrgEditor}
isLoading={isProjectLoading}
type="project"
onClick={(item) => {
Expand Down
14 changes: 6 additions & 8 deletions apps/web/app/[lng]/(dashboard)/settings/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import { ICON_NAME, Icon } from "@p4b/ui/components/Icon";

import { useTranslation } from "@/i18n/client";

import { useUserProfile } from "@/lib/api/users";
import { isOrgAdmin } from "@/lib/utils/auth";
import { useAuthZ } from "@/hooks/auth/AuthZ";

interface SettingsLayoutProps {
children: React.ReactNode;
Expand All @@ -34,9 +33,8 @@ const SettingsLayout = (props: SettingsLayoutProps) => {
const { children } = props;
const pathname = usePathname();
const theme = useTheme();
const { userProfile, isLoading: isUserProfileLoading } = useUserProfile();
const { t, i18n } = useTranslation("common");

const { isOrgAdmin, isLoading: isUserProfileLoading } = useAuthZ();
const navigation = useMemo(
() => [
{
Expand All @@ -56,24 +54,24 @@ const SettingsLayout = (props: SettingsLayoutProps) => {
icon: ICON_NAME.ORGANIZATION,
label: t("organization"),
current: pathname?.includes("/organization"),
auth: isOrgAdmin(userProfile?.roles),
auth: isOrgAdmin,
},
{
link: "/settings/usage",
icon: ICON_NAME.CHART_PIE,
label: t("usage_and_quotas"),
current: pathname?.includes("/usage"),
auth: isOrgAdmin(userProfile?.roles),
auth: isOrgAdmin,
},
{
link: "/settings/billing",
icon: ICON_NAME.CREDIT_CARD,
label: t("billing"),
current: pathname?.includes("/billing"),
auth: isOrgAdmin(userProfile?.roles),
auth: isOrgAdmin,
},
],
[pathname, t, userProfile?.roles]
[pathname, t, isOrgAdmin]
);

return (
Expand Down
50 changes: 24 additions & 26 deletions apps/web/app/[lng]/(dashboard)/settings/teams/[teamId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import { ICON_NAME, Icon } from "@p4b/ui/components/Icon";
import { useOrganizationMembers } from "@/lib/api/organizations";
import { deleteTeam, updateTeam, useTeam, useTeamMembers } from "@/lib/api/teams";
import { useOrganization } from "@/lib/api/users";
import { isTeamOwner } from "@/lib/utils/auth";
import type { Team, TeamMember, TeamUpdate } from "@/lib/validations/team";
import { teamRoleEnum, teamUpdateSchema } from "@/lib/validations/team";

import type { TeamMemberActions } from "@/types/common";

import { useAuthZ } from "@/hooks/auth/AuthZ";
import { useMemberSettingsMoreMenu } from "@/hooks/dashboard/SettingsHooks";

import { CustomTabPanel, a11yProps } from "@/components/common/CustomTabPanel";
Expand All @@ -36,6 +36,9 @@ function TeamProfile({ team }: { team: Team }) {
const [isTeamUpdateBusy, setIsTeamUpdateBusy] = useState<boolean>(false);
const [confirmDeleteOrLeaveTeamDialogOpen, setConfirmDeleteOrLeaveTeamDialogOpen] = useState(false);
const router = useRouter();
const { isTeamOwner } = useAuthZ({
team,
});

const {
register: registerTeamUpdate,
Expand Down Expand Up @@ -104,7 +107,7 @@ function TeamProfile({ team }: { team: Team }) {
{t("team_information")}
</Typography>
<Typography variant="caption">
{isTeamOwner(team.role)
{isTeamOwner
? t("update_team_information_description")
: t("overview_team_information_description")}
</Typography>
Expand All @@ -116,12 +119,12 @@ function TeamProfile({ team }: { team: Team }) {
control={control}
title={t("team_avatar")}
avatar={team?.avatar ?? ""}
readOnly={!isTeamOwner(team.role)}
readOnly={!isTeamOwner}
/>

<TextField
required
InputProps={{ readOnly: !isTeamOwner(team.role) }}
InputProps={{ readOnly: !isTeamOwner }}
helperText={errors.name ? errors.name?.message : ""}
label={t("team_name")}
id="name"
Expand All @@ -130,15 +133,15 @@ function TeamProfile({ team }: { team: Team }) {
/>

<TextField
InputProps={{ readOnly: !isTeamOwner(team.role) }}
InputProps={{ readOnly: !isTeamOwner }}
helperText={errors.description ? errors.description?.message : ""}
label={t("team_description")}
id="description"
{...registerTeamUpdate("description")}
error={errors.description ? true : false}
/>

{isTeamOwner(team.role) && (
{isTeamOwner && (
<Stack direction="row" alignItems="center" justifyContent="flex-end">
<LoadingButton
loading={isTeamUpdateBusy}
Expand All @@ -160,13 +163,11 @@ function TeamProfile({ team }: { team: Team }) {
<Divider />
<ConfirmModal
open={confirmDeleteOrLeaveTeamDialogOpen}
title={isTeamOwner(team.role) ? t("delete_team") : t("leave_team")}
title={isTeamOwner ? t("delete_team") : t("leave_team")}
body={
<Trans
i18nKey={
isTeamOwner(team.role)
? "common:delete_team_confirmation_body"
: "common:leave_team_confirmation_body"
isTeamOwner ? "common:delete_team_confirmation_body" : "common:leave_team_confirmation_body"
}
components={{ b: <b />, ul: <ul />, li: <li /> }}
/>
Expand All @@ -179,24 +180,22 @@ function TeamProfile({ team }: { team: Team }) {
await _deleteOrLeaveTeam();
}}
closeText={t("close")}
confirmText={isTeamOwner(team.role) ? t("delete_team") : t("leave_team")}
confirmText={isTeamOwner ? t("delete_team") : t("leave_team")}
/>
<Box>
<Typography variant="body1" fontWeight="bold" color={theme.palette.error.main}>
{t("danger_zone")}
</Typography>
<Typography variant="caption">
{isTeamOwner(team.role) ? t("danger_zone_delete_team_description") : t("leave_team")}
{isTeamOwner ? t("danger_zone_delete_team_description") : t("leave_team")}
</Typography>
</Box>
<Divider />
<Stack>
<Typography variant="body1">
<Trans
i18nKey={
isTeamOwner(team.role)
? "common:danger_zone_delete_team_body"
: "common:danger_zone_leave_team_body"
isTeamOwner ? "common:danger_zone_delete_team_body" : "common:danger_zone_leave_team_body"
}
components={{ b: <b />, a: <b /> }}
/>
Expand All @@ -206,10 +205,7 @@ function TeamProfile({ team }: { team: Team }) {
<LoadingButton
size="large"
startIcon={
<Icon
fontSize="small"
iconName={isTeamOwner(team.role) ? ICON_NAME.TRASH : ICON_NAME.SIGNOUT}
/>
<Icon fontSize="small" iconName={isTeamOwner ? ICON_NAME.TRASH : ICON_NAME.SIGNOUT} />
}
variant="outlined"
color="error"
Expand All @@ -221,7 +217,7 @@ function TeamProfile({ team }: { team: Team }) {
setConfirmDeleteOrLeaveTeamDialogOpen(true);
}}>
<Typography variant="body1" fontWeight="bold" color="inherit">
{isTeamOwner(team.role) ? t("delete_team") : t("leave_team")}
{isTeamOwner ? t("delete_team") : t("leave_team")}
</Typography>
</LoadingButton>
</Stack>
Expand All @@ -244,7 +240,9 @@ function TeamMembers({ team }: { team: Team }) {
const teamMemberIds = new Set((teamMembers || []).map((member) => member.id));
return (organizationMembers || []).filter((member) => !teamMemberIds.has(member.id));
}, [teamMembers, organizationMembers]);

const { isTeamOwner } = useAuthZ({
team,
});
const {
activeMemberMoreMenuOptions,
pendingInvitationMoreMenuOptions,
Expand All @@ -269,7 +267,7 @@ function TeamMembers({ team }: { team: Team }) {
}}
/>
)}
{organizationMembers && teamMembers && isTeamOwner(team.role) && (
{organizationMembers && teamMembers && isTeamOwner && (
<TeamMemberInviteModal
open={openInviteModal}
onClose={() => {
Expand All @@ -285,15 +283,15 @@ function TeamMembers({ team }: { team: Team }) {
<Divider />
<Box>
<Typography variant="body1" fontWeight="bold">
{isTeamOwner(team.role) ? t("team_manage_members") : t("members")}
{isTeamOwner ? t("team_manage_members") : t("members")}
</Typography>
<Typography variant="caption">
{isTeamOwner(team.role) ? t("team_manage_members_description") : t("team_members_description")}
{isTeamOwner ? t("team_manage_members_description") : t("team_members_description")}
</Typography>
</Box>
<Divider />

{isTeamOwner(team.role) && (
{isTeamOwner && (
<Stack alignItems="flex-end">
<LoadingButton
variant="contained"
Expand All @@ -316,7 +314,7 @@ function TeamMembers({ team }: { team: Team }) {
pendingInvitationMoreMenuOptions={pendingInvitationMoreMenuOptions}
onMoreMenuItemClick={openMoreMenu}
type="team"
viewOnly={!isTeamOwner(team.role)}
viewOnly={!isTeamOwner}
/>
</Stack>
</>
Expand Down
8 changes: 4 additions & 4 deletions apps/web/app/[lng]/(dashboard)/settings/teams/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ import { ICON_NAME, Icon } from "@p4b/ui/components/Icon";
import { useTranslation } from "@/i18n/client";

import { useTeams } from "@/lib/api/teams";
import { useUserProfile } from "@/lib/api/users";
import { isOrgEditor } from "@/lib/utils/auth";

import { useAuthZ } from "@/hooks/auth/AuthZ";

import TeamCreateModal from "@/components/modals/settings/TeamCreateModal";

export default function Teams() {
const { t } = useTranslation("common");
const theme = useTheme();
const { userProfile, isLoading: isUserProfileLoading } = useUserProfile();
const [openTeamCreateModal, setOpenTeamCreateModal] = useState(false);
const { teams, mutate: mutateTeams, isLoading } = useTeams();
const { isOrgEditor, isLoading: isUserProfileLoading } = useAuthZ();
const router = useRouter();
return (
<>
Expand All @@ -55,7 +55,7 @@ export default function Teams() {
mutateTeams();
}}
/>
{isOrgEditor(userProfile?.roles) && (
{isOrgEditor && (
<Stack alignItems="flex-end">
<LoadingButton
variant="contained"
Expand Down
Loading

0 comments on commit a0fe873

Please sign in to comment.