Skip to content
Snippets Groups Projects
Unverified Commit b7167616 authored by Alexander Polyankin's avatar Alexander Polyankin Committed by GitHub
Browse files

Add write checks (#20762)

parent 77af6de5
No related branches found
No related tags found
No related merge requests found
......@@ -3,4 +3,5 @@ export type CollectionId = number | string;
export interface Collection {
id: CollectionId;
name: string;
can_write: boolean;
}
......@@ -5,5 +5,6 @@ export const createMockCollection = (
): Collection => ({
id: 1,
name: "Collection",
can_write: false,
...opts,
});
......@@ -61,9 +61,11 @@ const EventCard = ({
)}
<CardCreatorInfo>{creatorMessage}</CardCreatorInfo>
</CardBody>
<CardAside>
<EntityMenu items={menuItems} triggerIcon="ellipsis" />
</CardAside>
{menuItems.length > 0 && (
<CardAside>
<EntityMenu items={menuItems} triggerIcon="ellipsis" />
</CardAside>
)}
</CardRoot>
);
};
......@@ -75,7 +77,9 @@ const getMenuItems = (
onArchive?: (event: TimelineEvent) => void,
onUnarchive?: (event: TimelineEvent) => void,
) => {
if (!event.archived) {
if (!collection.can_write) {
return [];
} else if (!event.archived) {
return [
{
title: t`Edit event`,
......
......@@ -15,7 +15,6 @@ export const ModalToolbar = styled.div`
export const ModalToolbarInput = styled(TextInput)`
flex: 1 1 auto;
margin-right: 1rem;
${TextInput.Input} {
height: 2.5rem;
......@@ -27,6 +26,7 @@ export const ModalToolbarLink = styled(Link)`
flex: 0 0 auto;
align-items: center;
height: 2.5rem;
margin-left: 1rem;
`;
export const ModalBody = styled.div`
......
......@@ -19,6 +19,7 @@ import {
ModalToolbarInput,
ModalToolbarLink,
} from "./TimelineDetailsModal.styled";
import { MenuItem } from "../../types";
export interface TimelineDetailsModalProps {
timeline: Timeline;
......@@ -50,16 +51,19 @@ const TimelineDetailsModal = ({
}, [timeline, searchText, isArchive]);
const menuItems = useMemo(() => {
return getMenuItems(timeline, collection);
}, [timeline, collection]);
return getMenuItems(timeline, collection, isArchive);
}, [timeline, collection, isArchive]);
const isNotEmpty = events.length > 0;
const isSearching = searchText.length > 0;
const canWrite = collection.can_write;
return (
<ModalRoot>
<ModalHeader title={title} onClose={onClose}>
{!isArchive && <EntityMenu items={menuItems} triggerIcon="ellipsis" />}
{menuItems.length > 0 && (
<EntityMenu items={menuItems} triggerIcon="ellipsis" />
)}
</ModalHeader>
{(isNotEmpty || isSearching) && (
<ModalToolbar>
......@@ -69,7 +73,7 @@ const TimelineDetailsModal = ({
icon={<Icon name="search" />}
onChange={setInputText}
/>
{!isArchive && (
{canWrite && !isArchive && (
<ModalToolbarLink
className="Button"
to={Urls.newEventInCollection(timeline, collection)}
......@@ -119,21 +123,34 @@ const isEventMatch = (event: TimelineEvent, searchText: string) => {
);
};
const getMenuItems = (timeline: Timeline, collection: Collection) => {
return [
{
title: t`New timeline`,
link: Urls.newTimelineInCollection(collection),
},
{
title: t`Edit timeline details`,
link: Urls.editTimelineInCollection(timeline, collection),
},
{
const getMenuItems = (
timeline: Timeline,
collection: Collection,
isArchive: boolean,
) => {
const items: MenuItem[] = [];
if (collection.can_write && !isArchive) {
items.push(
{
title: t`New timeline`,
link: Urls.newTimelineInCollection(collection),
},
{
title: t`Edit timeline details`,
link: Urls.editTimelineInCollection(timeline, collection),
},
);
}
if (!isArchive) {
items.push({
title: t`View archived events`,
link: Urls.timelineArchiveInCollection(timeline, collection),
},
];
});
}
return items;
};
export default TimelineDetailsModal;
......@@ -66,9 +66,11 @@ const TimelineEmptyState = ({
<EmptyStateMessage>
{t`Add events to Metabase to open important milestones, launches, or anything else, right alongside your data.`}
</EmptyStateMessage>
<Link className="Button Button--primary" to={link}>
{t`Add an event`}
</Link>
{collection.can_write && (
<Link className="Button Button--primary" to={link}>
{t`Add an event`}
</Link>
)}
</EmptyStateBody>
</EmptyStateRoot>
);
......
......@@ -19,13 +19,14 @@ const TimelineListModal = ({
collection,
onClose,
}: TimelineListModalProps): JSX.Element => {
const canWrite = collection.can_write;
const hasTimelines = timelines.length > 0;
const title = hasTimelines ? t`Events` : t`${collection.name} events`;
return (
<div>
<ModalHeader title={title} onClose={onClose}>
{hasTimelines && <TimelineMenu collection={collection} />}
{canWrite && hasTimelines && <TimelineMenu collection={collection} />}
</ModalHeader>
<ModalBody>
{hasTimelines ? (
......
export interface MenuItem {
title: string;
link?: string;
action?: () => void;
}
export interface ModalParams {
slug: string;
timelineId?: string;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment