diff --git a/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/EditResource.tsx b/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/EditResource.tsx index 9de92497..61023018 100644 --- a/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/EditResource.tsx +++ b/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/EditResource.tsx @@ -1,29 +1,40 @@ +import React from 'react'; +import { useParams } from 'next/navigation'; import { graphql } from '@/gql'; import { CreateFileResourceInput, + SchemaUpdateInput, UpdateFileResourceInput, } from '@/gql/generated/graphql'; -import { useMutation, useQuery } from '@tanstack/react-query'; -import { parseAsString, useQueryState } from 'next-usequerystate'; -import { useParams, useRouter } from 'next/navigation'; +import { IconTrash } from '@tabler/icons-react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { + parseAsBoolean, + parseAsString, + useQueryState, +} from 'next-usequerystate'; import { Button, + ButtonGroup, + Checkbox, Combobox, + DataTable, Dialog, Divider, DropZone, Icon, + IconButton, Select, + Spinner, Text, TextField, - toast + toast, } from 'opub-ui'; -import React from 'react'; -import { Icons } from '@/components/icons'; import { GraphQL } from '@/lib/api'; +import { Icons } from '@/components/icons'; import { createResourceFilesDoc } from './ResourceDropzone'; -import { ResourceSchema } from './ResourceSchema'; +import { ResourceSchema, updateSchema } from './ResourceSchema'; interface TListItem { label: string; @@ -50,18 +61,26 @@ export const EditResource = ({ reload, data }: any) => { `); const [resourceId, setResourceId] = useQueryState('id', parseAsString); + const [schema, setSchema] = React.useState([]); const { mutate, isLoading } = useMutation( - (data: { fileResourceInput: UpdateFileResourceInput }) => - GraphQL(updateResourceDoc, data), + (data: { + fileResourceInput: UpdateFileResourceInput; + isResetSchema: boolean; + }) => GraphQL(updateResourceDoc, data), { - onSuccess: () => { + onSuccess: (data, variables) => { toast('File changes saved', { action: { label: 'Dismiss', onClick: () => {}, }, }); + if (variables.isResetSchema) { + schemaMutation.mutate({ + resourceId: resourceId, + }); + } reload(); }, onError: (err: any) => { @@ -70,11 +89,35 @@ export const EditResource = ({ reload, data }: any) => { } ); - const { - data: payload, - refetch, - isLoading: isPending, - } = useQuery([`fetch_schema_${params.id}`], () => + const resetSchema: any = graphql(` + mutation resetFileResourceSchema($resourceId: UUID!) { + resetFileResourceSchema(resourceId: $resourceId) { + ... on TypeResource { + id + schema { + format + description + id + fieldName + } + } + } + } + `); + + const schemaMutation = useMutation( + (data: { resourceId: string }) => GraphQL(resetSchema, data), + { + onSuccess: () => { + schemaQuery.refetch(); + }, + onError: (err: any) => { + console.log('Error ::: ', err); + }, + } + ); + + const schemaQuery = useQuery([`fetch_schema_${params.id}`], () => GraphQL(fetchSchema, { datasetId: params.id }) ); @@ -92,6 +135,24 @@ export const EditResource = ({ reload, data }: any) => { } `); + const { mutate: modify } = useMutation( + (data: { input: SchemaUpdateInput }) => GraphQL(updateSchema, data), + { + onSuccess: () => { + schemaQuery.refetch(); + toast('Schema Updated Successfully', { + action: { + label: 'Dismiss', + onClick: () => {}, + }, + }); + }, + onError: (err: any) => { + console.log('Error ::: ', err); + }, + } + ); + const { mutate: transform } = useMutation( (data: { fileResourceInput: CreateFileResourceInput }) => GraphQL(createResourceFilesDoc, data), @@ -104,6 +165,7 @@ export const EditResource = ({ reload, data }: any) => { onClick: () => {}, }, }); + schemaQuery.refetch(); reload(); }, onError: (err: any) => { @@ -112,8 +174,6 @@ export const EditResource = ({ reload, data }: any) => { } ); - const router = useRouter(); - const ResourceList: TListItem[] = data.map((item: any) => ({ label: item.name, @@ -177,17 +237,20 @@ export const EditResource = ({ reload, data }: any) => { ); - const [resourceFile, setResourceFile] = React.useState(); const onDrop = React.useCallback( - (_dropFiles: File[], acceptedFiles: File[]) => - setResourceFile(acceptedFiles[0]), + (_dropFiles: File[], acceptedFiles: File[]) => { + mutate({ + fileResourceInput: { + id: resourceId, + file: acceptedFiles[0], + }, + isResetSchema: true, + }); + }, [] ); - - const fileInput = resourceFile ? ( -
{resourceFile.name}
- ) : ( + const fileInput = (
{getResourceObject(resourceId)?.fileDetails.file.name.replace( @@ -206,15 +269,23 @@ export const EditResource = ({ reload, data }: any) => { mutate({ fileResourceInput: { id: resourceId, - description: resourceDesc - ? resourceDesc - : getResourceObject(resourceId)?.description, - name: resourceName - ? resourceName - : getResourceObject(resourceId)?.label, - file: resourceFile, + description: resourceDesc || '', + name: resourceName || '', }, + isResetSchema: false, }); + if (schema.length > 0) { + const updatedScheme = schema.map((item) => { + const { fieldName, ...rest } = item as any; + return rest; + }); + modify({ + input: { + resource: resourceId, + updates: updatedScheme, + }, + }); + } }; return ( @@ -248,7 +319,7 @@ export const EditResource = ({ reload, data }: any) => { className=" w-1/5 justify-end" size="medium" kind="tertiary" - variant="basic" + variant="interactive" onClick={listViewFunction} >
@@ -356,7 +427,7 @@ export const EditResource = ({ reload, data }: any) => { /> { See Preview
*/} - {resourceId && payload && Object.keys(payload).length > 0 ? ( - item.id === resourceId - )[0]?.schema - } - /> - ) : null} +
+
+ Fields in the Resource + +
+ + The Field settings apply to the Resource on a master level and can not + be changed in Access Models. + + {schemaQuery.isLoading || schemaMutation.isLoading ? ( +
+ +
+ ) : resourceId && schemaQuery.data?.datasetResources?.filter( + (item: any) => item.id === resourceId ).length > 0 ? ( + item.id === resourceId)[0]?.schema} + /> + ) : ( +
Click on Reset Fields
+ )} +
); }; diff --git a/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/ResourceSchema.tsx b/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/ResourceSchema.tsx index 0bdcd4e3..132f7479 100644 --- a/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/ResourceSchema.tsx +++ b/app/[locale]/dashboard/organization/[organizationId]/dataset/[id]/edit/components/ResourceSchema.tsx @@ -1,46 +1,96 @@ import React from 'react'; import { useParams } from 'next/navigation'; import { graphql } from '@/gql'; +import { SchemaUpdateInput } from '@/gql/generated/graphql'; import { useMutation, useQuery } from '@tanstack/react-query'; -import { Button, DataTable, Icon, IconButton, Spinner, Text } from 'opub-ui'; +import { + Button, + DataTable, + Icon, + Select, + Spinner, + Text, + TextField, +} from 'opub-ui'; import { GraphQL } from '@/lib/api'; import { Icons } from '@/components/icons'; -export const ResourceSchema = ({ - resourceId, - isPending, - data, - refetch, -}: any) => { - - const resetSchema: any = graphql(` - mutation resetFileResourceSchema($resourceId: UUID!) { - resetFileResourceSchema(resourceId: $resourceId) { - ... on TypeResource { - id - schema { - format - description - id - fieldName - } - } +export const updateSchema: any = graphql(` + mutation updateSchema($input: SchemaUpdateInput!) { + updateSchema(input: $input) { + __typename + ... on TypeResource { + id } } - `); + } +`); - const { mutate, isLoading } = useMutation( - (data: { resourceId: string }) => GraphQL(resetSchema, data), - { - onSuccess: () => { - refetch(); - }, - onError: (err: any) => { - console.log('Error ::: ', err); - }, - } +const DescriptionCell = ({ + value, + rowIndex, + handleFieldChange, +}: { + value: string; + rowIndex: any; + handleFieldChange: any; +}) => { + const [description, setDescription] = React.useState(value || ''); + + const handleChange = (text: string) => { + setDescription(text); + handleFieldChange('description', text, rowIndex); + }; + + return ( + handleChange(e)} + /> ); +}; + +export const ResourceSchema = ({ setSchema, data }: any) => { + + const [updatedData, setUpdatedData] = React.useState(data); + + React.useEffect(() => { + if (data) { + setUpdatedData(data); + } + }, [data]); + + const handleFieldChange = ( + field: string, + newValue: string, + rowIndex: any + ) => { + setUpdatedData((prev: any) => { + const newData = [...prev]; + newData[rowIndex] = { + ...newData[rowIndex], + [field]: newValue, + }; + return newData; + }); + }; + + setSchema(updatedData); + const options = [ + { + label: 'Integer', + value: 'INTEGER', + }, + { + label: 'String', + value: 'STRING', + }, + ]; const generateColumnData = () => { return [ @@ -51,65 +101,58 @@ export const ResourceSchema = ({ { accessorKey: 'description', header: 'DESCRIPTION', + cell: (info: any) => { + const rowIndex = info.row.index; + const description = updatedData[rowIndex]?.description || ''; + return ( + + ); + }, }, { accessorKey: 'format', header: 'FORMAT', + cell: (info: any) => { + const rowIndex = info.row.index; + const format = updatedData[rowIndex]?.format || ''; + return ( +