diff --git a/web-components/src/components/cards/PostCard/PostCard.stories.tsx b/web-components/src/components/cards/PostCard/PostCard.stories.tsx index 2a93d2ab4c..2324150270 100644 --- a/web-components/src/components/cards/PostCard/PostCard.stories.tsx +++ b/web-components/src/components/cards/PostCard/PostCard.stories.tsx @@ -14,7 +14,7 @@ export const Public: Story = { args: { ...commonArgs, file, - isAdmin: false, + canManagePost: false, }, argTypes: { sharePublicLink: { action: 'share public click' }, @@ -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' }, @@ -42,7 +42,7 @@ export const NoImage: Story = { args: { ...commonArgs, privacyLabel: 'Files are private', - isAdmin: false, + canManagePost: false, }, argTypes: { sharePublicLink: { action: 'share public click' }, @@ -54,7 +54,7 @@ export const NoImage: Story = { export const Draft: Story = { args: { ...commonArgs, - isAdmin: true, + canManagePost: true, draftLabel: 'Draft', }, argTypes: { @@ -70,7 +70,7 @@ export const DraftPrivate: Story = { ...commonArgs, privacyLabel: 'Post is private', numberOfFiles: 5, - isAdmin: true, + canManagePost: true, draftLabel: 'Draft', file, }, diff --git a/web-components/src/components/cards/PostCard/PostCard.tsx b/web-components/src/components/cards/PostCard/PostCard.tsx index 63d9cedc71..b22a658db5 100644 --- a/web-components/src/components/cards/PostCard/PostCard.tsx +++ b/web-components/src/components/cards/PostCard/PostCard.tsx @@ -25,7 +25,7 @@ interface PostCardProps { author: User; signers?: Array; privacyLabel?: string; - isAdmin?: boolean; + canManagePost?: boolean; numberOfFiles?: number; sharePublicLink: (ev: React.MouseEvent) => void; sharePrivateLink: (ev: React.MouseEvent) => void; @@ -47,7 +47,7 @@ export default function PostCard({ author, signers, privacyLabel, - isAdmin, + canManagePost, numberOfFiles, sharePublicLink, sharePrivateLink, @@ -71,7 +71,7 @@ export default function PostCard({ > { return (
- {isAdmin ? ( + {canManagePost ? ( void; + onSubmit: () => void; +} & RegenModalProps; + +export const EditedDraftModal = ({ + onCancel, + onSubmit, + open, + onClose, +}: EditedDraftModalProps) => { + const { _ } = useLingui(); + return ( + + + <Trans> + Someone made changes to this draft while you were editing. + </Trans> + + + You will overwrite their changes if you continue. + + + + ); +}; diff --git a/web-marketplace/src/components/organisms/PostFlow/PostFlow.tsx b/web-marketplace/src/components/organisms/PostFlow/PostFlow.tsx index 0f671f04f0..8c23403687 100644 --- a/web-marketplace/src/components/organisms/PostFlow/PostFlow.tsx +++ b/web-marketplace/src/components/organisms/PostFlow/PostFlow.tsx @@ -1,4 +1,5 @@ import { useCallback, useEffect, useRef, useState } from 'react'; +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'; @@ -43,6 +44,7 @@ import { DRAFT_CREATED, DRAFT_SAVED, } from './PostFlow.constants'; +import { EditedDraftModal } from './PostFlow.EditedDraftModal'; import { SignModal } from './PostFlow.SignModal'; type Props = { @@ -82,6 +84,10 @@ export const PostFlow = ({ const { wallet } = useWallet(); const { activeAccount } = useAuth(); const [isFormModalOpen, setIsFormModalOpen] = useState(true); + const [isDraftEditedModalOpen, setIsDraftEditedModalOpen] = useState(false); + const [editedData, setEditedData] = useState( + undefined, + ); const [iri, setIri] = useState(); const { data: createdPostData, isFetching } = useQuery( getPostQuery({ @@ -104,8 +110,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 @@ -126,9 +133,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, @@ -168,7 +175,6 @@ export const PostFlow = ({ }, [ token, - draftPostIri, offChainProjectId, retryCsrfRequest, reactQueryClient, @@ -177,6 +183,50 @@ export const PostFlow = ({ ], ); + const onSubmit = useCallback( + async (data: PostFormSchemaType) => { + // Check if draft post has been updated in the meantime + if (draftPostId && initialValues?.updatedAt) { + try { + const resp = await fetch( + `${apiUri}/marketplace/v1/posts/by-id/${draftPostId}`, + { + method: 'GET', + credentials: 'include', + }, + ); + if (resp.status !== 200) { + 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 }); + setIsDraftEditedModalOpen(true); + return; + } + } catch (e) { + setErrorBannerTextAtom(String(e)); + return; + } + } + await saveDataPost(data); + }, + [ + saveDataPost, + setErrorBannerTextAtom, + draftPostId, + initialValues?.updatedAt, + _, + ], + ); + const fetchMsgAnchor = useFetchMsgAnchor({ projectSlug, projectId, @@ -187,6 +237,7 @@ export const PostFlow = ({ const hasAddress = !!wallet?.address && activeAccount?.addr === wallet.address; + useEffect(() => { if (iri && createdPostData && !isFetching) { setIsFormModalOpen(false); @@ -311,6 +362,17 @@ export const PostFlow = ({ bodyText={_(DISCARD_CHANGES_BODY)} buttonText={_(DISCARD_CHANGES_BUTTON)} /> + {editedData && ( + setIsDraftEditedModalOpen(false)} + onSubmit={async () => { + setIsDraftEditedModalOpen(false); + await saveDataPost(editedData); + }} + onClose={() => setIsDraftEditedModalOpen(false)} + /> + )} ); }; diff --git a/web-marketplace/src/components/organisms/PostForm/PostForm.schema.tsx b/web-marketplace/src/components/organisms/PostForm/PostForm.schema.tsx index c1efffa0ba..0a612e712d 100644 --- a/web-marketplace/src/components/organisms/PostForm/PostForm.schema.tsx +++ b/web-marketplace/src/components/organisms/PostForm/PostForm.schema.tsx @@ -11,6 +11,7 @@ type PostFormSchemaParams = { export const getPostFormSchema = ({ requiredMessage }: PostFormSchemaParams) => z.object({ + id: z.string().optional(), iri: z.string().optional(), title: z.string().max(POST_MAX_TITLE_LENGTH).min(1), comment: z.string().min(1), @@ -18,6 +19,7 @@ export const getPostFormSchema = ({ requiredMessage }: PostFormSchemaParams) => privacyType: z.custom(val => !!val, requiredMessage), published: z.boolean(), disallowFileDownloads: z.boolean().optional(), + updatedAt: z.date().optional(), }); export type PostFormSchemaType = z.infer>; diff --git a/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.DataStream.Post.tsx b/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.DataStream.Post.tsx index 4a170568a7..27eb54ec1a 100644 --- a/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.DataStream.Post.tsx +++ b/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.DataStream.Post.tsx @@ -68,25 +68,27 @@ type Props = { post: Post; index: number; postsLength: number; - isAdmin: boolean; adminAccountId?: string | null; offChainProjectId?: string; adminAddr?: string | null; setDraftPost: UseStateSetter | undefined>; projectLocation: GeocodeFeature; openCreatePostModal: () => void; + canManagePost: boolean; + canViewPost: boolean; }; export const DataStreamPost = ({ offChainProjectId, post, index, postsLength, - isAdmin, adminAccountId, adminAddr, setDraftPost, projectLocation, openCreatePostModal, + canManagePost, + canViewPost, }: Props) => { const { _ } = useLingui(); const [selectedLanguage] = useAtom(selectedLanguageAtom); @@ -196,7 +198,7 @@ export const DataStreamPost = ({ - {post.contents && (post.privacy !== 'private' || isAdmin) && ( + {post.contents && (post.privacy !== 'private' || canViewPost) && ( @@ -224,7 +226,7 @@ export const DataStreamPost = ({ timestamp: post.createdAt, tag: creatorIsAdmin ? _(ADMIN) : undefined, }} - isAdmin={isAdmin} + canManagePost={canManagePost} sharePublicLink={() => { copyTextToClipboard( LINK_PREFIX @@ -241,6 +243,8 @@ export const DataStreamPost = ({ preview={preview} onEditDraft={() => { setDraftPost({ + id: post.id, + updatedAt: new Date(post.updatedAt), iri: post.iri, title: post.contents?.title, comment: post.contents?.comment, @@ -265,7 +269,7 @@ export const DataStreamPost = ({ linkComponent={Link} /> )} - {post.privacy === 'private' && !isAdmin && ( + {post.privacy === 'private' && !canViewPost && (
{_(PRIVATE_POST)} @@ -273,7 +277,7 @@ export const DataStreamPost = ({ )} - {isAdmin && ( + {canManagePost && ( void; setDraftPost: UseStateSetter | undefined>; + canManagePost: boolean; + canViewPost: boolean; }; export const DataStream = ({ @@ -59,17 +60,15 @@ export const DataStream = ({ projectLocation, openCreatePostModal, setDraftPost, + canManagePost, + canViewPost, }: Props) => { const { _ } = useLingui(); const [selectedLanguage] = useAtom(selectedLanguageAtom); - const { activeAccountId } = useAuth(); const [year, setYear] = useState(null); const [years, setYears] = useState>([]); const hash = useHash(); - const isAdmin = - !!adminAccountId && !!activeAccountId && adminAccountId === activeAccountId; - const queryClient = useQueryClient(); const { data, fetchNextPage, hasNextPage, isLoading } = useInfiniteQuery( getPostsQuery({ @@ -111,7 +110,7 @@ export const DataStream = ({ titleAlign="left" className="mb-50 sm:mb-[100px] pt-0" > - {isAdmin && adminDescription && projectLocation && ( + {canManagePost && adminDescription && projectLocation && (
@@ -158,13 +157,14 @@ export const DataStream = ({ post={post} index={i} postsLength={posts.length} - isAdmin={isAdmin} + canManagePost={canManagePost} adminAccountId={adminAccountId} offChainProjectId={offChainProjectId} adminAddr={adminAddr} setDraftPost={setDraftPost} projectLocation={projectLocation} openCreatePostModal={openCreatePostModal} + canViewPost={canViewPost} /> ))} diff --git a/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.tsx b/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.tsx index fd129564d6..bdf3ba9bf5 100644 --- a/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.tsx +++ b/web-marketplace/src/components/templates/ProjectDetails/ProjectDetails.tsx @@ -51,8 +51,9 @@ import { ProjectStorySection } from 'components/organisms/ProjectStorySection/Pr import { SellOrdersActionsBar } from 'components/organisms/SellOrdersActionsBar/SellOrdersActionsBar'; import { AVG_PRICE_TOOLTIP_PROJECT } from 'components/organisms/SellOrdersActionsBar/SellOrdersActionsBar.constants'; import { - getCanCreatePost, getCanEditProject, + getCanManagePost, + getCanViewPost, } from 'components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils'; import { useFetchPaginatedBatches } from 'hooks/batches/useFetchPaginatedBatches'; import { useOnBuyButtonClick } from 'hooks/useOnBuyButtonClick'; @@ -336,7 +337,8 @@ function ProjectDetails(): JSX.Element { const { canEdit: canEditProject } = getCanEditProject({ role, }); - const { canCreatePost } = getCanCreatePost({ role }); + const canManagePost = getCanManagePost({ role }); + const canViewPost = getCanViewPost({ role }); // Fetch organization data if project belongs to an organization const organizationId = @@ -384,7 +386,7 @@ function ProjectDetails(): JSX.Element { isCommunityCredit={isCommunityCredit} onBookCallButtonClick={onBookCallButtonClick} canEditProject={canEditProject} - canCreatePost={canCreatePost} + canCreatePost={canManagePost} onBuyButtonClick={() => { onBuyButtonClick({ projectId, @@ -514,6 +516,8 @@ function ProjectDetails(): JSX.Element { projectLocation={projectLocation} openCreatePostModal={openCreatePostModal} setDraftPost={setDraftPost} + canManagePost={canManagePost} + canViewPost={canViewPost} /> } - {onChainOrOffChainProjectId && admin && ( + {/* {onChainOrOffChainProjectId && admin && ( - )} + )} */} {gettingStartedResourcesSection && IS_REGEN && (
diff --git a/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.test.ts b/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.test.ts index bc680d14ea..23c5eca8ca 100644 --- a/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.test.ts +++ b/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.test.ts @@ -8,44 +8,44 @@ import { ROLE_VIEWER, } from 'components/organisms/ActionDropdown/ActionDropdown.constants'; -import { getCanCreatePost } from './ProjectFormAccessTemplate.utils'; +import { getCanManagePost } from './ProjectFormAccessTemplate.utils'; describe('ProjectFormAccessTemplate.utils', () => { - describe('getCanCreatePostWithRole', () => { + describe('getCanManagePostWithRole', () => { it('should allow creating posts for owner role', () => { - const result = getCanCreatePost({ role: ROLE_OWNER }); + const result = getCanManagePost({ role: ROLE_OWNER }); - expect(result.canCreatePost).toBe(true); + expect(result).toBe(true); }); it('should allow creating posts for admin role', () => { - const result = getCanCreatePost({ role: ROLE_ADMIN }); + const result = getCanManagePost({ role: ROLE_ADMIN }); - expect(result.canCreatePost).toBe(true); + expect(result).toBe(true); }); it('should allow creating posts for editor role', () => { - const result = getCanCreatePost({ role: ROLE_EDITOR }); + const result = getCanManagePost({ role: ROLE_EDITOR }); - expect(result.canCreatePost).toBe(true); + expect(result).toBe(true); }); it('should allow creating posts for author role', () => { - const result = getCanCreatePost({ role: ROLE_AUTHOR }); + const result = getCanManagePost({ role: ROLE_AUTHOR }); - expect(result.canCreatePost).toBe(true); + expect(result).toBe(true); }); it('should not allow creating posts for viewer role', () => { - const result = getCanCreatePost({ role: ROLE_VIEWER }); + const result = getCanManagePost({ role: ROLE_VIEWER }); - expect(result.canCreatePost).toBe(false); + expect(result).toBe(false); }); it('should not allow creating posts when role is undefined', () => { - const result = getCanCreatePost({ role: undefined }); + const result = getCanManagePost({ role: undefined }); - expect(result.canCreatePost).toBe(false); + expect(result).toBe(false); }); }); }); diff --git a/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.ts b/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.ts index e6e77e7247..aa2b7d3619 100644 --- a/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.ts +++ b/web-marketplace/src/components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils.ts @@ -3,6 +3,7 @@ import { ROLE_AUTHOR, ROLE_EDITOR, ROLE_OWNER, + ROLE_VIEWER, } from 'components/organisms/ActionDropdown/ActionDropdown.constants'; import { ProjectRole } from 'components/organisms/BaseMembersTable/BaseMembersTable.types'; @@ -16,16 +17,25 @@ export const getCanEditProject = ({ role }: GetCanEditProjectParams) => { }; }; -type GetCanCreatePostParams = { +type GetCanManagePostParams = { role?: ProjectRole; }; -export const getCanCreatePost = ({ role }: GetCanCreatePostParams) => { - return { - canCreatePost: - role === ROLE_OWNER || - role === ROLE_ADMIN || - role === ROLE_EDITOR || - role === ROLE_AUTHOR, - }; +export const getCanManagePost = ({ role }: GetCanManagePostParams) => { + return ( + role === ROLE_OWNER || + role === ROLE_ADMIN || + role === ROLE_EDITOR || + role === ROLE_AUTHOR + ); +}; + +export const getCanViewPost = ({ role }: GetCanManagePostParams) => { + return ( + role === ROLE_OWNER || + role === ROLE_ADMIN || + role === ROLE_EDITOR || + role === ROLE_AUTHOR || + role === ROLE_VIEWER + ); }; diff --git a/web-marketplace/src/legacy-pages/Dashboard/MyProjects/ManageProject.tsx b/web-marketplace/src/legacy-pages/Dashboard/MyProjects/ManageProject.tsx index 7cd910c40d..b320058678 100644 --- a/web-marketplace/src/legacy-pages/Dashboard/MyProjects/ManageProject.tsx +++ b/web-marketplace/src/legacy-pages/Dashboard/MyProjects/ManageProject.tsx @@ -19,8 +19,8 @@ import { ROLE_AUTHOR } from 'components/organisms/ActionDropdown/ActionDropdown. import { PostFlow } from 'components/organisms/PostFlow/PostFlow'; import ProjectDashboardBanner from 'components/organisms/ProjectDashboardBanner/ProjectDashboardBanner'; import { - getCanCreatePost, getCanEditProject, + getCanManagePost, } from 'components/templates/ProjectFormTemplate/ProjectFormAccessTemplate.utils'; import { useCanAccessManageProjectWithRole } from './hooks/useCanAccessManageProjectWithRole'; @@ -95,7 +95,7 @@ const ManageProject = () => { const { canEdit: canEditProject } = getCanEditProject({ role, }); - const { canCreatePost } = getCanCreatePost({ role }); + const canManagePost = getCanManagePost({ role }); if (isLoading) return ; @@ -107,7 +107,7 @@ const ManageProject = () => { { setPostProjectId(project.id); setPostOffChainProjectId(project.offChainId); @@ -139,7 +139,7 @@ const ManageProject = () => { {/* Content section */} - {canCreatePost && postProjectId && ( + {canManagePost && postProjectId && ( { setPostProjectId(undefined); diff --git a/web-marketplace/src/lib/i18n/locales/en.po b/web-marketplace/src/lib/i18n/locales/en.po index 8f3abdb1c5..e8709ef023 100644 --- a/web-marketplace/src/lib/i18n/locales/en.po +++ b/web-marketplace/src/lib/i18n/locales/en.po @@ -426,7 +426,7 @@ msgstr "" #. placeholder {0}: selectedProjectsWithAddresses[idx].offChainId #. placeholder {1}: result.reason -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:266 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:272 msgid "Adding member to project {0} failed: {1}" msgstr "" @@ -1069,6 +1069,11 @@ msgstr "" msgid "Cancelled credits have been removed from from the credit batch's tradable supply. Cancelling credits is permanent and implies the credits have been moved to another chain or registry." msgstr "" +#. placeholder {0}: resp.statusText +#: src/components/organisms/PostFlow/PostFlow.tsx:200 +msgid "Cannot get existing post: {0}" +msgstr "" + #: src/components/organisms/MediaForm/hooks/useHandleUpload.ts:57 msgid "Cannot upload file without a project id" msgstr "" @@ -1275,7 +1280,7 @@ msgid "Close project creation" msgstr "" #: src/components/organisms/RegistryLayout/RegistryLayout.constants.ts:4 -#: src/features/ecocredit/BridgeFlow/BridgeFlow.tsx:220 +#: src/features/ecocredit/BridgeFlow/BridgeFlow.tsx:221 #: src/lib/constants/shared.constants.tsx:96 msgid "CLOSE WINDOW" msgstr "" @@ -1445,7 +1450,7 @@ msgstr "" msgid "Copy link to project page" msgstr "" -#: src/legacy-pages/CreateOrganization/hooks/useCreateDao/useCreateDao.ts:308 +#: src/legacy-pages/CreateOrganization/hooks/useCreateDao/useCreateDao.ts:313 msgid "Could not find the organization associated with the created DAO. Please try refreshing the page later." msgstr "" @@ -1572,7 +1577,7 @@ msgstr "" #: src/components/organisms/CreditBatches/CreditBatches.tsx:220 #: src/components/organisms/CreditBatchesSection/CreditBatchesSection.tsx:24 -#: src/legacy-pages/Profile/Profile.tsx:130 +#: src/legacy-pages/Profile/Profile.tsx:133 msgid "Credit Batches" msgstr "" @@ -1647,7 +1652,7 @@ msgstr "" #: src/components/layout/Layout.Footer.tsx:33 #: src/legacy-pages/Home/Home.tsx:182 -#: src/legacy-pages/Profile/Profile.tsx:124 +#: src/legacy-pages/Profile/Profile.tsx:127 msgid "Credit Classes" msgstr "" @@ -2991,11 +2996,11 @@ msgstr "" msgid "Make the location data private" msgstr "" -#: src/legacy-pages/Profile/Profile.tsx:182 +#: src/legacy-pages/Profile/Profile.tsx:185 msgid "Manage Credit Batches" msgstr "" -#: src/legacy-pages/Profile/Profile.tsx:177 +#: src/legacy-pages/Profile/Profile.tsx:180 msgid "Manage Credit Classes" msgstr "" @@ -3007,7 +3012,7 @@ msgstr "" msgid "Manage Credits" msgstr "" -#: src/legacy-pages/Profile/Profile.tsx:172 +#: src/legacy-pages/Profile/Profile.tsx:175 msgid "Manage Members" msgstr "" @@ -3015,7 +3020,7 @@ msgstr "" msgid "Manage organization" msgstr "" -#: src/legacy-pages/Profile/Profile.tsx:162 +#: src/legacy-pages/Profile/Profile.tsx:165 msgid "Manage Portfolio" msgstr "" @@ -3031,7 +3036,7 @@ msgstr "" msgid "Manage projects" msgstr "" -#: src/legacy-pages/Profile/Profile.tsx:167 +#: src/legacy-pages/Profile/Profile.tsx:170 msgid "Manage Projects" msgstr "" @@ -3039,7 +3044,7 @@ msgstr "" msgid "manage sell orders" msgstr "" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:26 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:24 msgid "Manage your Stripe account for fiat purchases" msgstr "" @@ -3102,7 +3107,7 @@ msgid "member not found" msgstr "" #: src/components/organisms/DashboardNavigation/DashboardNavigation.utils.tsx:113 -#: src/legacy-pages/Profile/Profile.tsx:118 +#: src/legacy-pages/Profile/Profile.tsx:121 msgid "Members" msgstr "" @@ -3579,6 +3584,10 @@ msgstr "" #~ msgid "Overview" #~ msgstr "" +#: src/components/organisms/PostFlow/PostFlow.EditedDraftModal.tsx:33 +msgid "overwrite & publish" +msgstr "" + #: src/components/organisms/OrganizationMembers/OrganizationMembers.constants.tsx:14 msgid "Owner" msgstr "" @@ -3774,7 +3783,7 @@ msgstr "" #: src/components/organisms/DashboardNavigation/DashboardNavigation.utils.tsx:45 #: src/legacy-pages/Dashboard/Dashboard.constants.tsx:18 -#: src/legacy-pages/Profile/Profile.tsx:104 +#: src/legacy-pages/Profile/Profile.tsx:107 msgid "Portfolio" msgstr "" @@ -4163,7 +4172,7 @@ msgstr "" #: src/components/organisms/ProjectCardsSection/ProjectCardsSection.tsx:81 #: src/components/organisms/RegistryLayout/RegistryLayout.config.tsx:35 #: src/legacy-pages/CreditClassDetails/CreditClassDetails.Projects.tsx:40 -#: src/legacy-pages/Profile/Profile.tsx:110 +#: src/legacy-pages/Profile/Profile.tsx:113 msgid "Projects" msgstr "" @@ -4183,7 +4192,7 @@ msgstr "" #~ msgid "Public profile" #~ msgstr "" -#: src/legacy-pages/Profile/Profile.tsx:272 +#: src/legacy-pages/Profile/Profile.tsx:281 msgid "public profile tabs" msgstr "" @@ -4693,7 +4702,7 @@ msgstr "" msgid "set up a Keplr wallet →" msgstr "" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:35 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:33 msgid "set up account" msgstr "" @@ -4805,6 +4814,10 @@ msgstr "" msgid "Sold Out" msgstr "" +#: src/components/organisms/PostFlow/PostFlow.EditedDraftModal.tsx:25 +msgid "Someone made changes to this draft while you were editing." +msgstr "" + #: src/legacy-pages/CreateOrganization/steps/OrganizationProfileStep.tsx:154 msgid "Something went wrong while creating the organization." msgstr "" @@ -5298,7 +5311,7 @@ msgstr "" msgid "Threat Category of Ecosystem" msgstr "" -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:199 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:205 msgid "Timed out waiting for project DAOs to be indexed." msgstr "" @@ -5328,7 +5341,7 @@ msgstr "" msgid "Token expired" msgstr "" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:49 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:47 msgid "tokenization" msgstr "" @@ -5514,13 +5527,13 @@ msgstr "" #. placeholder {0}: selectedCardSellOrders[idx].id #. placeholder {1}: result.reason -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:305 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:311 msgid "Updating Card Order {0} failed: {1}" msgstr "" #. placeholder {0}: selectedProjectsWithAddresses[idx].offChainId #. placeholder {1}: result.reason -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:224 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:230 msgid "Updating Offchain Project {0} failed: {1}" msgstr "" @@ -5762,7 +5775,7 @@ msgstr "" msgid "view transaction" msgstr "" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:31 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:29 msgid "view transactions" msgstr "" @@ -6157,6 +6170,10 @@ msgstr "" msgid "You will not be able to issue credits with this option unless you later register this project with a credit class." msgstr "" +#: src/components/organisms/PostFlow/PostFlow.EditedDraftModal.tsx:30 +msgid "You will overwrite their changes if you continue." +msgstr "" + #: src/legacy-pages/Dashboard/MyEcocredits/MyEcocredits.constants.ts:18 msgid "You will receive one ecocredit for every basket token you redeem. Oldest batches will be pulled first." msgstr "" diff --git a/web-marketplace/src/lib/i18n/locales/es.po b/web-marketplace/src/lib/i18n/locales/es.po index 13b7669896..4dc2353660 100644 --- a/web-marketplace/src/lib/i18n/locales/es.po +++ b/web-marketplace/src/lib/i18n/locales/es.po @@ -73,8 +73,8 @@ msgstr "(tú)" msgid "{0, plural, one {allowed credit class} other {allowed credit classes}}" msgstr "{0, plural, one {clase de crédito permitida} other {clases de crédito permitidas}}" -#. placeholder {0}: import { plural } from '@lingui/core/macro'; import { Trans } from '@lingui/react/macro'; import ContainedButton from 'web-components/src/components/buttons/ContainedButton'; import Modal, { RegenModalProps } from 'web-components/src/components/modal'; import { Body, Title } from 'web-components/src/components/typography'; type OrganizationCreatedModalProps = RegenModalProps & { numberOfMigratedProjects: number; }; export const OrganizationCreatedModal = ({ open, onClose, numberOfMigratedProjects, }: OrganizationCreatedModalProps) => ( <Trans>Organization has been created!</Trans> {numberOfMigratedProjects > 0 && ( {plural(numberOfMigratedProjects, { one: `${numberOfMigratedProjects} project`, other: `${numberOfMigratedProjects} projects`, })} , with all associated credits and sell orders,{' '} {plural(numberOfMigratedProjects, { one: `was`, other: `were`, })}{' '} migrated to your new organization account. )} Please note: this organization is represented on-chain by a DAO (Decentralized Autonomous Organization). You can{' '} learn more about DAOs in our documentation , including how they work and the ways you can participate.
view org profile
); -#. placeholder {1}: import { plural } from '@lingui/core/macro'; import { Trans } from '@lingui/react/macro'; import ContainedButton from 'web-components/src/components/buttons/ContainedButton'; import Modal, { RegenModalProps } from 'web-components/src/components/modal'; import { Body, Title } from 'web-components/src/components/typography'; type OrganizationCreatedModalProps = RegenModalProps & { numberOfMigratedProjects: number; }; export const OrganizationCreatedModal = ({ open, onClose, numberOfMigratedProjects, }: OrganizationCreatedModalProps) => ( <Trans>Organization has been created!</Trans> {numberOfMigratedProjects > 0 && ( {plural(numberOfMigratedProjects, { one: `${numberOfMigratedProjects} project`, other: `${numberOfMigratedProjects} projects`, })} , with all associated credits and sell orders,{' '} {plural(numberOfMigratedProjects, { one: `was`, other: `were`, })}{' '} migrated to your new organization account. )} Please note: this organization is represented on-chain by a DAO (Decentralized Autonomous Organization). You can{' '} learn more about DAOs in our documentation , including how they work and the ways you can participate.
view org profile
); +#. placeholder {0}: import { plural } from '@lingui/core/macro'; import { Trans } from '@lingui/react/macro'; import ContainedButton from 'web-components/src/components/buttons/ContainedButton'; import Modal, { RegenModalProps } from 'web-components/src/components/modal'; import { Body, Title } from 'web-components/src/components/typography'; type OrganizationCreatedModalProps = RegenModalProps & { numberOfMigratedProjects: number; }; export const OrganizationCreatedModal = ({ open, onClose, numberOfMigratedProjects, }: OrganizationCreatedModalProps) => ( <Trans>Organization has been created!</Trans> {numberOfMigratedProjects > 0 && ( {plural(numberOfMigratedProjects, { one: `${numberOfMigratedProjects} project`, other: `${numberOfMigratedProjects} projects`, })} , with all associated credits and sell orders,{' '} {plural(numberOfMigratedProjects, { one: `was`, other: `were`, })}{' '} migrated to your new organization account. )} Please note: this organization is represented on-chain by a DAO (Decentralized Autonomous Organization). You can{' '} learn more about DAOs in our documentation , including how they work and the ways you can participate.
view org profile
); +#. placeholder {1}: import { plural } from '@lingui/core/macro'; import { Trans } from '@lingui/react/macro'; import ContainedButton from 'web-components/src/components/buttons/ContainedButton'; import Modal, { RegenModalProps } from 'web-components/src/components/modal'; import { Body, Title } from 'web-components/src/components/typography'; type OrganizationCreatedModalProps = RegenModalProps & { numberOfMigratedProjects: number; }; export const OrganizationCreatedModal = ({ open, onClose, numberOfMigratedProjects, }: OrganizationCreatedModalProps) => ( <Trans>Organization has been created!</Trans> {numberOfMigratedProjects > 0 && ( {plural(numberOfMigratedProjects, { one: `${numberOfMigratedProjects} project`, other: `${numberOfMigratedProjects} projects`, })} , with all associated credits and sell orders,{' '} {plural(numberOfMigratedProjects, { one: `was`, other: `were`, })}{' '} migrated to your new organization account. )} Please note: this organization is represented on-chain by a DAO (Decentralized Autonomous Organization). You can{' '} learn more about DAOs in our documentation , including how they work and the ways you can participate.
view org profile
); #: src/legacy-pages/Profile/Profile.OrganizationCreatedModal.tsx:22 msgid "{0}, with all associated credits and sell orders, {1} migrated to your new organization account." msgstr "{0}, con todos los créditos y órdenes de venta asociados, {1} migrados a su nueva cuenta de organización." @@ -432,7 +432,7 @@ msgstr "Añadir URL de vídeo" #. placeholder {0}: selectedProjectsWithAddresses[idx].offChainId #. placeholder {1}: result.reason -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:266 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:272 msgid "Adding member to project {0} failed: {1}" msgstr "Error al agregar miembro al proyecto {0}: {1}" @@ -1075,6 +1075,11 @@ msgstr "CANCELAR" msgid "Cancelled credits have been removed from from the credit batch's tradable supply. Cancelling credits is permanent and implies the credits have been moved to another chain or registry." msgstr "Los créditos cancelados se han eliminado del suministro comercializable del lote de créditos. La cancelación de créditos es permanente e implica que los créditos se han trasladado a otra cadena o registro." +#. placeholder {0}: resp.statusText +#: src/components/organisms/PostFlow/PostFlow.tsx:200 +msgid "Cannot get existing post: {0}" +msgstr "" + #: src/components/organisms/MediaForm/hooks/useHandleUpload.ts:57 msgid "Cannot upload file without a project id" msgstr "No se puede cargar un archivo sin un ID de proyecto" @@ -1281,7 +1286,7 @@ msgid "Close project creation" msgstr "Cerrar la creación del proyecto" #: src/components/organisms/RegistryLayout/RegistryLayout.constants.ts:4 -#: src/features/ecocredit/BridgeFlow/BridgeFlow.tsx:220 +#: src/features/ecocredit/BridgeFlow/BridgeFlow.tsx:221 #: src/lib/constants/shared.constants.tsx:96 msgid "CLOSE WINDOW" msgstr "CERRAR VENTANA" @@ -1451,7 +1456,7 @@ msgstr "Copiar enlace al perfil" msgid "Copy link to project page" msgstr "Copiar enlace a la página del proyecto" -#: src/legacy-pages/CreateOrganization/hooks/useCreateDao/useCreateDao.ts:308 +#: src/legacy-pages/CreateOrganization/hooks/useCreateDao/useCreateDao.ts:313 msgid "Could not find the organization associated with the created DAO. Please try refreshing the page later." msgstr "No se pudo encontrar la organización asociada con la DAO creada. Intente actualizar la página más tarde." @@ -1578,7 +1583,7 @@ msgstr "tabla de lotes de crédito" #: src/components/organisms/CreditBatches/CreditBatches.tsx:220 #: src/components/organisms/CreditBatchesSection/CreditBatchesSection.tsx:24 -#: src/legacy-pages/Profile/Profile.tsx:130 +#: src/legacy-pages/Profile/Profile.tsx:133 msgid "Credit Batches" msgstr "Lotes de crédito" @@ -1653,7 +1658,7 @@ msgstr "Clases de crédito" #: src/components/layout/Layout.Footer.tsx:33 #: src/legacy-pages/Home/Home.tsx:182 -#: src/legacy-pages/Profile/Profile.tsx:124 +#: src/legacy-pages/Profile/Profile.tsx:127 msgid "Credit Classes" msgstr "Clases de crédito" @@ -2999,11 +3004,11 @@ msgstr "Hacer que los archivos y los datos de ubicación sean privados" msgid "Make the location data private" msgstr "Hacer que los datos de ubicación sean privados" -#: src/legacy-pages/Profile/Profile.tsx:182 +#: src/legacy-pages/Profile/Profile.tsx:185 msgid "Manage Credit Batches" msgstr "Administrar lotes de crédito" -#: src/legacy-pages/Profile/Profile.tsx:177 +#: src/legacy-pages/Profile/Profile.tsx:180 msgid "Manage Credit Classes" msgstr "Administrar clases de crédito" @@ -3015,7 +3020,7 @@ msgstr "Administrar créditos" msgid "Manage Credits" msgstr "Administrar créditos" -#: src/legacy-pages/Profile/Profile.tsx:172 +#: src/legacy-pages/Profile/Profile.tsx:175 msgid "Manage Members" msgstr "Gestionar miembros" @@ -3023,7 +3028,7 @@ msgstr "Gestionar miembros" msgid "Manage organization" msgstr "Gestionar la organización" -#: src/legacy-pages/Profile/Profile.tsx:162 +#: src/legacy-pages/Profile/Profile.tsx:165 msgid "Manage Portfolio" msgstr "Administrar cartera" @@ -3039,7 +3044,7 @@ msgstr "administrar pestañas de proyectos" msgid "Manage projects" msgstr "Gestionar proyectos" -#: src/legacy-pages/Profile/Profile.tsx:167 +#: src/legacy-pages/Profile/Profile.tsx:170 msgid "Manage Projects" msgstr "Administrar proyectos" @@ -3047,7 +3052,7 @@ msgstr "Administrar proyectos" msgid "manage sell orders" msgstr "gestionar órdenes de venta" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:26 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:24 msgid "Manage your Stripe account for fiat purchases" msgstr "Administra tu cuenta de Stripe para compras con moneda fiduciaria" @@ -3110,7 +3115,7 @@ msgid "member not found" msgstr "miembro no encontrado" #: src/components/organisms/DashboardNavigation/DashboardNavigation.utils.tsx:113 -#: src/legacy-pages/Profile/Profile.tsx:118 +#: src/legacy-pages/Profile/Profile.tsx:121 msgid "Members" msgstr "Miembros" @@ -3587,6 +3592,10 @@ msgstr "Nuestros servicios" #~ msgid "Overview" #~ msgstr "Descripción general" +#: src/components/organisms/PostFlow/PostFlow.EditedDraftModal.tsx:33 +msgid "overwrite & publish" +msgstr "" + #: src/components/organisms/OrganizationMembers/OrganizationMembers.constants.tsx:14 msgid "Owner" msgstr "Dueño" @@ -3782,7 +3791,7 @@ msgstr "Por favor espere mientras se procesa la transacción" #: src/components/organisms/DashboardNavigation/DashboardNavigation.utils.tsx:45 #: src/legacy-pages/Dashboard/Dashboard.constants.tsx:18 -#: src/legacy-pages/Profile/Profile.tsx:104 +#: src/legacy-pages/Profile/Profile.tsx:107 msgid "Portfolio" msgstr "Cartera" @@ -4171,7 +4180,7 @@ msgstr "PROYECTADO:" #: src/components/organisms/ProjectCardsSection/ProjectCardsSection.tsx:81 #: src/components/organisms/RegistryLayout/RegistryLayout.config.tsx:35 #: src/legacy-pages/CreditClassDetails/CreditClassDetails.Projects.tsx:40 -#: src/legacy-pages/Profile/Profile.tsx:110 +#: src/legacy-pages/Profile/Profile.tsx:113 msgid "Projects" msgstr "Proyectos" @@ -4191,7 +4200,7 @@ msgstr "Proporcione información de contacto personal para esta organización." #~ msgid "Public profile" #~ msgstr "Perfil público" -#: src/legacy-pages/Profile/Profile.tsx:272 +#: src/legacy-pages/Profile/Profile.tsx:281 msgid "public profile tabs" msgstr "pestañas de perfil público" @@ -4701,7 +4710,7 @@ msgstr "Establecer créditos máximos" msgid "set up a Keplr wallet →" msgstr "Configurar una billetera Keplr →" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:35 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:33 msgid "set up account" msgstr "configurar cuenta" @@ -4813,6 +4822,10 @@ msgstr "Índice social y cultural" msgid "Sold Out" msgstr "Agotado" +#: src/components/organisms/PostFlow/PostFlow.EditedDraftModal.tsx:25 +msgid "Someone made changes to this draft while you were editing." +msgstr "" + #: src/legacy-pages/CreateOrganization/steps/OrganizationProfileStep.tsx:154 msgid "Something went wrong while creating the organization." msgstr "Algo salió mal al crear la organización." @@ -5306,7 +5319,7 @@ msgstr "Esta dirección de billetera ya está en uso en otra cuenta. ¿Quieres f msgid "Threat Category of Ecosystem" msgstr "Categoría de amenaza del ecosistema" -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:199 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:205 msgid "Timed out waiting for project DAOs to be indexed." msgstr "Se agotó el tiempo de espera para que se indexaran los DAO del proyecto." @@ -5336,7 +5349,7 @@ msgstr "Alternar opciones del proyecto" msgid "Token expired" msgstr "Token caducado" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:49 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:47 msgid "tokenization" msgstr "tokenización" @@ -5522,13 +5535,13 @@ msgstr "Actualizar metadatos del proyecto" #. placeholder {0}: selectedCardSellOrders[idx].id #. placeholder {1}: result.reason -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:305 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:311 msgid "Updating Card Order {0} failed: {1}" msgstr "Error al actualizar el pedido de la tarjeta {0}: {1}" #. placeholder {0}: selectedProjectsWithAddresses[idx].offChainId #. placeholder {1}: result.reason -#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:224 +#: src/legacy-pages/CreateOrganization/hooks/useMigrateProjects/useMigrateProjects.ts:230 msgid "Updating Offchain Project {0} failed: {1}" msgstr "Error al actualizar el proyecto fuera de la cadena {0}: {1}" @@ -5770,7 +5783,7 @@ msgstr "Ver la lista completa de videos de soporte»" msgid "view transaction" msgstr "ver transacción" -#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:31 +#: src/components/organisms/SellerSetupAccount/SellerSetupAccount.tsx:29 msgid "view transactions" msgstr "ver transacciones" @@ -6165,6 +6178,10 @@ msgstr "Cambió de cuenta en Keplr, por lo que su cuenta en Regen Marketplace ta msgid "You will not be able to issue credits with this option unless you later register this project with a credit class." msgstr "No podrás emitir créditos con esta opción a menos que posteriormente registres este proyecto con una clase de crédito." +#: src/components/organisms/PostFlow/PostFlow.EditedDraftModal.tsx:30 +msgid "You will overwrite their changes if you continue." +msgstr "" + #: src/legacy-pages/Dashboard/MyEcocredits/MyEcocredits.constants.ts:18 msgid "You will receive one ecocredit for every basket token you redeem. Oldest batches will be pulled first." msgstr "Recibirás un ecocrédito por cada ficha de cesta que canjees. Los lotes más antiguos se retirarán primero." diff --git a/web-marketplace/src/lib/queries/react-query/registry-server/getPostQuery/getPostQuery.types.ts b/web-marketplace/src/lib/queries/react-query/registry-server/getPostQuery/getPostQuery.types.ts index b4b297d697..e75facbe0c 100644 --- a/web-marketplace/src/lib/queries/react-query/registry-server/getPostQuery/getPostQuery.types.ts +++ b/web-marketplace/src/lib/queries/react-query/registry-server/getPostQuery/getPostQuery.types.ts @@ -22,6 +22,7 @@ export type PostContents = JsonLdDocument & { }; export type Post = { + id: string; iri: string; createdAt: string; creatorAccountId: string; @@ -43,6 +44,7 @@ export type Post = { prevIri?: string; nextIri?: string; canDownloadFiles: boolean; + updatedAt: string; }; export type ReactQueryGetPostQueryResponse = QueryObserverOptions;