mirror of https://github.com/buster-so/buster.git
sharing updates part 1
This commit is contained in:
parent
e4a8957d72
commit
4608e8573e
|
@ -16,9 +16,6 @@ export enum ShareAssetType {
|
|||
export interface BusterShare {
|
||||
sharingKey: string;
|
||||
individual_permissions: null | BusterShareIndividual[];
|
||||
team_permissions: null | { name: string; id: string; role: ShareRole }[];
|
||||
organization_permissions: null | [];
|
||||
password_secret_id: string | null;
|
||||
public_expiry_date: string | null;
|
||||
public_enabled_by: string | null;
|
||||
publicly_accessible: boolean;
|
||||
|
@ -29,6 +26,5 @@ export interface BusterShare {
|
|||
export interface BusterShareIndividual {
|
||||
email: string;
|
||||
role: ShareRole;
|
||||
id: string;
|
||||
name: string;
|
||||
name?: string;
|
||||
}
|
||||
|
|
|
@ -5,31 +5,19 @@ import { ShareRole } from '../share/shareInterfaces';
|
|||
*
|
||||
* @interface ShareRequest
|
||||
*/
|
||||
export type ShareRequest = {
|
||||
/** The unique identifier of the dashboard */
|
||||
id: string;
|
||||
/** User-specific permissions array */
|
||||
user_permissions?: {
|
||||
/** Email of the user to grant permissions to */
|
||||
user_email: string;
|
||||
/** Role to assign to the user */
|
||||
export type SharePostRequest = {
|
||||
email: string;
|
||||
role: ShareRole;
|
||||
}[];
|
||||
|
||||
export type ShareDeleteRequest = string[];
|
||||
|
||||
export type ShareUpdateRequest = {
|
||||
users?: {
|
||||
email: string;
|
||||
role: ShareRole;
|
||||
}[];
|
||||
/** Array of user IDs to remove access from */
|
||||
remove_users?: string[];
|
||||
/** Team-specific permissions array */
|
||||
team_permissions?: {
|
||||
/** ID of the team to grant permissions to */
|
||||
team_id: string;
|
||||
/** Role to assign to the team */
|
||||
role: ShareRole;
|
||||
}[];
|
||||
/** Array of team IDs to remove access from */
|
||||
remove_teams?: string[];
|
||||
/** Whether the dashboard is publicly accessible */
|
||||
publicly_accessible?: boolean;
|
||||
/** Optional password for public access */
|
||||
public_password?: string | null;
|
||||
/** Optional expiration date for public access (timestamptz) */
|
||||
public_expiry_date?: string | null;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { ShareRole } from '@/api/asset_interfaces';
|
||||
import type { BusterCollection, BusterCollectionListItem } from '@/api/asset_interfaces/collection';
|
||||
import {
|
||||
ShareDeleteRequest,
|
||||
SharePostRequest,
|
||||
ShareUpdateRequest
|
||||
} from '@/api/asset_interfaces/shared_interfaces';
|
||||
import mainApi from '@/api/buster_rest/instances';
|
||||
import type {
|
||||
CreateCollectionParams,
|
||||
|
@ -33,3 +39,29 @@ export const collectionsUpdateCollection = async (params: UpdateCollectionParams
|
|||
export const collectionsDeleteCollection = async (params: DeleteCollectionParams) => {
|
||||
return await mainApi.delete<BusterCollection>('/collections', { params }).then((res) => res.data);
|
||||
};
|
||||
|
||||
// share collections
|
||||
|
||||
export const shareCollection = async ({ id, params }: { id: string; params: SharePostRequest }) => {
|
||||
return mainApi
|
||||
.post<BusterCollection>(`/collections/${id}/sharing`, params)
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const unshareCollection = async ({ id, data }: { id: string; data: ShareDeleteRequest }) => {
|
||||
return mainApi
|
||||
.delete<BusterCollection>(`/collections/${id}/sharing`, { data })
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const updateCollectionShare = async ({
|
||||
data,
|
||||
id
|
||||
}: {
|
||||
id: string;
|
||||
data: ShareUpdateRequest;
|
||||
}) => {
|
||||
return mainApi
|
||||
.put<BusterCollection>(`/collections/${id}/sharing`, { data })
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,10 @@ import {
|
|||
dashboardsGetDashboard,
|
||||
dashboardsCreateDashboard,
|
||||
dashboardsUpdateDashboard,
|
||||
dashboardsDeleteDashboard
|
||||
dashboardsDeleteDashboard,
|
||||
shareDashboard,
|
||||
updateDashboardShare,
|
||||
unshareDashboard
|
||||
} from './requests';
|
||||
import type { DashboardsListRequest } from '@/api/request_interfaces/dashboards/interfaces';
|
||||
import { dashboardQueryKeys } from '@/api/query_keys/dashboard';
|
||||
|
@ -228,3 +231,76 @@ export const useRemoveItemFromDashboard = () => {
|
|||
mutationFn
|
||||
});
|
||||
};
|
||||
|
||||
export const useShareDashboard = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: shareDashboard,
|
||||
onMutate: (variables) => {
|
||||
const queryKey = dashboardQueryKeys.dashboardGetDashboard(variables.id).queryKey;
|
||||
queryClient.setQueryData(queryKey, (previousData) => {
|
||||
return create(previousData!, (draft) => {
|
||||
draft.individual_permissions?.push(...variables.params);
|
||||
});
|
||||
});
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData(
|
||||
dashboardQueryKeys.dashboardGetDashboard(data.dashboard.id).queryKey,
|
||||
data
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useUnshareDashboard = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: unshareDashboard,
|
||||
onMutate: (variables) => {
|
||||
const queryKey = dashboardQueryKeys.dashboardGetDashboard(variables.id).queryKey;
|
||||
queryClient.setQueryData(queryKey, (previousData) => {
|
||||
return create(previousData!, (draft) => {
|
||||
draft.individual_permissions =
|
||||
draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || [];
|
||||
});
|
||||
});
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData(
|
||||
dashboardQueryKeys.dashboardGetDashboard(data.dashboard.id).queryKey,
|
||||
data
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateDashboardShare = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: updateDashboardShare,
|
||||
onMutate: (variables) => {
|
||||
const queryKey = dashboardQueryKeys.dashboardGetDashboard(variables.id).queryKey;
|
||||
queryClient.setQueryData(queryKey, (previousData) => {
|
||||
return create(previousData!, (draft) => {
|
||||
draft.individual_permissions =
|
||||
draft.individual_permissions!.map((t) => {
|
||||
const found = variables.data.users?.find((v) => v.email === t.email);
|
||||
if (found) return found;
|
||||
return t;
|
||||
}) || [];
|
||||
|
||||
if (variables.data.publicly_accessible !== undefined) {
|
||||
draft.publicly_accessible = variables.data.publicly_accessible;
|
||||
}
|
||||
if (variables.data.public_password !== undefined) {
|
||||
draft.public_password = variables.data.public_password;
|
||||
}
|
||||
if (variables.data.public_expiry_date !== undefined) {
|
||||
draft.public_expiry_date = variables.data.public_expiry_date;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -9,6 +9,12 @@ import type {
|
|||
BusterDashboardListItem,
|
||||
BusterDashboardResponse
|
||||
} from '@/api/asset_interfaces/dashboard';
|
||||
import { ShareRole } from '@/api/asset_interfaces';
|
||||
import {
|
||||
ShareDeleteRequest,
|
||||
SharePostRequest,
|
||||
ShareUpdateRequest
|
||||
} from '@/api/asset_interfaces/shared_interfaces';
|
||||
|
||||
export const dashboardsGetList = async (params: DashboardsListRequest) => {
|
||||
return await mainApi
|
||||
|
@ -35,3 +41,29 @@ export const dashboardsUpdateDashboard = async (params: DashboardUpdateRequest)
|
|||
export const dashboardsDeleteDashboard = async ({ ids }: { ids: string[] }) => {
|
||||
return await mainApi.delete<null>(`/dashboards`, { data: { ids } }).then((res) => res.data);
|
||||
};
|
||||
|
||||
// share dashboards
|
||||
|
||||
export const shareDashboard = async ({ id, params }: { id: string; params: SharePostRequest }) => {
|
||||
return mainApi
|
||||
.post<BusterDashboardResponse>(`/dashboards/${id}/sharing`, params)
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const unshareDashboard = async ({ id, data }: { id: string; data: ShareDeleteRequest }) => {
|
||||
return mainApi
|
||||
.delete<BusterDashboardResponse>(`/dashboards/${id}/sharing`, { data })
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const updateDashboardShare = async ({
|
||||
data,
|
||||
id
|
||||
}: {
|
||||
id: string;
|
||||
data: ShareUpdateRequest;
|
||||
}) => {
|
||||
return mainApi
|
||||
.put<BusterDashboardResponse>(`/dashboards/${id}/sharing`, { data })
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric';
|
||||
import type { VerificationStatus } from '@/api/asset_interfaces/share';
|
||||
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
|
||||
|
||||
export interface GetMetricParams {
|
||||
id: string;
|
||||
|
@ -42,4 +41,4 @@ export type UpdateMetricParams = {
|
|||
status?: VerificationStatus;
|
||||
/** file in yaml format to update */
|
||||
file?: string;
|
||||
} & ShareRequest;
|
||||
};
|
||||
|
|
|
@ -6,6 +6,12 @@ import type {
|
|||
BusterMetricData,
|
||||
BusterMetricListItem
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import { ShareRole } from '@/api/asset_interfaces/share';
|
||||
import {
|
||||
ShareDeleteRequest,
|
||||
SharePostRequest,
|
||||
ShareUpdateRequest
|
||||
} from '@/api/asset_interfaces/shared_interfaces';
|
||||
|
||||
export const getMetric = async ({ id, password, version_number }: GetMetricParams) => {
|
||||
return mainApi
|
||||
|
@ -56,3 +62,23 @@ export const duplicateMetric = async (params: {
|
|||
}) => {
|
||||
return mainApi.post<BusterMetric>(`/metrics/duplicate`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
// share metrics
|
||||
|
||||
export const shareMetric = async ({ id, params }: { id: string; params: SharePostRequest }) => {
|
||||
return mainApi.post<BusterMetric>(`/metrics/${id}/sharing`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const unshareMetric = async ({ id, data }: { id: string; data: ShareDeleteRequest }) => {
|
||||
return mainApi.delete<BusterMetric>(`/metrics/${id}/sharing`, { data }).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const updateMetricShare = async ({
|
||||
params,
|
||||
id
|
||||
}: {
|
||||
id: string;
|
||||
params: ShareUpdateRequest;
|
||||
}) => {
|
||||
return mainApi.put<BusterMetric>(`/metrics/${id}/sharing`, { params }).then((res) => res.data);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
|
||||
import type { ShareAssetType } from '../../asset_interfaces';
|
||||
|
||||
export interface GetCollectionListParams {
|
||||
|
@ -41,7 +40,7 @@ export type UpdateCollectionParams = {
|
|||
/** Share request parameters */
|
||||
share_with?: string[];
|
||||
share_type?: string;
|
||||
} & ShareRequest;
|
||||
};
|
||||
|
||||
export interface DeleteCollectionParams {
|
||||
/** Array of collection IDs to be deleted */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { DashboardConfig } from '@/api/asset_interfaces/dashboard';
|
||||
import { VerificationStatus } from '@/api/asset_interfaces/share';
|
||||
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
|
||||
|
||||
/**
|
||||
* Interface for dashboard list request parameters
|
||||
|
@ -68,7 +67,7 @@ export type DashboardUpdateRequest = {
|
|||
metrics?: string[];
|
||||
/** The file content of the dashboard */
|
||||
file?: string;
|
||||
} & ShareRequest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for deleting dashboards
|
||||
|
|
|
@ -3,16 +3,11 @@ import { AppAssetCheckLayout } from '@/layouts/AppAssetCheckLayout';
|
|||
|
||||
export default async function MetricPage(props: {
|
||||
params: Promise<{ metricId: string }>;
|
||||
|
||||
searchParams: Promise<{ embed?: string }>;
|
||||
}) {
|
||||
const searchParams = await props.searchParams;
|
||||
const params = await props.params;
|
||||
const { embed } = searchParams;
|
||||
const { metricId } = params;
|
||||
|
||||
const embedView = embed === 'true';
|
||||
|
||||
return (
|
||||
<AppAssetCheckLayout assetId={metricId} type="metric">
|
||||
<MetricController metricId={metricId} />
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
import { Avatar } from '@/components/ui/avatar';
|
||||
import { AccessDropdown } from './AccessDropdown';
|
||||
|
||||
import React from 'react';
|
||||
import { ShareRole } from '@/api/asset_interfaces';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
|
||||
export const IndividualSharePerson: React.FC<{
|
||||
name: string;
|
||||
name?: string;
|
||||
email: string;
|
||||
role: ShareRole;
|
||||
id: string;
|
||||
onUpdateShareRole: (id: string, email: string, role: ShareRole | null) => void;
|
||||
}> = React.memo(({ name, onUpdateShareRole, email, id, role }) => {
|
||||
onUpdateShareRole: (email: string, role: ShareRole | null) => void;
|
||||
}> = React.memo(({ name, onUpdateShareRole, email, role }) => {
|
||||
const isSameEmailName = name === email;
|
||||
|
||||
const onChangeShareLevel = useMemoizedFn((v: ShareRole | null) => {
|
||||
onUpdateShareRole(id, email, v);
|
||||
onUpdateShareRole(email, v);
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -9,16 +9,15 @@ import { AccessDropdown } from './AccessDropdown';
|
|||
import { IndividualSharePerson } from './IndividualSharePerson';
|
||||
import { ShareMenuContentEmbed } from './ShareMenuContentEmbed';
|
||||
import { ShareMenuContentPublish } from './ShareMenuContentPublish';
|
||||
import { ShareWithGroupAndTeam } from './ShareWithTeamAndGroup';
|
||||
import { ShareMenuTopBarOptions } from './ShareMenuTopBar';
|
||||
import { useUserConfigContextSelector } from '@/context/Users';
|
||||
import { inputHasText } from '@/lib/text';
|
||||
import { UserGroup, ChevronRight } from '@/components/ui/icons';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
|
||||
import { useUpdateCollection } from '@/api/buster_rest/collections';
|
||||
import { useSaveMetric } from '@/api/buster_rest/metrics';
|
||||
import { useUpdateDashboard } from '@/api/buster_rest/dashboards';
|
||||
import { ShareUpdateRequest } from '@/api/asset_interfaces/shared_interfaces';
|
||||
|
||||
export const ShareMenuContentBody: React.FC<{
|
||||
selectedOptions: ShareMenuTopBarOptions;
|
||||
|
@ -44,8 +43,6 @@ export const ShareMenuContentBody: React.FC<{
|
|||
|
||||
const selectedClass = selectedOptions === ShareMenuTopBarOptions.Share ? '' : '';
|
||||
const individual_permissions = shareAssetConfig.individual_permissions;
|
||||
const team_permissions = shareAssetConfig.team_permissions;
|
||||
const organization_permissions = shareAssetConfig.organization_permissions;
|
||||
const publicly_accessible = shareAssetConfig.publicly_accessible;
|
||||
const publicExpirationDate = shareAssetConfig.public_expiry_date;
|
||||
const password = shareAssetConfig.public_password;
|
||||
|
@ -57,8 +54,6 @@ export const ShareMenuContentBody: React.FC<{
|
|||
goBack={goBack}
|
||||
onCopyLink={onCopyLink}
|
||||
individual_permissions={individual_permissions}
|
||||
team_permissions={team_permissions}
|
||||
organization_permissions={organization_permissions}
|
||||
publicly_accessible={publicly_accessible}
|
||||
publicExpirationDate={publicExpirationDate}
|
||||
password={password}
|
||||
|
@ -90,7 +85,6 @@ const ShareMenuContentShare: React.FC<{
|
|||
ShareRole.CAN_VIEW
|
||||
);
|
||||
const disableSubmit = !inputHasText(inputValue) || !validate(inputValue);
|
||||
const hasUserTeams = userTeams?.length > 0;
|
||||
const hasIndividualPermissions = !!individual_permissions?.length;
|
||||
|
||||
const onSubmitNewEmail = useMemoizedFn(async () => {
|
||||
|
@ -122,20 +116,17 @@ const ShareMenuContentShare: React.FC<{
|
|||
setInputValue('');
|
||||
});
|
||||
|
||||
const onUpdateShareRole = useMemoizedFn(
|
||||
async (userId: string, email: string, role: ShareRole | null) => {
|
||||
const payload: ShareRequest = { id: assetId };
|
||||
|
||||
if (!role) {
|
||||
payload.remove_users = [userId];
|
||||
} else {
|
||||
payload.user_permissions = [
|
||||
const onUpdateShareRole = useMemoizedFn(async (email: string, role: ShareRole | null) => {
|
||||
if (role) {
|
||||
const payload: ShareUpdateRequest & { id: string } = {
|
||||
id: assetId,
|
||||
users: [
|
||||
{
|
||||
user_email: email,
|
||||
email,
|
||||
role
|
||||
}
|
||||
];
|
||||
}
|
||||
]
|
||||
};
|
||||
if (assetType === ShareAssetType.METRIC) {
|
||||
await onShareMetric(payload);
|
||||
} else if (assetType === ShareAssetType.DASHBOARD) {
|
||||
|
@ -143,8 +134,9 @@ const ShareMenuContentShare: React.FC<{
|
|||
} else if (assetType === ShareAssetType.COLLECTION) {
|
||||
await onShareCollection(payload);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const onChangeInputValue = useMemoizedFn((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value);
|
||||
|
@ -195,7 +187,7 @@ const ShareMenuContentShare: React.FC<{
|
|||
<div className="flex flex-col space-y-2 overflow-hidden px-3">
|
||||
{individual_permissions?.map((permission) => (
|
||||
<IndividualSharePerson
|
||||
key={permission.id}
|
||||
key={permission.email}
|
||||
{...permission}
|
||||
onUpdateShareRole={onUpdateShareRole}
|
||||
/>
|
||||
|
@ -241,8 +233,6 @@ const ContentRecord: Record<
|
|||
goBack: () => void;
|
||||
onCopyLink: () => void;
|
||||
individual_permissions: BusterShare['individual_permissions'];
|
||||
team_permissions: BusterShare['team_permissions'];
|
||||
organization_permissions: BusterShare['organization_permissions'];
|
||||
publicly_accessible: boolean;
|
||||
publicExpirationDate: string | null | undefined;
|
||||
password: string | null | undefined;
|
||||
|
@ -253,6 +243,5 @@ const ContentRecord: Record<
|
|||
> = {
|
||||
Share: ShareMenuContentShare,
|
||||
Embed: ShareMenuContentEmbed,
|
||||
ShareWithGroupAndTeam: ShareWithGroupAndTeam,
|
||||
Publish: ShareMenuContentPublish
|
||||
};
|
||||
|
|
|
@ -8,8 +8,7 @@ import { type SegmentedItem } from '@/components/ui/segmented';
|
|||
export enum ShareMenuTopBarOptions {
|
||||
Share = 'Share',
|
||||
Publish = 'Publish',
|
||||
Embed = 'Embed',
|
||||
ShareWithGroupAndTeam = 'ShareWithGroupAndTeam'
|
||||
Embed = 'Embed'
|
||||
}
|
||||
|
||||
export const ShareMenuTopBar: React.FC<{
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { CopyLinkButton } from './CopyLinkButton';
|
||||
import { BackButton, Button } from '@/components/ui/buttons';
|
||||
import { AccessDropdown } from './AccessDropdown';
|
||||
import { useUserConfigContextSelector } from '@/context/Users';
|
||||
import { ShareRole } from '@/api/asset_interfaces';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { UserGroup } from '@/components/ui/icons';
|
||||
import { ShareAssetType } from '@/api/asset_interfaces';
|
||||
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
|
||||
import { useGetCollection, useUpdateCollection } from '@/api/buster_rest/collections';
|
||||
import { useGetMetric, useSaveMetric } from '@/api/buster_rest/metrics';
|
||||
import { useGetDashboard, useUpdateDashboard } from '@/api/buster_rest/dashboards';
|
||||
|
||||
export const ShareWithGroupAndTeam: React.FC<{
|
||||
goBack: () => void;
|
||||
onCopyLink: () => void;
|
||||
assetType: ShareAssetType;
|
||||
assetId: string;
|
||||
}> = ({ assetType, assetId, goBack, onCopyLink }) => {
|
||||
const userTeams = useUserConfigContextSelector((state) => state.userTeams);
|
||||
const { mutateAsync: onShareDashboard } = useUpdateDashboard();
|
||||
const { mutateAsync: onShareMetric } = useSaveMetric();
|
||||
const { mutateAsync: onShareCollection } = useUpdateCollection();
|
||||
const { data: dashboardResponse } = useGetDashboard(
|
||||
assetType === ShareAssetType.DASHBOARD ? assetId : undefined
|
||||
);
|
||||
const { data: collection } = useGetCollection(
|
||||
assetType === ShareAssetType.COLLECTION ? assetId : undefined
|
||||
);
|
||||
const { data: metric } = useGetMetric(
|
||||
assetType === ShareAssetType.METRIC ? { id: assetId } : { id: undefined }
|
||||
);
|
||||
|
||||
const onUpdateShareRole = useMemoizedFn(
|
||||
async ({ teamId, role }: { teamId: string; role: ShareRole | null }) => {
|
||||
const payload: ShareRequest = { id: assetId };
|
||||
if (!role) {
|
||||
payload.remove_teams = [teamId];
|
||||
} else {
|
||||
payload.team_permissions = [{ team_id: teamId, role }];
|
||||
}
|
||||
if (assetType === ShareAssetType.METRIC) {
|
||||
await onShareMetric(payload);
|
||||
} else if (assetType === ShareAssetType.DASHBOARD) {
|
||||
await onShareDashboard(payload);
|
||||
} else if (assetType === ShareAssetType.COLLECTION) {
|
||||
await onShareCollection(payload);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const listedTeam: { id: string; name: string; role: ShareRole | null }[] = useMemo(() => {
|
||||
const assosciatedPermissiongSearch = (teamId: string) => {
|
||||
if (assetType === ShareAssetType.METRIC && metric) {
|
||||
return metric.team_permissions?.find((t) => t.id === teamId);
|
||||
} else if (assetType === ShareAssetType.DASHBOARD && dashboardResponse) {
|
||||
return dashboardResponse.team_permissions?.find((t) => t.id === teamId);
|
||||
} else if (assetType === ShareAssetType.COLLECTION && collection) {
|
||||
return collection.team_permissions?.find((t) => t.id === teamId);
|
||||
}
|
||||
};
|
||||
return userTeams.reduce<{ id: string; name: string; role: ShareRole | null }[]>((acc, team) => {
|
||||
const assosciatedPermission = assosciatedPermissiongSearch(team.id);
|
||||
acc.push({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
role: assosciatedPermission?.role || null
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
}, [userTeams, dashboardResponse, metric, assetId, collection, assetType]);
|
||||
|
||||
const stuffToShow = listedTeam.length > 0 || userTeams.length === 0;
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex h-[40px] items-center justify-between space-x-1 px-3">
|
||||
<BackButton onClick={goBack} />
|
||||
<div>
|
||||
<CopyLinkButton onCopyLink={onCopyLink} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
|
||||
<div className="">
|
||||
{listedTeam.map((team) => (
|
||||
<ShareOption
|
||||
key={team.id}
|
||||
title={userTeams.length > 1 ? team.name : 'Your team'}
|
||||
role={team.role}
|
||||
onUpdateShareRole={(role) => {
|
||||
onUpdateShareRole({
|
||||
teamId: team.id,
|
||||
role
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{userTeams.length === 0 && (
|
||||
<div className="flex w-full items-center justify-center p-3">
|
||||
<Text variant="secondary">Not currently a member of any teams</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!stuffToShow && (
|
||||
<div className="flex w-full items-center justify-center p-3">
|
||||
<Text variant="secondary">No teams to share with</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ShareOption: React.FC<{
|
||||
title: string;
|
||||
onUpdateShareRole: (role: ShareRole | null) => void;
|
||||
role: ShareRole | null;
|
||||
}> = ({ onUpdateShareRole, title, role }) => {
|
||||
return (
|
||||
<div className={'flex h-[40px] cursor-pointer items-center justify-between space-x-2 px-3'}>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button prefix={<UserGroup />} />
|
||||
|
||||
<Text>{title}</Text>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<AccessDropdown
|
||||
groupShare
|
||||
shareLevel={role}
|
||||
onChangeShareLevel={(v) => {
|
||||
onUpdateShareRole(v);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -56,7 +56,6 @@ export const SelectChartType: React.FC<SelectChartTypeProps> = ({
|
|||
|
||||
const onSelectChartType = useMemoizedFn((chartIconType: ChartIconType) => {
|
||||
const chartConfig = selectedChartTypeMethod(chartIconType, columnSettings);
|
||||
console.log('chartConfig', chartConfig);
|
||||
onUpdateMetricChartConfig({ chartConfig });
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue