feat(admin): sprint 19 admin dashboard, routing, i18n
- Add admin dashboard feature (models/gateway/facade/components/page) - Wire admin/products routes and backoffice coming-soon placeholders - Add lastPublishedAt to ProjectEditorFacade/state - Add dashboard i18n keys (en/ru/hy) and docs/ADMIN.md Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,8 @@ export interface ProjectValidationIssue {
|
||||
|
||||
const HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
||||
const HTTP_URL = /^https?:\/\/\S+$/;
|
||||
const KNOWN_PLATFORM_LAYOUT_TYPES = new Set(['default', 'sidebar-left', 'carousel-home', 'minimal']);
|
||||
const KNOWN_SECTION_LAYOUT_STRATEGIES = new Set(['stack', 'grid', 'hero', 'carousel', 'split']);
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ProjectValidator {
|
||||
@@ -20,6 +22,8 @@ export class ProjectValidator {
|
||||
...this.homepageIssues(bootstrap),
|
||||
...this.navigationIssues(bootstrap),
|
||||
...this.colorIssues(bootstrap),
|
||||
...this.translationIssues(bootstrap),
|
||||
...this.layoutIssues(bootstrap),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -69,4 +73,35 @@ export class ProjectValidator {
|
||||
const invalid = Object.values(bootstrap.theme.palette).some(value => !HEX_COLOR.test(value));
|
||||
return invalid ? [{ code: 'invalid-colors', message: 'builder.validationInvalidColors' }] : [];
|
||||
}
|
||||
|
||||
private translationIssues(bootstrap: BootstrapConfig): ProjectValidationIssue[] {
|
||||
const otherLocales = bootstrap.localization.supportedLocales.filter(locale => locale !== bootstrap.localization.defaultLocale);
|
||||
if (otherLocales.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const headerMissing = bootstrap.navigation.header.some(item => {
|
||||
const label = item.label;
|
||||
if (!label || typeof label !== 'object') {
|
||||
return false;
|
||||
}
|
||||
return otherLocales.some(locale => !label[locale]?.trim());
|
||||
});
|
||||
|
||||
const staticPages = bootstrap.staticPages;
|
||||
const staticPagesMissing = staticPages && !Array.isArray(staticPages)
|
||||
? Object.values(staticPages).some(page => page.translations && otherLocales.some(locale => !page.translations![locale]))
|
||||
: false;
|
||||
|
||||
return headerMissing || staticPagesMissing ? [{ code: 'missing-translations', message: 'builder.validationMissingTranslations' }] : [];
|
||||
}
|
||||
|
||||
private layoutIssues(bootstrap: BootstrapConfig): ProjectValidationIssue[] {
|
||||
const invalidPlatformLayout = !!bootstrap.layout?.type && !KNOWN_PLATFORM_LAYOUT_TYPES.has(bootstrap.layout.type);
|
||||
const invalidSectionLayout = bootstrap.pages.some(page =>
|
||||
page.sections.some(section => !!section.layout?.strategy && !KNOWN_SECTION_LAYOUT_STRATEGIES.has(section.layout.strategy)),
|
||||
);
|
||||
|
||||
return invalidPlatformLayout || invalidSectionLayout ? [{ code: 'invalid-layouts', message: 'builder.validationInvalidLayouts' }] : [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user