From 657e07c6bc68315b4563996396e3fcd9f9166205 Mon Sep 17 00:00:00 2001 From: Joseph Chalabi Date: Tue, 7 Jan 2025 21:18:51 -0700 Subject: [PATCH] fix: update the group update modal --- components/groups/components/myGroups.tsx | 7 +- components/groups/modals/updateGroupModal.tsx | 534 ++++++++++-------- 2 files changed, 315 insertions(+), 226 deletions(-) diff --git a/components/groups/components/myGroups.tsx b/components/groups/components/myGroups.tsx index 5ec7d4b..302e59e 100644 --- a/components/groups/components/myGroups.tsx +++ b/components/groups/components/myGroups.tsx @@ -112,14 +112,9 @@ export function YourGroups({ return 'Untitled Group'.toLowerCase().includes(searchTerm.toLowerCase()); } }); - + console.log(groups); const totalPages = Math.ceil(filteredGroups.length / pageSize.groupInfo); - const paginatedGroups = filteredGroups.slice( - (currentPage - 1) * pageSize.groupInfo, - currentPage * pageSize.groupInfo - ); - const totalPagesGroupEntries = Math.ceil(filteredGroups.length / pageSize.groupEntries); const paginatedGroupEntries = filteredGroups.slice( (currentPage - 1) * pageSize.groupEntries, currentPage * pageSize.groupEntries diff --git a/components/groups/modals/updateGroupModal.tsx b/components/groups/modals/updateGroupModal.tsx index 6150137..daf7a01 100644 --- a/components/groups/modals/updateGroupModal.tsx +++ b/components/groups/modals/updateGroupModal.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Formik, Form } from 'formik'; +import { Formik, Form, useFormikContext } from 'formik'; import Yup from '@/utils/yupExtensions'; import { TextInput, TextArea, NumberInput } from '@/components/react/inputs'; @@ -13,6 +13,11 @@ import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; import env from '@/config/env'; import { createPortal } from 'react-dom'; +import { isValidManifestAddress } from '@/utils/string'; +import { TrashIcon, PlusIcon } from '@/components/icons'; +import { MdContacts } from 'react-icons/md'; +import { TailwindModal } from '@/components/react/modal'; + export function UpdateGroupModal({ group, policyAddress, @@ -40,7 +45,6 @@ export function UpdateGroupModal({ const maybeTitle = maybeMetadata?.title ?? ''; const maybeAuthors = maybeMetadata?.authors ?? ''; - const maybeSummary = maybeMetadata?.summary ?? ''; const maybeDetails = maybeMetadata?.details ?? ''; const maybePolicies = group?.policies?.[0]; @@ -54,9 +58,7 @@ export function UpdateGroupModal({ cosmos.group.v1.MessageComposer.withTypeUrl; const [name, setName] = useState(maybeTitle); - const [authors, setAuthors] = useState(maybeAuthors); - const [summary, setSummary] = useState(maybeSummary); - + const [authors, setAuthors] = useState(maybeAuthors ? [maybeAuthors] : []); const [description, setDescription] = useState(maybeDetails); const [threshold, setThreshold] = useState(maybeThreshold); const [votingPeriod, setVotingPeriod] = useState({ @@ -66,6 +68,9 @@ export function UpdateGroupModal({ seconds: 0, }); + const [isContactsOpen, setIsContactsOpen] = useState(false); + const [activeAuthorIndex, setActiveAuthorIndex] = useState(null); + // Initialize voting period state from existing data if available useEffect(() => { const initialVotingPeriodSeconds = maybeVotingPeriod ? Number(maybeVotingPeriod.seconds) : 0; @@ -101,15 +106,12 @@ export function UpdateGroupModal({ // Update Group Metadata if ( hasStateChanged(name, maybeTitle) || - hasStateChanged(authors, maybeAuthors) || - hasStateChanged(summary, maybeSummary) || + hasStateChanged(authors.join(','), maybeAuthors) || hasStateChanged(description, maybeDetails) ) { const newMetadata = JSON.stringify({ title: name, - authors: authors, - summary: summary, - + authors: authors.join(','), details: description, }); const msgGroupMetadata = updateGroupMetadata({ @@ -224,39 +226,28 @@ export function UpdateGroupModal({ .shape({ name: Yup.string() .max(50, 'Name must be at most 50 characters') - .noProfanity('Profanity is not allowed') - .when(['threshold', 'votingPeriod'], { - is: (threshold: number, votingPeriod: any) => { - // Convert both values to numbers for comparison - const hasThresholdChange = Number(threshold) !== Number(maybeThreshold); - const totalSeconds = - (Number(votingPeriod?.days) || 0) * 86400 + - (Number(votingPeriod?.hours) || 0) * 3600 + - (Number(votingPeriod?.minutes) || 0) * 60 + - (Number(votingPeriod?.seconds) || 0); - const originalSeconds = Number(maybeVotingPeriod?.seconds) || 0; - const hasVotingPeriodChange = totalSeconds !== originalSeconds; - - return hasThresholdChange || hasVotingPeriodChange; - }, - then: schema => schema.optional(), - otherwise: schema => - schema.when(['authors', 'summary', 'description'], { - is: (authors: string, summary: string, description: string) => - !authors && !summary && !description, - then: schema => schema.required('At least one metadata field is required'), - otherwise: schema => schema.optional(), - }), - }), - authors: Yup.string() - .noProfanity('Profanity is not allowed') - .max(50, 'Authors must not exceed 50 characters') - .optional(), + .noProfanity('Profanity is not allowed'), + authors: Yup.array() + .of( + Yup.string().test( + 'author-validation', + 'Invalid author name or address', + function (value) { + if (value?.startsWith('manifest')) { + return isValidManifestAddress(value); + } + return Yup.string() + .max(50, 'Author name must not exceed 50 characters') + .noProfanity('Profanity is not allowed') + .isValidSync(value); + } + ) + ) + .min(1, 'At least one author is required'), description: Yup.string() - .noProfanity('Profanity is not allowed') .min(20, 'Description must be at least 20 characters') - .max(100, 'Description must not exceed 100 characters') - .optional(), + .max(1000, 'Description must not exceed 1000 characters') + .noProfanity('Profanity is not allowed'), threshold: Yup.number().min(1, 'Threshold must be at least 1').optional(), votingPeriod: Yup.object() .shape({ @@ -329,209 +320,312 @@ export function UpdateGroupModal({ - e.stopPropagation()} > - {({ setFieldValue, values, isValid, dirty, errors, touched }) => ( - <> -
e.stopPropagation()} - > -
+
+ +
+ + {({ values, isValid }) => ( +
+
+ { + switch (field) { + case 'title': + setName(value); + break; + case 'authors': + setAuthors(value); + break; + case 'description': + setDescription(value); + break; + } + }} + address={address} + isContactsOpen={isContactsOpen} + setIsContactsOpen={setIsContactsOpen} + activeAuthorIndex={activeAuthorIndex} + setActiveAuthorIndex={setActiveAuthorIndex} + /> + + { + switch (field) { + case 'votingPeriod': + setVotingPeriod(value); + break; + case 'votingThreshold': + setThreshold(value.toString()); + break; + } + }} + /> +
+ + { + if (activeAuthorIndex !== null) { + const newAuthors = [...authors]; + newAuthors[activeAuthorIndex] = selectedAddress; + setAuthors(newAuthors); + } + }} + /> + +
+ -

Update Group

- - -
- ) => { - setName(e.target.value); - setFieldValue('name', e.target.value); - }} - maxLength={24} - /> - ) => { - setAuthors(e.target.value); - setFieldValue('authors', e.target.value); - }} - /> - ) => { - setSummary(e.target.value); - setFieldValue('summary', e.target.value); - }} - /> - -