From 12d9c12634f1931b0ae2f84940f175799ea3378e Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Tue, 31 Aug 2021 17:05:34 +0200 Subject: [PATCH 1/8] Add list and list item blocks --- .../api/project/models/project.settings.json | 4 +- backend/components/blocks/list-item.json | 13 ++ backend/components/project/list-block.json | 15 ++ backend/components/project/title-block.json | 13 -- .../features/project/blocks/ListBlock.tsx | 57 ++++++ .../features/project/blocks/ListItemBlock.tsx | 44 +++++ frontend/graphql.schema.json | 168 +++++++++++++++--- frontend/graphql/generated.ts | 69 ++++--- frontend/graphql/getProjects.graphql | 12 +- 9 files changed, 324 insertions(+), 71 deletions(-) create mode 100644 backend/components/blocks/list-item.json create mode 100644 backend/components/project/list-block.json delete mode 100644 backend/components/project/title-block.json create mode 100644 frontend/features/project/blocks/ListBlock.tsx create mode 100644 frontend/features/project/blocks/ListItemBlock.tsx diff --git a/backend/api/project/models/project.settings.json b/backend/api/project/models/project.settings.json index f76104e9..2697ae4c 100644 --- a/backend/api/project/models/project.settings.json +++ b/backend/api/project/models/project.settings.json @@ -51,10 +51,10 @@ "blocks": { "type": "dynamiczone", "components": [ - "project.title-block", "project.blockquote-block", "project.image-block", - "project.paragraph-block" + "project.paragraph-block", + "project.list-block" ], "pluginOptions": { "i18n": { diff --git a/backend/components/blocks/list-item.json b/backend/components/blocks/list-item.json new file mode 100644 index 00000000..524687d4 --- /dev/null +++ b/backend/components/blocks/list-item.json @@ -0,0 +1,13 @@ +{ + "collectionName": "components_blocks_list_items", + "info": { + "name": "listItem", + "icon": "ban" + }, + "options": {}, + "attributes": { + "text": { + "type": "string" + } + } +} diff --git a/backend/components/project/list-block.json b/backend/components/project/list-block.json new file mode 100644 index 00000000..a749d21f --- /dev/null +++ b/backend/components/project/list-block.json @@ -0,0 +1,15 @@ +{ + "collectionName": "components_project_list_blocks", + "info": { + "name": "listBlock", + "icon": "list-ul" + }, + "options": {}, + "attributes": { + "items": { + "type": "component", + "repeatable": true, + "component": "blocks.list-item" + } + } +} diff --git a/backend/components/project/title-block.json b/backend/components/project/title-block.json deleted file mode 100644 index 5b22e505..00000000 --- a/backend/components/project/title-block.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "collectionName": "components_project_title_blocks", - "info": { - "name": "titleBlock", - "icon": "angle-up" - }, - "options": {}, - "attributes": { - "title": { - "type": "string" - } - } -} diff --git a/frontend/features/project/blocks/ListBlock.tsx b/frontend/features/project/blocks/ListBlock.tsx new file mode 100644 index 00000000..c4306390 --- /dev/null +++ b/frontend/features/project/blocks/ListBlock.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { + Block, + BlockComponentProps, + BlocksControls, + InlineBlocks, +} from "react-tinacms-inline"; + +import { Box } from "@chakra-ui/react"; +import { listItemBlock } from "./ListItemBlock"; + +export type ListBlockData = BlockTemplateData< + "listBlock", + { + id: string; + items: { + text: Nullable[]; + }; + } +>; + +export default function ListBlock() { + return ( + + + + ); +} + +function BlockComponent({ index, data }: BlockComponentProps) { + return ( + + + + ); +} + +export const listBlock: Block = { + Component: BlockComponent, + template: { + label: "List block", + defaultItem: { + blocks: [], + }, + fields: [], + }, +}; diff --git a/frontend/features/project/blocks/ListItemBlock.tsx b/frontend/features/project/blocks/ListItemBlock.tsx new file mode 100644 index 00000000..a90f6cd1 --- /dev/null +++ b/frontend/features/project/blocks/ListItemBlock.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import { + Block, + BlockComponentProps, + BlocksControls, + InlineText, +} from "react-tinacms-inline"; + +import { Box } from "@chakra-ui/react"; + +export type ListItemBlockData = BlockTemplateData< + "listItemBlock", + { + id: string; + text: string; + } +>; + +export default function ListItemBlock() { + return ( + + + + ); +} + +function BlockComponent({ index, data }: BlockComponentProps) { + return ( + + + + ); +} + +export const listItemBlock: Block = { + Component: BlockComponent, + template: { + label: "List item block", + defaultItem: { + text: "Default item text", + }, + fields: [], + }, +}; diff --git a/frontend/graphql.schema.json b/frontend/graphql.schema.json index bf3d3757..a85f3704 100644 --- a/frontend/graphql.schema.json +++ b/frontend/graphql.schema.json @@ -289,6 +289,68 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "ComponentBlocksListItem", + "description": null, + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "text", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "ComponentBlocksListItemInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "text", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "ComponentBlocksNavigationBlock", @@ -871,7 +933,7 @@ }, { "kind": "OBJECT", - "name": "ComponentProjectParagraphBlock", + "name": "ComponentProjectListBlock", "description": null, "fields": [ { @@ -891,13 +953,17 @@ "deprecationReason": null }, { - "name": "text", + "name": "items", "description": null, "args": [], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ComponentBlocksListItem", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null @@ -910,17 +976,21 @@ }, { "kind": "INPUT_OBJECT", - "name": "ComponentProjectParagraphBlockInput", + "name": "ComponentProjectListBlockInput", "description": null, "fields": null, "inputFields": [ { - "name": "text", + "name": "items", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ComponentBlocksListItemInput", + "ofType": null + } }, "defaultValue": null, "isDeprecated": false, @@ -933,7 +1003,7 @@ }, { "kind": "OBJECT", - "name": "ComponentProjectTitleBlock", + "name": "ComponentProjectParagraphBlock", "description": null, "fields": [ { @@ -953,7 +1023,7 @@ "deprecationReason": null }, { - "name": "title", + "name": "text", "description": null, "args": [], "type": { @@ -972,12 +1042,12 @@ }, { "kind": "INPUT_OBJECT", - "name": "ComponentProjectTitleBlockInput", + "name": "ComponentProjectParagraphBlockInput", "description": null, "fields": null, "inputFields": [ { - "name": "title", + "name": "text", "description": null, "type": { "kind": "SCALAR", @@ -3516,6 +3586,11 @@ "name": "ComponentBlocksCard", "ofType": null }, + { + "kind": "OBJECT", + "name": "ComponentBlocksListItem", + "ofType": null + }, { "kind": "OBJECT", "name": "ComponentBlocksNavigationBlock", @@ -3548,12 +3623,12 @@ }, { "kind": "OBJECT", - "name": "ComponentProjectParagraphBlock", + "name": "ComponentProjectListBlock", "ofType": null }, { "kind": "OBJECT", - "name": "ComponentProjectTitleBlock", + "name": "ComponentProjectParagraphBlock", "ofType": null }, { @@ -5688,22 +5763,22 @@ "possibleTypes": [ { "kind": "OBJECT", - "name": "ComponentProjectTitleBlock", + "name": "ComponentProjectBlockquoteBlock", "ofType": null }, { "kind": "OBJECT", - "name": "ComponentProjectBlockquoteBlock", + "name": "ComponentProjectImageBlock", "ofType": null }, { "kind": "OBJECT", - "name": "ComponentProjectImageBlock", + "name": "ComponentProjectParagraphBlock", "ofType": null }, { "kind": "OBJECT", - "name": "ComponentProjectParagraphBlock", + "name": "ComponentProjectListBlock", "ofType": null } ] @@ -11795,6 +11870,41 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "editComponentBlocksListItemInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "text", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "editComponentBlocksNavigationBlockInput", @@ -12091,7 +12201,7 @@ }, { "kind": "INPUT_OBJECT", - "name": "editComponentProjectParagraphBlockInput", + "name": "editComponentProjectListBlockInput", "description": null, "fields": null, "inputFields": [ @@ -12108,12 +12218,16 @@ "deprecationReason": null }, { - "name": "text", + "name": "items", "description": null, "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "editComponentBlocksListItemInput", + "ofType": null + } }, "defaultValue": null, "isDeprecated": false, @@ -12126,7 +12240,7 @@ }, { "kind": "INPUT_OBJECT", - "name": "editComponentProjectTitleBlockInput", + "name": "editComponentProjectParagraphBlockInput", "description": null, "fields": null, "inputFields": [ @@ -12143,7 +12257,7 @@ "deprecationReason": null }, { - "name": "title", + "name": "text", "description": null, "type": { "kind": "SCALAR", diff --git a/frontend/graphql/generated.ts b/frontend/graphql/generated.ts index 9ec0faac..5619537e 100644 --- a/frontend/graphql/generated.ts +++ b/frontend/graphql/generated.ts @@ -53,6 +53,16 @@ export type ComponentBlocksCardInput = { label: Scalars['String']; }; +export type ComponentBlocksListItem = { + __typename?: 'ComponentBlocksListItem'; + id: Scalars['ID']; + text?: Maybe; +}; + +export type ComponentBlocksListItemInput = { + text?: Maybe; +}; + export type ComponentBlocksNavigationBlock = { __typename?: 'ComponentBlocksNavigationBlock'; id: Scalars['ID']; @@ -127,24 +137,24 @@ export type ComponentProjectImageBlockInput = { image?: Maybe; }; -export type ComponentProjectParagraphBlock = { - __typename?: 'ComponentProjectParagraphBlock'; +export type ComponentProjectListBlock = { + __typename?: 'ComponentProjectListBlock'; id: Scalars['ID']; - text?: Maybe; + items?: Maybe>>; }; -export type ComponentProjectParagraphBlockInput = { - text?: Maybe; +export type ComponentProjectListBlockInput = { + items?: Maybe>>; }; -export type ComponentProjectTitleBlock = { - __typename?: 'ComponentProjectTitleBlock'; +export type ComponentProjectParagraphBlock = { + __typename?: 'ComponentProjectParagraphBlock'; id: Scalars['ID']; - title?: Maybe; + text?: Maybe; }; -export type ComponentProjectTitleBlockInput = { - title?: Maybe; +export type ComponentProjectParagraphBlockInput = { + text?: Maybe; }; export type ComponentSectionCardSection = { @@ -378,7 +388,7 @@ export type MenuInput = { updated_by?: Maybe; }; -export type Morph = UsersPermissionsMe | UsersPermissionsMeRole | UsersPermissionsLoginPayload | UserPermissionsPasswordPayload | Global | UpdateGlobalPayload | DeleteGlobalPayload | Menu | MenuConnection | MenuAggregator | MenuGroupBy | MenuConnectionId | MenuConnectionCreated_At | MenuConnectionUpdated_At | MenuConnectionTitle | MenuConnectionPublished_At | CreateMenuPayload | UpdateMenuPayload | DeleteMenuPayload | Pages | PagesConnection | PagesAggregator | PagesGroupBy | PagesConnectionId | PagesConnectionCreated_At | PagesConnectionUpdated_At | PagesConnectionTitle | PagesConnectionPath | PagesConnectionLocale | PagesConnectionPublished_At | CreatePagePayload | UpdatePagePayload | DeletePagePayload | Project | ProjectConnection | ProjectAggregator | ProjectGroupBy | ProjectConnectionId | ProjectConnectionCreated_At | ProjectConnectionUpdated_At | ProjectConnectionProjectType | ProjectConnectionLinkPath | ProjectConnectionLinkLabel | ProjectConnectionDescription | ProjectConnectionPath | ProjectConnectionCompanyName | ProjectConnectionImage | ProjectConnectionLocale | ProjectConnectionPublished_At | CreateProjectPayload | UpdateProjectPayload | DeleteProjectPayload | I18NLocale | UploadFile | UploadFileConnection | UploadFileAggregator | UploadFileAggregatorSum | UploadFileAggregatorAvg | UploadFileAggregatorMin | UploadFileAggregatorMax | UploadFileGroupBy | UploadFileConnectionId | UploadFileConnectionCreated_At | UploadFileConnectionUpdated_At | UploadFileConnectionName | UploadFileConnectionAlternativeText | UploadFileConnectionCaption | UploadFileConnectionWidth | UploadFileConnectionHeight | UploadFileConnectionFormats | UploadFileConnectionHash | UploadFileConnectionExt | UploadFileConnectionMime | UploadFileConnectionSize | UploadFileConnectionUrl | UploadFileConnectionPreviewUrl | UploadFileConnectionProvider | UploadFileConnectionProvider_Metadata | DeleteFilePayload | UsersPermissionsPermission | UsersPermissionsRole | UsersPermissionsRoleConnection | UsersPermissionsRoleAggregator | UsersPermissionsRoleGroupBy | UsersPermissionsRoleConnectionId | UsersPermissionsRoleConnectionName | UsersPermissionsRoleConnectionDescription | UsersPermissionsRoleConnectionType | CreateRolePayload | UpdateRolePayload | DeleteRolePayload | UsersPermissionsUser | UsersPermissionsUserConnection | UsersPermissionsUserAggregator | UsersPermissionsUserGroupBy | UsersPermissionsUserConnectionId | UsersPermissionsUserConnectionCreated_At | UsersPermissionsUserConnectionUpdated_At | UsersPermissionsUserConnectionUsername | UsersPermissionsUserConnectionEmail | UsersPermissionsUserConnectionProvider | UsersPermissionsUserConnectionConfirmed | UsersPermissionsUserConnectionBlocked | UsersPermissionsUserConnectionRole | CreateUserPayload | UpdateUserPayload | DeleteUserPayload | ComponentBlocksCard | ComponentBlocksNavigationBlock | ComponentBlocksSingleFeature | ComponentGlobalTopbar | ComponentMenuPageLink | ComponentProjectBlockquoteBlock | ComponentProjectImageBlock | ComponentProjectParagraphBlock | ComponentProjectTitleBlock | ComponentSectionCardSection | ComponentSectionFooterSection | ComponentSectionHeroSection | ComponentSectionProjectsSection | ComponentSectionSimpleSection | ComponentSectionSingleFeatureSection; +export type Morph = UsersPermissionsMe | UsersPermissionsMeRole | UsersPermissionsLoginPayload | UserPermissionsPasswordPayload | Global | UpdateGlobalPayload | DeleteGlobalPayload | Menu | MenuConnection | MenuAggregator | MenuGroupBy | MenuConnectionId | MenuConnectionCreated_At | MenuConnectionUpdated_At | MenuConnectionTitle | MenuConnectionPublished_At | CreateMenuPayload | UpdateMenuPayload | DeleteMenuPayload | Pages | PagesConnection | PagesAggregator | PagesGroupBy | PagesConnectionId | PagesConnectionCreated_At | PagesConnectionUpdated_At | PagesConnectionTitle | PagesConnectionPath | PagesConnectionLocale | PagesConnectionPublished_At | CreatePagePayload | UpdatePagePayload | DeletePagePayload | Project | ProjectConnection | ProjectAggregator | ProjectGroupBy | ProjectConnectionId | ProjectConnectionCreated_At | ProjectConnectionUpdated_At | ProjectConnectionProjectType | ProjectConnectionLinkPath | ProjectConnectionLinkLabel | ProjectConnectionDescription | ProjectConnectionPath | ProjectConnectionCompanyName | ProjectConnectionImage | ProjectConnectionLocale | ProjectConnectionPublished_At | CreateProjectPayload | UpdateProjectPayload | DeleteProjectPayload | I18NLocale | UploadFile | UploadFileConnection | UploadFileAggregator | UploadFileAggregatorSum | UploadFileAggregatorAvg | UploadFileAggregatorMin | UploadFileAggregatorMax | UploadFileGroupBy | UploadFileConnectionId | UploadFileConnectionCreated_At | UploadFileConnectionUpdated_At | UploadFileConnectionName | UploadFileConnectionAlternativeText | UploadFileConnectionCaption | UploadFileConnectionWidth | UploadFileConnectionHeight | UploadFileConnectionFormats | UploadFileConnectionHash | UploadFileConnectionExt | UploadFileConnectionMime | UploadFileConnectionSize | UploadFileConnectionUrl | UploadFileConnectionPreviewUrl | UploadFileConnectionProvider | UploadFileConnectionProvider_Metadata | DeleteFilePayload | UsersPermissionsPermission | UsersPermissionsRole | UsersPermissionsRoleConnection | UsersPermissionsRoleAggregator | UsersPermissionsRoleGroupBy | UsersPermissionsRoleConnectionId | UsersPermissionsRoleConnectionName | UsersPermissionsRoleConnectionDescription | UsersPermissionsRoleConnectionType | CreateRolePayload | UpdateRolePayload | DeleteRolePayload | UsersPermissionsUser | UsersPermissionsUserConnection | UsersPermissionsUserAggregator | UsersPermissionsUserGroupBy | UsersPermissionsUserConnectionId | UsersPermissionsUserConnectionCreated_At | UsersPermissionsUserConnectionUpdated_At | UsersPermissionsUserConnectionUsername | UsersPermissionsUserConnectionEmail | UsersPermissionsUserConnectionProvider | UsersPermissionsUserConnectionConfirmed | UsersPermissionsUserConnectionBlocked | UsersPermissionsUserConnectionRole | CreateUserPayload | UpdateUserPayload | DeleteUserPayload | ComponentBlocksCard | ComponentBlocksListItem | ComponentBlocksNavigationBlock | ComponentBlocksSingleFeature | ComponentGlobalTopbar | ComponentMenuPageLink | ComponentProjectBlockquoteBlock | ComponentProjectImageBlock | ComponentProjectListBlock | ComponentProjectParagraphBlock | ComponentSectionCardSection | ComponentSectionFooterSection | ComponentSectionHeroSection | ComponentSectionProjectsSection | ComponentSectionSimpleSection | ComponentSectionSingleFeatureSection; export type Mutation = { __typename?: 'Mutation'; @@ -711,7 +721,7 @@ export type ProjectAggregator = { totalCount?: Maybe; }; -export type ProjectBlocksDynamicZone = ComponentProjectTitleBlock | ComponentProjectBlockquoteBlock | ComponentProjectImageBlock | ComponentProjectParagraphBlock; +export type ProjectBlocksDynamicZone = ComponentProjectBlockquoteBlock | ComponentProjectImageBlock | ComponentProjectParagraphBlock | ComponentProjectListBlock; export type ProjectConnection = { @@ -1549,6 +1559,11 @@ export type EditComponentBlocksCardInput = { label?: Maybe; }; +export type EditComponentBlocksListItemInput = { + id?: Maybe; + text?: Maybe; +}; + export type EditComponentBlocksNavigationBlockInput = { id?: Maybe; label?: Maybe; @@ -1586,14 +1601,14 @@ export type EditComponentProjectImageBlockInput = { image?: Maybe; }; -export type EditComponentProjectParagraphBlockInput = { +export type EditComponentProjectListBlockInput = { id?: Maybe; - text?: Maybe; + items?: Maybe>>; }; -export type EditComponentProjectTitleBlockInput = { +export type EditComponentProjectParagraphBlockInput = { id?: Maybe; - title?: Maybe; + text?: Maybe; }; export type EditComponentSectionCardSectionInput = { @@ -1893,9 +1908,6 @@ export type GetProjectsQuery = ( { __typename?: 'UploadFile' } & Pick )>, blocks?: Maybe - ) | ( { __typename: 'ComponentProjectBlockquoteBlock' } & Pick ) | ( @@ -1908,6 +1920,13 @@ export type GetProjectsQuery = ( ) | ( { __typename: 'ComponentProjectParagraphBlock' } & Pick + ) | ( + { __typename?: 'ComponentProjectListBlock' } + & Pick + & { items?: Maybe + )>>> } )>>> } )>>> } ); @@ -2095,11 +2114,6 @@ export const GetProjects = ` alternativeText } blocks { - ... on ComponentProjectTitleBlock { - __typename - id - title - } ... on ComponentProjectBlockquoteBlock { __typename id @@ -2119,6 +2133,13 @@ export const GetProjects = ` id text } + ... on ComponentProjectListBlock { + id + items { + id + text + } + } } } } diff --git a/frontend/graphql/getProjects.graphql b/frontend/graphql/getProjects.graphql index f2233276..71ff02ca 100644 --- a/frontend/graphql/getProjects.graphql +++ b/frontend/graphql/getProjects.graphql @@ -19,11 +19,6 @@ query getProjects($locale: String) { alternativeText } blocks { - ... on ComponentProjectTitleBlock { - __typename - id - title - } ... on ComponentProjectBlockquoteBlock { __typename id @@ -43,6 +38,13 @@ query getProjects($locale: String) { id text } + ... on ComponentProjectListBlock { + id + items { + id + text + } + } } } } From 0f283fb9b65080e26695de48251ee3cfac8956d8 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 16:26:30 +0200 Subject: [PATCH 2/8] Add single project handling. Needs blocks implementation --- .../mainNavigation/blocks/NavigationBlock.tsx | 4 +- frontend/graphql/generated.ts | 42 +- frontend/graphql/getProjects.graphql | 4 +- frontend/graphql/saveChanges.graphql | 1 + frontend/graphql/updateProject.graphql | 16 + frontend/pages/[[...slug]].tsx | 6 +- frontend/pages/projects/[...handle].tsx | 448 ++++++++++++++++++ frontend/pages/projects/index.tsx | 2 +- frontend/theme/index.ts | 8 + 9 files changed, 522 insertions(+), 9 deletions(-) create mode 100644 frontend/graphql/updateProject.graphql create mode 100644 frontend/pages/projects/[...handle].tsx diff --git a/frontend/features/mainNavigation/blocks/NavigationBlock.tsx b/frontend/features/mainNavigation/blocks/NavigationBlock.tsx index 76dbe4a3..f873c9ae 100644 --- a/frontend/features/mainNavigation/blocks/NavigationBlock.tsx +++ b/frontend/features/mainNavigation/blocks/NavigationBlock.tsx @@ -31,7 +31,6 @@ export function NavigationBlock({ url }: NavigationBlockProps) { px="2.5" py="3" letterSpacing="0.08em" - color="dark" position="relative" transition="all 0.3s" fontSize="sm" @@ -53,7 +52,8 @@ export function NavigationBlock({ url }: NavigationBlockProps) { opacity: "1", w: "full", }, - }}> + }} + > diff --git a/frontend/graphql/generated.ts b/frontend/graphql/generated.ts index 9ec0faac..f51955b0 100644 --- a/frontend/graphql/generated.ts +++ b/frontend/graphql/generated.ts @@ -1877,6 +1877,7 @@ export type GetGlobalQuery = ( ); export type GetProjectsQueryVariables = Exact<{ + where?: Maybe; locale?: Maybe; }>; @@ -1967,6 +1968,29 @@ export type UpdateMenuMutation = ( )> } ); +export type UpdateProjectMutationVariables = Exact<{ + projectInput?: Maybe; + menuInput?: Maybe; +}>; + + +export type UpdateProjectMutation = ( + { __typename?: 'Mutation' } + & { updateProject?: Maybe<( + { __typename?: 'updateProjectPayload' } + & { project?: Maybe<( + { __typename?: 'Project' } + & Pick + )> } + )>, updateMenu?: Maybe<( + { __typename?: 'updateMenuPayload' } + & { menu?: Maybe<( + { __typename?: 'Menu' } + & Pick + )> } + )> } +); + export const GetPages = ` query GetPages($where: JSON, $locale: String) { @@ -2074,8 +2098,8 @@ export const GetGlobal = ` } `; export const GetProjects = ` - query getProjects($locale: String) { - projects(locale: $locale) { + query getProjects($where: JSON, $locale: String) { + projects(where: $where, locale: $locale) { id linkPath linkLabel @@ -2153,5 +2177,19 @@ export const UpdateMenu = ` id } } +} + `; +export const UpdateProject = ` + mutation updateProject($projectInput: updateProjectInput, $menuInput: updateMenuInput) { + updateProject(input: $projectInput) { + project { + id + } + } + updateMenu(input: $menuInput) { + menu { + id + } + } } `; \ No newline at end of file diff --git a/frontend/graphql/getProjects.graphql b/frontend/graphql/getProjects.graphql index f2233276..f36193da 100644 --- a/frontend/graphql/getProjects.graphql +++ b/frontend/graphql/getProjects.graphql @@ -1,5 +1,5 @@ -query getProjects($locale: String) { - projects(locale: $locale) { +query getProjects($where: JSON, $locale: String) { + projects(where: $where, locale: $locale) { id linkPath linkLabel diff --git a/frontend/graphql/saveChanges.graphql b/frontend/graphql/saveChanges.graphql index 979a29ce..67dca359 100644 --- a/frontend/graphql/saveChanges.graphql +++ b/frontend/graphql/saveChanges.graphql @@ -4,6 +4,7 @@ mutation saveChanges($pageInput: updatePageInput, $menuInput: updateMenuInput) { id } } + updateMenu(input: $menuInput) { menu { id diff --git a/frontend/graphql/updateProject.graphql b/frontend/graphql/updateProject.graphql new file mode 100644 index 00000000..d93f9667 --- /dev/null +++ b/frontend/graphql/updateProject.graphql @@ -0,0 +1,16 @@ +mutation updateProject( + $projectInput: updateProjectInput + $menuInput: updateMenuInput +) { + updateProject(input: $projectInput) { + project { + id + } + } + + updateMenu(input: $menuInput) { + menu { + id + } + } +} diff --git a/frontend/pages/[[...slug]].tsx b/frontend/pages/[[...slug]].tsx index c424df7d..6cfa93c7 100644 --- a/frontend/pages/[[...slug]].tsx +++ b/frontend/pages/[[...slug]].tsx @@ -58,6 +58,8 @@ const StyledInlineBlocks = chakra(InlineBlocks); export default function DynamicPage({ data: data, preview }: DynamicPageProps) { const { colorMode } = useColorMode(); + console.log("data slug", data); + const itemProps = React.useMemo(() => { return { isPreview: preview, @@ -156,7 +158,7 @@ export const getStaticPaths: GetStaticPaths = async (context) => { return { paths, fallback: true }; }; -function wrap(value: T | T[]): T[] { +export function wrap(value: T | T[]): T[] { if (Array.isArray(value)) { return value; } @@ -391,7 +393,7 @@ function getPageData( path: page.path ? page.path : undefined, localizations: page.localizations ? filterListNullableItems( - page.localizations?.map((localization) => { + page.localizations.map((localization) => { return { id: localization?.id, locale: localization?.locale, diff --git a/frontend/pages/projects/[...handle].tsx b/frontend/pages/projects/[...handle].tsx new file mode 100644 index 00000000..1b401176 --- /dev/null +++ b/frontend/pages/projects/[...handle].tsx @@ -0,0 +1,448 @@ +import { Box, Img, Text } from "@chakra-ui/react"; +import { + LocaleMenu, + LocaleMenuButton, + LocaleMenuList, + LocaleMenuLink, +} from "@components/LocaleMenu"; +import { MobileNavDrawer } from "@components/MobileNavDrawer"; +import { WordmarkLogo } from "@components/WordmarkLogo"; +import { + NavBar, + NavMenuMobile, + NavMenuDesktop, +} from "@features/mainNavigation"; +import { + GetGlobal, + GetGlobalQuery, + GetGlobalQueryVariables, + GetProjects, + GetProjectsQuery, + GetProjectsQueryVariables, + UpdateMenuInput, + UpdateProject, + UpdateProjectInput, +} from "@graphql/generated"; +import { fetchGraphQL } from "@graphql/utils"; +import { SiteLayout } from "@layouts/siteLayout"; +import { + GlobalData, + LocalizationsData, + MenuData, +} from "@plugins/usePagePlugin"; +import { filterListNullableItems } from "@utils"; +import { GetStaticPaths, GetStaticProps } from "next"; +import { useRouter } from "next/router"; +import { wrap } from "pages/[[...slug]]"; +import React from "react"; +import { InlineForm, InlineText } from "react-tinacms-inline"; +import { useCMS, useForm, usePlugin } from "tinacms"; +import { FormOptions } from "tinacms"; +import { Form } from "tinacms"; +import { getGlobalData } from "."; +import NextLink from "next/link"; +import { STRAPI_URL } from "@config/env"; + +interface ProjectData { + id: string; + path: string; + linkPath: Nullable; + linkLabel: Nullable; + description: Nullable; + locale: Nullable; + companyName: Nullable; + projectType: Nullable; + image: Nullable; + localizations?: LocalizationsData[]; + blocks: string; +} + +interface ProjectImage { + id: string; + url: string; + alternativeText: Nullable; +} + +interface DynamicPageProps { + locale: string; + preview: boolean; + data: { + global: GlobalData; + project: ProjectData; + }; +} + +export default function DynamicPage({ data: data }: DynamicPageProps) { + console.log("data", JSON.stringify(data, null, " ")); + const [_, form] = useProjectPlugin(data); + const router = useRouter(); + + return ( + + + + + + + + + + + + + + + + {router.locale!.toUpperCase()} + + + + {router.locale?.toUpperCase()} + + {data ? ( + data.project.localizations?.map((pageLocale) => { + return ( + + {pageLocale.locale?.toUpperCase()} + + ); + }) + ) : ( + + )} + + + + + + + + + + + + + + + + + + + + + + + Blocchi + + + + + + ); +} + +export const getStaticPaths: GetStaticPaths = async (context) => { + if (context.locales == null) { + throw new Error("No locale has been defined!"); + } + const allProjectsRequests = context.locales.map(async (locale) => { + const localeProjects = await fetchGraphQL< + GetProjectsQuery, + GetProjectsQueryVariables + >(GetProjects, { + locale, + }); + + if (localeProjects.projects) { + return filterListNullableItems(localeProjects.projects); + } + return []; + }); + + const allProjects = await Promise.all(allProjectsRequests); + const projects = allProjects.flat(); + + const paths = projects.map((page) => { + const pagePath = page.path?.replace(/^\/+/, "") || ""; + + const slugArray: any = + pagePath.length > 0 ? pagePath.split("/") : undefined; + + console.log("slugArray", slugArray); + + return { + params: { handle: slugArray }, + locale: page.locale!, + }; + }); + + return { paths, fallback: "blocking" }; +}; + +export const getStaticProps: GetStaticProps< + DynamicPageProps | { notFound: boolean } +> = async (context) => { + const pathParts = wrap(context.params?.handle || []); + const path = `/projects/${pathParts.join("/")}`; + const locale = context.locale; + if (locale == null) { + throw new Error(`Path "${pathParts.join("/")}" has no locale!`); + } + const preview = context.preview === true; + + console.log("path", path); + + const availableProjects = await fetchGraphQL< + GetProjectsQuery, + GetProjectsQueryVariables + >(GetProjects, { + locale, + where: { + path, + }, + }); + + if (availableProjects.projects == null) { + return { + notFound: true, + }; + } + + const availableGlobal = await fetchGraphQL< + GetGlobalQuery, + GetGlobalQueryVariables + >(GetGlobal); + + if (availableGlobal.global == null) { + return { + notFound: true, + }; + } + + const projectData = getProjectData(availableProjects.projects, locale); + + const globalData = getGlobalData(availableGlobal.global); + + if (projectData == null) { + return { + notFound: true, + }; + } + + if (globalData == null) { + return { + notFound: true, + }; + } + + if (preview) { + return { + props: { + path: pathParts, + locale, + preview, + previewData: context.previewData, + data: { + global: globalData, + project: projectData, + }, + }, + }; + } + + return { + props: { + path: pathParts, + locale, + preview, + data: { + global: globalData, + project: projectData, + }, + }, + }; +}; + +function getProjectData( + projects: GetProjectsQuery["projects"], + locale: string +): ProjectData | undefined { + const project = projects?.find((project) => project?.locale === locale); + if (project == null) { + return undefined; + } + return { + id: project.id, + companyName: project.companyName || null, + description: project.description || null, + projectType: project.projectType || null, + linkLabel: project.linkLabel || null, + linkPath: project.linkPath || null, + path: project.path, + locale: project.locale || null, + blocks: "aa", + image: project.image + ? { + id: project.image.id, + url: project.image.url, + alternativeText: project.image.alternativeText || null, + } + : null, + localizations: project.localizations + ? filterListNullableItems(project.localizations).map( + (localization) => { + return { + id: localization.id, + locale: localization.locale || null, + path: localization.path || null, + }; + } + ) + : [], + }; +} + +function getProjectInput(data: ProjectData): UpdateProjectInput { + return { + where: { id: data.id }, + data: { + companyName: data.companyName, + description: data.description, + projectType: data.projectType, + linkLabel: data.linkLabel, + linkPath: data.linkPath, + path: data.path, + locale: data.locale, + blocks: undefined, + image: data.image ? data.image.id : null, + }, + }; +} + +interface Data { + project: ProjectData; + global: GlobalData; +} + +function useProjectPlugin(data: Data): [Data, Form] { + const cms = useCMS(); + const formConfig: FormOptions = { + id: data.project.id, + label: "Project settings", + initialValues: data, + onSubmit: async (data) => { + const projectInput = getProjectInput(data.project); + const menuInput = getMenuInput(data.global.topbar.menu); + try { + const response = await cms.api.strapi.fetchGraphql(UpdateProject, { + projectInput: projectInput, + menuInput: menuInput, + }); + + if (response.errors != null) { + cms.alerts.error("Error while saving data", 10000); + } else { + if (response.data) { + cms.alerts.success("Changes saved!"); + } else { + cms.alerts.error("Error while saving changes"); + } + } + } catch (error) { + console.log(error); + cms.alerts.error("Error while saving changes"); + } + }, + fields: [], + }; + + const [formData, form] = useForm(formConfig, { values: data }); + usePlugin(form); + + return [formData, form]; +} + +function getMenuInput(data: MenuData): UpdateMenuInput { + return { + where: { id: data.id }, + data: { + title: data.title, + links: data.links.map((link) => { + return { + id: link.id, + label: link.label || null, + url: link.url || null, + }; + }), + }, + }; +} diff --git a/frontend/pages/projects/index.tsx b/frontend/pages/projects/index.tsx index 36d63110..fa595bd5 100644 --- a/frontend/pages/projects/index.tsx +++ b/frontend/pages/projects/index.tsx @@ -498,7 +498,7 @@ function getMenuInput(data: GlobalData): UpdateMenuInput { }; } -function getGlobalData( +export function getGlobalData( global: GetGlobalQuery["global"] ): GlobalData | undefined { if (global == null) { diff --git a/frontend/theme/index.ts b/frontend/theme/index.ts index 9e784626..27e36b82 100644 --- a/frontend/theme/index.ts +++ b/frontend/theme/index.ts @@ -48,6 +48,14 @@ const overrides: ThemeOverride = { Define custom components */ }, + styles: { + global: { + body: { + fontSize: "sm", + letterSpacing: "0.02em", + }, + }, + }, }; const customTheme = extendTheme(overrides); From 55d246ee83c58b471de6c5d2258415bb09e6c171 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 16:31:56 +0200 Subject: [PATCH 3/8] Update index.tsx --- frontend/features/mainNavigation/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/features/mainNavigation/index.tsx b/frontend/features/mainNavigation/index.tsx index 7f97a4f1..086c8fcf 100644 --- a/frontend/features/mainNavigation/index.tsx +++ b/frontend/features/mainNavigation/index.tsx @@ -20,7 +20,7 @@ const NavigationInlineBlocks = chakra(InlineBlocks); export function NavBar({ children }: React.PropsWithChildren) { return ( - + ) { {children} - + ); } From a146f2d132ae9b7462bb38e7443bab81d9021b59 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 16:51:55 +0200 Subject: [PATCH 4/8] Fixes --- frontend/pages/projects/[...handle].tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/pages/projects/[...handle].tsx b/frontend/pages/projects/[...handle].tsx index 1b401176..d7db2320 100644 --- a/frontend/pages/projects/[...handle].tsx +++ b/frontend/pages/projects/[...handle].tsx @@ -73,12 +73,11 @@ interface DynamicPageProps { } export default function DynamicPage({ data: data }: DynamicPageProps) { - console.log("data", JSON.stringify(data, null, " ")); const [_, form] = useProjectPlugin(data); const router = useRouter(); return ( - + @@ -237,8 +236,6 @@ export const getStaticPaths: GetStaticPaths = async (context) => { const slugArray: any = pagePath.length > 0 ? pagePath.split("/") : undefined; - console.log("slugArray", slugArray); - return { params: { handle: slugArray }, locale: page.locale!, @@ -259,8 +256,6 @@ export const getStaticProps: GetStaticProps< } const preview = context.preview === true; - console.log("path", path); - const availableProjects = await fetchGraphQL< GetProjectsQuery, GetProjectsQueryVariables From 6bed6f08600051f5bf69eb5670d08e7ac575abe7 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 16:56:17 +0200 Subject: [PATCH 5/8] Force project type to be uppercase --- frontend/pages/projects/[...handle].tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/projects/[...handle].tsx b/frontend/pages/projects/[...handle].tsx index d7db2320..de539557 100644 --- a/frontend/pages/projects/[...handle].tsx +++ b/frontend/pages/projects/[...handle].tsx @@ -372,7 +372,7 @@ function getProjectInput(data: ProjectData): UpdateProjectInput { data: { companyName: data.companyName, description: data.description, - projectType: data.projectType, + projectType: data.projectType?.toUpperCase(), linkLabel: data.linkLabel, linkPath: data.linkPath, path: data.path, From 6bc9621339edce0020f052cf2699357e8efd5894 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 16:58:52 +0200 Subject: [PATCH 6/8] Update [...handle].tsx --- frontend/pages/projects/[...handle].tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/projects/[...handle].tsx b/frontend/pages/projects/[...handle].tsx index de539557..cb4d93f6 100644 --- a/frontend/pages/projects/[...handle].tsx +++ b/frontend/pages/projects/[...handle].tsx @@ -78,7 +78,7 @@ export default function DynamicPage({ data: data }: DynamicPageProps) { return ( - + From 9571bfb6323aaad9ca76a73b50a6482410196161 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 17:04:36 +0200 Subject: [PATCH 7/8] Remove console.logs --- frontend/pages/[[...slug]].tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/pages/[[...slug]].tsx b/frontend/pages/[[...slug]].tsx index 6cfa93c7..e07858f3 100644 --- a/frontend/pages/[[...slug]].tsx +++ b/frontend/pages/[[...slug]].tsx @@ -57,9 +57,6 @@ const StyledInlineBlocks = chakra(InlineBlocks); export default function DynamicPage({ data: data, preview }: DynamicPageProps) { const { colorMode } = useColorMode(); - - console.log("data slug", data); - const itemProps = React.useMemo(() => { return { isPreview: preview, From 2fa739d622355d900e83bd7f2737af184faf3ec8 Mon Sep 17 00:00:00 2001 From: Giacomo Baggio Date: Wed, 1 Sep 2021 17:09:24 +0200 Subject: [PATCH 8/8] Update [...handle].tsx --- frontend/pages/projects/[...handle].tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/projects/[...handle].tsx b/frontend/pages/projects/[...handle].tsx index cb4d93f6..8947a7f3 100644 --- a/frontend/pages/projects/[...handle].tsx +++ b/frontend/pages/projects/[...handle].tsx @@ -200,7 +200,7 @@ export default function DynamicPage({ data: data }: DynamicPageProps) { pos="relative" > - Blocchi + Blocks