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 @@ -14,7 +14,7 @@ export const Public: Story = {
args: {
...commonArgs,
file,
isAdmin: false,
canManagePost: false,
},
argTypes: {
sharePublicLink: { action: 'share public click' },
Expand All @@ -29,7 +29,7 @@ export const Private: Story = {
privacyLabel: 'Post is private',
numberOfFiles: 5,
file,
isAdmin: true,
canManagePost: true,
},
argTypes: {
sharePublicLink: { action: 'share public click' },
Expand All @@ -42,7 +42,7 @@ export const NoImage: Story = {
args: {
...commonArgs,
privacyLabel: 'Files are private',
isAdmin: false,
canManagePost: false,
},
argTypes: {
sharePublicLink: { action: 'share public click' },
Expand All @@ -54,7 +54,7 @@ export const NoImage: Story = {
export const Draft: Story = {
args: {
...commonArgs,
isAdmin: true,
canManagePost: true,
draftLabel: 'Draft',
},
argTypes: {
Expand All @@ -70,7 +70,7 @@ export const DraftPrivate: Story = {
...commonArgs,
privacyLabel: 'Post is private',
numberOfFiles: 5,
isAdmin: true,
canManagePost: true,
draftLabel: 'Draft',
file,
},
Expand Down
11 changes: 6 additions & 5 deletions web-components/src/components/cards/PostCard/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface PostCardProps {
author: User;
signers?: Array<User>;
privacyLabel?: string;
isAdmin?: boolean;
canManagePost?: boolean;
numberOfFiles?: number;
sharePublicLink: (ev: React.MouseEvent) => void;
sharePrivateLink: (ev: React.MouseEvent) => void;
Expand All @@ -47,7 +47,7 @@ export default function PostCard({
author,
signers,
privacyLabel,
isAdmin,
canManagePost,
numberOfFiles,
sharePublicLink,
sharePrivateLink,
Expand All @@ -71,7 +71,7 @@ export default function PostCard({
>
<ActionButton
draft={!!draftLabel}
isAdmin={isAdmin}
canManagePost={canManagePost}
sharePublicLink={sharePublicLink}
sharePrivateLink={sharePrivateLink}
onDelete={onDelete}
Expand Down Expand Up @@ -247,14 +247,15 @@ export default function PostCard({
</Box>
</Grid>
)}
{!hasFile && (
{!hasFile && (privacyLabel || draftLabel) && (
<Grid
className="xl:absolute xl:-top-[7px] xl:right-[25px]"
item
xs="auto"
sx={{
flexShrink: 0,
marginRight: '10px',
marginBottom: { xs: '0px', md: '20px', xlg: '0px' },
marginBottom: { xs: '0px', md: '20px', xl: '0px' },
}}
>
{!draftLabel && privacyLabel && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import { IconButton } from '@mui/material';

import {
Expand All @@ -10,17 +9,17 @@ import ShareIcon from '../../icons/ShareIcon';
const ActionButton = ({
publicPost,
draft,
isAdmin,
canManagePost,
sharePublicLink,
sharePrivateLink,
onDelete,
onEditDraft,
}: {
isAdmin?: boolean;
canManagePost?: boolean;
} & PostAdminButtonProps): JSX.Element => {
return (
<div className="z-[1] absolute top-5 right-5 lg:top-[15px] lg:right-[12px] cursor-pointer">
{isAdmin ? (
{canManagePost ? (
<PostAdminButton
publicPost={publicPost}
draft={draft}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';

import { RegenModalProps } from 'web-components/src/components/modal';
import { SadBeeModal } from 'web-components/src/components/modal/SadBeeModal/SadBeeModal';
import { CancelButtonFooter } from 'web-components/src/components/organisms/CancelButtonFooter/CancelButtonFooter';
import { Body, Title } from 'web-components/src/components/typography';

type DeletedDraftModalProps = {
onCancel: () => void;
onSubmit: () => void;
shouldSaveDraft: boolean;
} & RegenModalProps;

export const DeletedDraftModal = ({
onCancel,
onSubmit,
open,
onClose,
shouldSaveDraft,
}: DeletedDraftModalProps) => {
const { _ } = useLingui();
return (
<SadBeeModal open={open} onClose={onClose}>
<Title variant="h4" className="text-center my-20">
<Trans>Another user deleted this draft.</Trans>
<br />
{shouldSaveDraft ? (
<Trans>Restore and save your version?</Trans>
) : (
<Trans>Restore and publish your version?</Trans>
)}
</Title>
<Body size="lg" className="text-center mb-50">
{shouldSaveDraft ? (
<Trans>Save to keep your changes.</Trans>
) : (
<Trans>Publish to keep your changes.</Trans>
)}
</Body>
<CancelButtonFooter
label={shouldSaveDraft ? _(msg`save`) : _(msg`publish`)}
onCancel={onCancel}
onClick={onSubmit}
/>
</SadBeeModal>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';

import { RegenModalProps } from 'web-components/src/components/modal';
import { SadBeeModal } from 'web-components/src/components/modal/SadBeeModal/SadBeeModal';
import { CancelButtonFooter } from 'web-components/src/components/organisms/CancelButtonFooter/CancelButtonFooter';
import { Body, Title } from 'web-components/src/components/typography';

type EditedDraftModalProps = {
onCancel: () => void;
onSubmit: () => void;
shouldSaveDraft: boolean;
} & RegenModalProps;

export const EditedDraftModal = ({
onCancel,
onSubmit,
open,
onClose,
shouldSaveDraft,
}: EditedDraftModalProps) => {
const { _ } = useLingui();
return (
<SadBeeModal open={open} onClose={onClose}>
<Title variant="h4" className="text-center my-20">
<Trans>
Someone made changes to this draft while you were editing.
</Trans>
</Title>
<Body size="lg" className="text-center mb-50">
<Trans>You will overwrite their changes if you continue.</Trans>
</Body>
<CancelButtonFooter
label={
shouldSaveDraft
? _(msg`overwrite & save`)
: _(msg`overwrite & publish`)
}
onCancel={onCancel}
onClick={onSubmit}
/>
</SadBeeModal>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ export const POST_CREATED_SIGNING_FAILED = msg`You successfully created this pos
export const CREATE_DATA_POST = msg`Create Data Post`;
export const DRAFT_CREATED = msg`Draft created!`;
export const DRAFT_SAVED = msg`Draft saved!`;

export const DRAFT_SUBMIT_LABEL = 'save';
export const PUBLISH_SUBMIT_LABEL = 'publish';
102 changes: 96 additions & 6 deletions web-marketplace/src/components/organisms/PostFlow/PostFlow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { GeocodeFeature } from '@mapbox/mapbox-sdk/services/geocoding';
import { ContentHash_Graph } from '@regen-network/api/regen/data/v2/types';
Expand Down Expand Up @@ -45,7 +45,11 @@ import {
basePostContent,
DRAFT_CREATED,
DRAFT_SAVED,
DRAFT_SUBMIT_LABEL,
PUBLISH_SUBMIT_LABEL,
} from './PostFlow.constants';
import { DeletedDraftModal } from './PostFlow.DeletedDraftModal';
import { EditedDraftModal } from './PostFlow.EditedDraftModal';
import { SignModal } from './PostFlow.SignModal';

type Props = {
Expand Down Expand Up @@ -86,6 +90,15 @@ export const PostFlow = ({
const { activeAccount } = useAuth();
const userDao = useDaoOrganization();
const [isFormModalOpen, setIsFormModalOpen] = useState(true);
const [draftEditedModalLabel, setDraftEditedModalLabel] = useState<
string | undefined
>(undefined);
const [draftDeletedModalLabel, setDraftDeletedModalLabel] = useState<
string | undefined
>(undefined);
const [editedData, setEditedData] = useState<PostFormSchemaType | undefined>(
undefined,
);
const [iri, setIri] = useState<string | undefined>();
const { data: createdPostData, isFetching } = useQuery(
getPostQuery({
Expand All @@ -95,7 +108,6 @@ export const PostFlow = ({
}),
);
const { _ } = useLingui();
const { pathname } = useLocation();
const router = useRouter();

const [offChainProjectId, setOffChainProjectId] =
Expand All @@ -109,8 +121,9 @@ export const PostFlow = ({
const setErrorBannerTextAtom = useSetAtom(errorBannerTextAtom);
const setBannerText = useSetAtom(bannerTextAtom);
const draftPostIri = initialValues?.iri;
const draftPostId = initialValues?.id;

const onSubmit = useCallback(
const saveDataPost = useCallback(
async (data: PostFormSchemaType) => {
if (token) {
const files = data.files
Expand All @@ -131,9 +144,9 @@ export const PostFlow = ({
try {
await postData({
url: `${apiServerUrl}/marketplace/v1/posts${
draftPostIri ? `/${draftPostIri}` : ''
data?.iri ? `/${data.iri}` : ''
}`,
method: draftPostIri ? 'PUT' : 'POST',
method: data?.iri ? 'PUT' : 'POST',
data: {
projectId: offChainProjectId,
privacy: data.privacyType,
Expand Down Expand Up @@ -173,7 +186,6 @@ export const PostFlow = ({
},
[
token,
draftPostIri,
offChainProjectId,
retryCsrfRequest,
reactQueryClient,
Expand All @@ -182,6 +194,59 @@ export const PostFlow = ({
],
);

const onSubmit = useCallback(
async (data: PostFormSchemaType) => {
// Check if draft post has been updated in the meantime
if (draftPostId && initialValues?.updatedAt) {
const modalLabel = data.published
? PUBLISH_SUBMIT_LABEL
: DRAFT_SUBMIT_LABEL;
try {
const resp = await fetch(
`${apiUri}/marketplace/v1/posts/by-id/${draftPostId}`,
{
method: 'GET',
credentials: 'include',
},
);
if (resp.status !== 200) {
if (resp.status === 404) {
// We set iri to undefined to re-create the post
setEditedData({ ...data, iri: undefined });
setDraftDeletedModalLabel(modalLabel);
return;
}
throw new Error(
_(msg`Cannot get existing post: ${resp.statusText}`),
);
}
const existingPost: { iri: string; updatedAt: string } =
await resp.json();
if (
new Date(existingPost.updatedAt).getTime() !==
initialValues?.updatedAt.getTime()
) {
// We need to overwrite iri in case it has changed
setEditedData({ ...data, iri: existingPost.iri });
setDraftEditedModalLabel(modalLabel);
return;
}
} catch (e) {
setErrorBannerTextAtom(String(e));
return;
}
}
await saveDataPost(data);
},
[
saveDataPost,
setErrorBannerTextAtom,
draftPostId,
initialValues?.updatedAt,
_,
],
);

const fetchMsgAnchor = useFetchMsgAnchor({
projectSlug,
projectId,
Expand All @@ -192,6 +257,7 @@ export const PostFlow = ({

const hasAddress =
!!wallet?.address && activeAccount?.addr === wallet.address;

useEffect(() => {
if (iri && createdPostData && !isFetching) {
setIsFormModalOpen(false);
Expand Down Expand Up @@ -323,6 +389,30 @@ export const PostFlow = ({
bodyText={_(DISCARD_CHANGES_BODY)}
buttonText={_(DISCARD_CHANGES_BUTTON)}
/>
{editedData && draftEditedModalLabel && (
<EditedDraftModal
open={!!draftEditedModalLabel}
shouldSaveDraft={draftEditedModalLabel === DRAFT_SUBMIT_LABEL}
onCancel={() => setDraftEditedModalLabel(undefined)}
onSubmit={async () => {
setDraftEditedModalLabel(undefined);
await saveDataPost(editedData);
}}
onClose={() => setDraftEditedModalLabel(undefined)}
/>
)}
{editedData && draftDeletedModalLabel && (
<DeletedDraftModal
open={!!draftDeletedModalLabel}
shouldSaveDraft={draftDeletedModalLabel === DRAFT_SUBMIT_LABEL}
onCancel={() => setDraftDeletedModalLabel(undefined)}
onSubmit={async () => {
setDraftDeletedModalLabel(undefined);
await saveDataPost(editedData);
}}
onClose={() => setDraftDeletedModalLabel(undefined)}
/>
)}
</>
);
};
Loading
Loading