Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {Loader} from '@mantine/core';
import {useEffect, useState} from 'preact/hooks';
import {joinClassNames} from '../../utils/classes.js';
import {getDocFromCacheOrFetch} from '../../utils/doc-cache.js';
import {getDocServingUrl} from '../../utils/doc-urls.js';
import {notifyErrors} from '../../utils/notifications.js';
import {getNestedValue} from '../../utils/objects.js';
import {DocStatusBadges} from '../DocStatusBadges/DocStatusBadges.js';
Expand Down Expand Up @@ -57,7 +56,7 @@ export function DocPreviewCard(props: DocPreviewCardProps) {
return;
}

const [collection, slug] = docId.split('/');
const [collection] = docId.split('/');
const fields = doc.fields || {};
const rootCollection = window.__ROOT_CTX.collections[collection];
if (!rootCollection) {
Expand All @@ -75,10 +74,6 @@ export function DocPreviewCard(props: DocPreviewCardProps) {
const previewImage =
getNestedValue(fields, rootCollection.preview?.image || 'meta.image') ||
rootCollection.preview?.defaultImage;
const docServingUrl = getDocServingUrl({
collectionId: collection,
slug: slug,
});

let Component: 'div' | 'a' = 'div';
const attrs: Record<string, any> = {};
Expand Down Expand Up @@ -117,9 +112,6 @@ export function DocPreviewCard(props: DocPreviewCardProps) {
<DocStatusBadges doc={doc} />
</div>
)}
{props.variant !== 'compact' && docServingUrl && (
<div className="DocPreviewCard__content__url">{docServingUrl}</div>
)}
</div>
</Component>
);
Expand Down
112 changes: 88 additions & 24 deletions packages/root-cms/ui/pages/EditReleasePage/EditReleasePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {ActionIcon, Breadcrumbs, Tooltip} from '@mantine/core';
import {useModals} from '@mantine/modals';
import {showNotification, updateNotification} from '@mantine/notifications';
import {IconTrashFilled} from '@tabler/icons-preact';
import {IconArchive, IconRestore} from '@tabler/icons-preact';
import {useEffect, useState} from 'preact/hooks';
import {route} from 'preact-router';
import {ConditionalTooltip} from '../../components/ConditionalTooltip/ConditionalTooltip.js';
import {Heading} from '../../components/Heading/Heading.js';
Expand All @@ -12,45 +13,57 @@ import {useProjectRoles} from '../../hooks/useProjectRoles.js';
import {Layout} from '../../layout/Layout.js';
import {testCanPublish} from '../../utils/permissions.js';
import './EditReleasePage.css';
import {deleteRelease} from '../../utils/release.js';
import {
Release,
archiveRelease,
getRelease,
unarchiveRelease,
} from '../../utils/release.js';

export function EditReleasePage(props: {id: string}) {
const [release, setRelease] = useState<Release | null>(null);
const modals = useModals();
const modalTheme = useModalTheme();
const {roles} = useProjectRoles();
const currentUserEmail = window.firebase.user.email || '';
const canPublish = testCanPublish(roles, currentUserEmail);

function onDeleteClicked() {
const notificationId = `delete-release-${props.id}`;
useEffect(() => {
getRelease(props.id).then((release) => {
setRelease(release);
});
}, [props.id]);

function onArchiveClicked() {
const notificationId = `archive-release-${props.id}`;
const modalId = modals.openConfirmModal({
...modalTheme,
title: 'Delete release',
title: 'Archive release',
children: (
<Text size="body-sm" weight="semi-bold">
Are you sure you want to delete release <code>{props.id}</code>? There
is no undo. This will only delete the release; the docs in the release
will remain unchanged.
Are you sure you want to archive release <code>{props.id}</code>?
</Text>
),
labels: {confirm: 'Delete', cancel: 'Cancel'},
labels: {confirm: 'Archive', cancel: 'Cancel'},
cancelProps: {size: 'xs'},
confirmProps: {color: 'red', size: 'xs'},
onCancel: () => console.log('Cancel'),
closeOnConfirm: false,
onConfirm: async () => {
showNotification({
id: notificationId,
title: 'Deleting release',
message: `Deleting ${props.id}...`,
title: 'Archiving release',
message: `Archiving ${props.id}...`,
loading: true,
autoClose: false,
});
await deleteRelease(props.id);
await archiveRelease(props.id);
const newRelease = await getRelease(props.id);
setRelease(newRelease);
updateNotification({
id: notificationId,
title: 'Deleted release',
message: `Successfully deleted ${props.id}`,
title: 'Archived release',
message: `Successfully archived ${props.id}`,
loading: false,
autoClose: 5000,
});
Expand All @@ -60,6 +73,45 @@ export function EditReleasePage(props: {id: string}) {
});
}

function onUnarchiveClicked() {
const notificationId = `unarchive-release-${props.id}`;
const modalId = modals.openConfirmModal({
...modalTheme,
title: 'Unarchive release',
children: (
<Text size="body-sm" weight="semi-bold">
Are you sure you want to unarchive release <code>{props.id}</code>?
</Text>
),
labels: {confirm: 'Unarchive', cancel: 'Cancel'},
cancelProps: {size: 'xs'},
confirmProps: {color: 'dark', size: 'xs'},
onCancel: () => console.log('Cancel'),
closeOnConfirm: false,
onConfirm: async () => {
showNotification({
id: notificationId,
title: 'Unarchiving release',
message: `Unarchiving ${props.id}...`,
loading: true,
autoClose: false,
});
await unarchiveRelease(props.id);
const newRelease = await getRelease(props.id);
setRelease(newRelease);
updateNotification({
id: notificationId,
title: 'Unarchived release',
message: `Successfully unarchived ${props.id}`,
loading: false,
autoClose: 5000,
});
modals.closeModal(modalId);
route(`/cms/releases/${props.id}`);
},
});
}

return (
<Layout>
<div className="EditReleasePage">
Expand All @@ -73,18 +125,30 @@ export function EditReleasePage(props: {id: string}) {
<Heading size="h1">Edit Release: {props.id}</Heading>
<div className="EditReleasePage__header__controls">
<ConditionalTooltip
label="You don't have access to delete releases"
label="You don't have access to archive releases"
condition={!canPublish}
>
<Tooltip label="Delete" disabled={!canPublish}>
<ActionIcon
onClick={onDeleteClicked}
loading={!roles}
disabled={!canPublish}
>
<IconTrashFilled size={20} stroke="1.5" />
</ActionIcon>
</Tooltip>
{release?.archivedAt ? (
<Tooltip label="Unarchive" disabled={!canPublish}>
<ActionIcon
onClick={onUnarchiveClicked}
loading={!roles}
disabled={!canPublish}
>
<IconRestore size={20} stroke="1.5" />
</ActionIcon>
</Tooltip>
) : (
<Tooltip label="Archive" disabled={!canPublish}>
<ActionIcon
onClick={onArchiveClicked}
loading={!roles}
disabled={!canPublish}
>
<IconArchive size={20} stroke="1.5" />
</ActionIcon>
</Tooltip>
)}
</ConditionalTooltip>
</div>
</div>
Expand Down
88 changes: 3 additions & 85 deletions packages/root-cms/ui/pages/ReleasePage/ReleasePage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import './ReleasePage.css';

import {
ActionIcon,
Breadcrumbs,
Expand All @@ -8,12 +10,7 @@ import {
} from '@mantine/core';
import {useModals} from '@mantine/modals';
import {showNotification, updateNotification} from '@mantine/notifications';
import {
IconArchive,
IconArchiveOff,
IconRestore,
IconSettings,
} from '@tabler/icons-preact';
import {IconSettings} from '@tabler/icons-preact';
import {useEffect, useState} from 'preact/hooks';
import {ConditionalTooltip} from '../../components/ConditionalTooltip/ConditionalTooltip.js';
import {DocPreviewCard} from '../../components/DocPreviewCard/DocPreviewCard.js';
Expand All @@ -31,24 +28,15 @@ import {
cancelScheduledRelease,
getRelease,
publishRelease,
archiveRelease,
unarchiveRelease,
} from '../../utils/release.js';
import {timestamp} from '../../utils/time.js';
import './ReleasePage.css';

export function ReleasePage(props: {id: string}) {
const [loading, setLoading] = useState(true);
const [release, setRelease] = useState<Release | null>(null);
const [updated, setUpdated] = useState(0);
const id = props.id;

const modals = useModals();
const modalTheme = useModalTheme();
const {roles} = useProjectRoles();
const currentUserEmail = window.firebase.user.email || '';
const canPublish = testCanPublish(roles, currentUserEmail);

async function init() {
setLoading(true);
await notifyErrors(async () => {
Expand All @@ -68,48 +56,6 @@ export function ReleasePage(props: {id: string}) {
init();
}

function onArchiveClicked() {
modals.openConfirmModal({
...modalTheme,
title: `Archive release: ${id}`,
children: (
<Text size="body-sm" weight="semi-bold">
Are you sure you want to archive this release?
</Text>
),
labels: {confirm: 'Archive', cancel: 'Cancel'},
cancelProps: {size: 'xs'},
confirmProps: {color: 'dark', size: 'xs'},
closeOnConfirm: true,
onConfirm: async () => {
await notifyErrors(async () => {
await archiveRelease(id);
});
},
});
}

function onUnarchiveClicked() {
modals.openConfirmModal({
...modalTheme,
title: `Unarchive release: ${id}`,
children: (
<Text size="body-sm" weight="semi-bold">
Are you sure you want to unarchive this release?
</Text>
),
labels: {confirm: 'Unarchive', cancel: 'Cancel'},
cancelProps: {size: 'xs'},
confirmProps: {color: 'dark', size: 'xs'},
closeOnConfirm: true,
onConfirm: async () => {
await notifyErrors(async () => {
await unarchiveRelease(id);
});
},
});
}

return (
<Layout>
<div className="ReleasePage">
Expand Down Expand Up @@ -158,34 +104,6 @@ export function ReleasePage(props: {id: string}) {
key={`data-sources-${updated}`}
/>
)}
{release && canPublish && (
<div className="ReleasePage__footer">
{release.archivedAt ? (
<Button
className="ReleasePage__footer__unarchive"
variant="default"
size="xs"
leftIcon={<IconRestore size={16} />}
onClick={() => onUnarchiveClicked()}
disabled={!canPublish}
>
Unarchive Release
</Button>
) : (
<Button
className="ReleasePage__footer__archive"
variant="filled"
color="red"
size="xs"
leftIcon={<IconArchive size={16} />}
onClick={() => onArchiveClicked()}
disabled={!canPublish}
>
Archive Release
</Button>
)}
</div>
)}
</>
)}
</div>
Expand Down
Loading