Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge main into next #3456

Merged
merged 20 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7f72e82
Extract text content from blocks (#3057)
thomasdax98 Feb 10, 2025
f5b1407
Add `includeInvisibleContent` option to `extractTextContents` (#3412)
thomasdax98 Feb 17, 2025
2998c74
Generate SEO block fields (#2614)
thomasdax98 Feb 17, 2025
e452353
Demo Site: Add handler for revalidateTag (#3444)
fraxachun Feb 18, 2025
bb041f7
Add changeset for SEO tag generation (#3453)
thomasdax98 Feb 18, 2025
9c93436
Docs: add info on how to provide dependencies in a custom block (#3454)
thomasdax98 Feb 18, 2025
3c47c08
Add language support for content generation (#3451)
thomasdax98 Feb 18, 2025
1c3f4e6
Merge pull request #3397 from vivid-planet/feature/seo-tag-generation
johnnyomair Feb 18, 2025
6b75f20
Use Data Grid density for `DataGridToolbar`'s density (#3337)
juliawegmayr Feb 18, 2025
9b190db
Fix spacing for `ListItemIcon` and `ListItemAvatar` (#3416)
juliawegmayr Feb 18, 2025
66e6f79
Version Packages (#3301)
github-actions[bot] Feb 18, 2025
2c7b75e
Demo Admin: Use first available content scope for user as default val…
raphaelblum Feb 19, 2025
0feb568
Docs: Add stories for `createCompositeBlockSelectField` (#3345)
johnnyomair Feb 19, 2025
457c62d
Add all variants to button dev story (#3360)
juliawegmayr Feb 19, 2025
faa54eb
Fix display of warnings for forms that use both form-level and field-…
juliawegmayr Feb 19, 2025
e6f9641
Set fallback values for user created via ID token (#3467)
fraxachun Feb 20, 2025
2322738
Demo Site: use alternative CSS-only animation for accordion block (#3…
johnnyomair Feb 20, 2025
32ad6c5
Merge main into next
invalid-email-address Feb 20, 2025
4b45d5f
Fix conflicts
thomasdax98 Feb 24, 2025
1e9a33b
Merge branch 'next' into merge-main-into-next
thomasdax98 Feb 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .changeset/afraid-clocks-juggle.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/clever-cougars-glow.md

This file was deleted.

7 changes: 0 additions & 7 deletions .changeset/eighty-goats-beam.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/famous-pianos-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/admin": patch
---

Fix display of warnings for forms that use both form-level and field-level validation
5 changes: 0 additions & 5 deletions .changeset/friendly-seas-yawn.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/healthy-fireants-behave.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/metal-bees-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/cms-api": patch
---

Add fallback values for users created via ID token
5 changes: 0 additions & 5 deletions .changeset/nine-roses-reflect.md

This file was deleted.

8 changes: 0 additions & 8 deletions .changeset/sharp-monkeys-cry.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/shiny-mangos-report.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/sixty-radios-switch.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/strong-bees-breathe.md

This file was deleted.

3 changes: 2 additions & 1 deletion demo/admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { css, Global } from "@emotion/react";
import { createApolloClient } from "@src/common/apollo/createApolloClient";
import { ConfigProvider, createConfig } from "@src/config";
import { type ContentScope } from "@src/site-configs";
import { theme } from "@src/theme";
import { HTML5toTouch } from "rdndmb-html5-to-touch";
import { DndProvider } from "react-dnd-multi-backend";
Expand Down Expand Up @@ -99,7 +100,7 @@ export function App() {
}}
>
<IntlProvider locale="en" messages={getMessages()}>
<LocaleProvider resolveLocaleForScope={(scope) => scope.domain}>
<LocaleProvider resolveLocaleForScope={(scope: ContentScope) => scope.language}>
<MuiThemeProvider theme={theme}>
<DndProvider options={HTML5toTouch}>
<SnackbarProvider>
Expand Down
6 changes: 5 additions & 1 deletion demo/admin/src/common/ContentScopeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ export const ContentScopeProvider = ({ children }: Pick<ContentScopeProviderProp
language: { value: contentScope.language, label: contentScope.language.toUpperCase() },
}));

if (user.allowedContentScopes.length === 0) {
throw new Error("User does not have access to any scopes.");
}

return (
<ContentScopeProviderLibrary<ContentScope> values={values} defaultValue={{ domain: "main", language: "en" }}>
<ContentScopeProviderLibrary<ContentScope> values={values} defaultValue={userContentScopes[0]}>
{children}
</ContentScopeProviderLibrary>
);
Expand Down
1 change: 1 addition & 0 deletions demo/admin/src/common/blocks/LayoutBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export const LayoutBlock = createCompositeBlock(
<Field name="layout" component={FinalFormLayoutSelect} layouts={layoutOptions} fullWidth />
</BlocksFinalForm>
),
extractTextContents: () => [],
}),
title: <FormattedMessage id="layoutBlock.layout" defaultMessage="Layout" />,
},
Expand Down
189 changes: 100 additions & 89 deletions demo/admin/src/documents/pages/EditPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
BlockAdminComponentRoot,
BlockAdminTabLabel,
BlockPreviewWithTabs,
ContentGenerationConfigProvider,
ContentScopeIndicator,
createUsePage,
openSitePreviewWindow,
Expand Down Expand Up @@ -119,95 +120,105 @@ export const EditPage = ({ id }: Props) => {

return (
<AzureAiTranslatorProvider showApplyTranslationDialog={true} enabled={true}>
{hasChanges && (
<RouterPrompt
message={(location) => {
if (location.pathname.startsWith(match.url)) return true; //we navigated within our self
return intl.formatMessage({
id: "editPage.discardChanges",
defaultMessage: "Discard unsaved changes?",
});
}}
saveAction={async () => {
try {
await handleSavePage();
return true;
} catch {
return false;
}
}}
/>
)}
<Toolbar scopeIndicator={<ContentScopeIndicator />}>
<ToolbarItem>
<IconButton onClick={stackApi?.goBack} size="large">
<ArrowLeft />
</IconButton>
</ToolbarItem>
<PageName pageId={id} />
<FillSpace />
<ToolbarActions>
<Stack direction="row" spacing={1}>
<Button
startIcon={<Preview />}
variant="textDark"
disabled={!pageState}
onClick={() => {
openSitePreviewWindow(pageState.path, contentScopeMatch.url);
}}
>
<FormattedMessage id="pages.pages.page.edit.preview" defaultMessage="Web preview" />
</Button>
{pageSaveButton}
</Stack>
</ToolbarActions>
</Toolbar>
<MainContent disablePaddingBottom>
<BlockPreviewWithTabs previewUrl={previewUrl} previewState={previewState} previewApi={previewApi}>
{[
{
key: "content",
label: (
<BlockAdminTabLabel isValid={rootBlocksApi.content.isValid}>
<FormattedMessage id="generic.blocks" defaultMessage="Blocks" />
</BlockAdminTabLabel>
),
content: (
<BlockAdminComponentRoot
title={intl.formatMessage({ id: "pages.pages.page.edit.pageBlocks.title", defaultMessage: "Page" })}
>
{rootBlocksApi.content.adminUI}
</BlockAdminComponentRoot>
),
},
{
key: "stage",
label: (
<BlockAdminTabLabel isValid={rootBlocksApi.stage.isValid}>
<FormattedMessage id="pages.page.edit.stage" defaultMessage="Stage" />
</BlockAdminTabLabel>
),
content: (
<BlockAdminComponentRoot
title={intl.formatMessage({ id: "pages.pages.page.edit.stage.title", defaultMessage: "Stage" })}
>
{rootBlocksApi.stage.adminUI}
</BlockAdminComponentRoot>
),
},
{
key: "config",
label: (
<BlockAdminTabLabel isValid={rootBlocksApi.seo.isValid}>
<FormattedMessage id="pages.pages.page.edit.config" defaultMessage="Config" />
</BlockAdminTabLabel>
),
content: rootBlocksApi.seo.adminUI,
},
]}
</BlockPreviewWithTabs>
</MainContent>
{dialogs}
<ContentGenerationConfigProvider
seo={{
getRelevantContent: () => {
if (!pageState || !pageState.document) return [];

return PageContentBlock.extractTextContents?.(pageState.document.content, { includeInvisibleContent: false }) ?? [];
},
}}
>
{hasChanges && (
<RouterPrompt
message={(location) => {
if (location.pathname.startsWith(match.url)) return true; //we navigated within our self
return intl.formatMessage({
id: "editPage.discardChanges",
defaultMessage: "Discard unsaved changes?",
});
}}
saveAction={async () => {
try {
await handleSavePage();
return true;
} catch {
return false;
}
}}
/>
)}
<Toolbar scopeIndicator={<ContentScopeIndicator />}>
<ToolbarItem>
<IconButton onClick={stackApi?.goBack} size="large">
<ArrowLeft />
</IconButton>
</ToolbarItem>
<PageName pageId={id} />
<FillSpace />
<ToolbarActions>
<Stack direction="row" spacing={1}>
<Button
startIcon={<Preview />}
variant="textDark"
disabled={!pageState}
onClick={() => {
openSitePreviewWindow(pageState.path, contentScopeMatch.url);
}}
>
<FormattedMessage id="pages.pages.page.edit.preview" defaultMessage="Web preview" />
</Button>
{pageSaveButton}
</Stack>
</ToolbarActions>
</Toolbar>
<MainContent disablePaddingBottom>
<BlockPreviewWithTabs previewUrl={previewUrl} previewState={previewState} previewApi={previewApi}>
{[
{
key: "content",
label: (
<BlockAdminTabLabel isValid={rootBlocksApi.content.isValid}>
<FormattedMessage id="generic.blocks" defaultMessage="Blocks" />
</BlockAdminTabLabel>
),
content: (
<BlockAdminComponentRoot
title={intl.formatMessage({ id: "pages.pages.page.edit.pageBlocks.title", defaultMessage: "Page" })}
>
{rootBlocksApi.content.adminUI}
</BlockAdminComponentRoot>
),
},
{
key: "stage",
label: (
<BlockAdminTabLabel isValid={rootBlocksApi.stage.isValid}>
<FormattedMessage id="pages.page.edit.stage" defaultMessage="Stage" />
</BlockAdminTabLabel>
),
content: (
<BlockAdminComponentRoot
title={intl.formatMessage({ id: "pages.pages.page.edit.stage.title", defaultMessage: "Stage" })}
>
{rootBlocksApi.stage.adminUI}
</BlockAdminComponentRoot>
),
},
{
key: "config",
label: (
<BlockAdminTabLabel isValid={rootBlocksApi.seo.isValid}>
<FormattedMessage id="pages.pages.page.edit.config" defaultMessage="Config" />
</BlockAdminTabLabel>
),
content: rootBlocksApi.seo.adminUI,
},
]}
</BlockPreviewWithTabs>
</MainContent>
{dialogs}
</ContentGenerationConfigProvider>
</AzureAiTranslatorProvider>
);
};
10 changes: 10 additions & 0 deletions demo/api/block-meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,16 @@
"name": "scope",
"kind": "Json",
"nullable": true
},
{
"name": "altText",
"kind": "String",
"nullable": true
},
{
"name": "title",
"kind": "String",
"nullable": true
}
]
},
Expand Down
12 changes: 8 additions & 4 deletions demo/api/src/content-generation/content-generation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import { Injectable } from "@nestjs/common";
export class ContentGenerationService implements ContentGenerationServiceInterface {
constructor(private readonly openAiContentGenerationService: AzureOpenAiContentGenerationService) {}

async generateAltText(fileId: string) {
return this.openAiContentGenerationService.generateAltText(fileId);
async generateAltText(fileId: string, options?: { language: string }) {
return this.openAiContentGenerationService.generateAltText(fileId, options);
}

async generateImageTitle(fileId: string) {
return this.openAiContentGenerationService.generateImageTitle(fileId);
async generateImageTitle(fileId: string, options?: { language: string }) {
return this.openAiContentGenerationService.generateImageTitle(fileId, options);
}

async generateSeoTags(content: string, options: { language: string }) {
return this.openAiContentGenerationService.generateSeoTags(content, options);
}
}
Loading
Loading