Browse Source

Content view restructured.

pull/272/head
Sebastian Stehle 8 years ago
parent
commit
65280bb867
  1. 11
      src/Squidex/app/features/content/module.ts
  2. 6
      src/Squidex/app/features/content/pages/content/content-page.component.html
  3. 71
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  4. 65
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  5. 16
      src/Squidex/app/features/content/pages/contents/contents-page.component.scss
  6. 83
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  7. 24
      src/Squidex/app/features/content/pages/contents/search-form.component.html
  8. 20
      src/Squidex/app/features/content/pages/contents/search-form.component.scss
  9. 29
      src/Squidex/app/features/content/pages/contents/search-form.component.ts
  10. 30
      src/Squidex/app/features/content/pages/messages.ts
  11. 8
      src/Squidex/app/features/content/shared/contents-selector.component.html
  12. 28
      src/Squidex/app/features/content/shared/contents-selector.component.scss
  13. 6
      src/Squidex/app/features/content/shared/contents-selector.component.ts
  14. 2
      src/Squidex/app/features/content/shared/references-editor.component.html
  15. 2
      src/Squidex/app/features/schemas/declarations.ts
  16. 2
      src/Squidex/app/features/schemas/module.ts
  17. 38
      src/Squidex/app/shared/guards/schema-must-exist-published.guard.ts
  18. 6
      src/Squidex/app/shared/guards/schema-must-exist.guard.ts
  19. 2
      src/Squidex/app/shared/internal.ts
  20. 4
      src/Squidex/app/shared/module.ts

11
src/Squidex/app/features/content/module.ts

@ -13,7 +13,7 @@ import {
CanDeactivateGuard,
ResolveAppLanguagesGuard,
ResolveContentGuard,
ResolvePublishedSchemaGuard,
SchemaMustExistPublishedGuard,
SqxFrameworkModule,
SqxSharedModule
} from '@app/shared';
@ -41,11 +41,16 @@ const routes: Routes = [
},
{
path: ':schemaName',
component: ContentsPageComponent,
canActivate: [SchemaMustExistPublishedGuard],
resolve: {
schema: ResolvePublishedSchemaGuard, appLanguages: ResolveAppLanguagesGuard
appLanguages: ResolveAppLanguagesGuard
},
children: [
{
path: '',
component: ContentsPageComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: 'new',
component: ContentPageComponent,

6
src/Squidex/app/features/content/pages/content/content-page.component.html

@ -1,8 +1,12 @@
<sqx-title message="{app} | {schema} | Content" parameter1="app" parameter2="schema" [value1]="ctx.appName" [value2]="schema?.displayName"></sqx-title>
<form [formGroup]="contentForm" (ngSubmit)="saveAndPublish()">
<sqx-panel desiredWidth="53rem" showSidebar="true">
<sqx-panel desiredWidth="54rem" showSidebar="true">
<ng-container title>
<a class="btn btn-link" (click)="back()">
<i class="icon-angle-left"></i>
</a>
<ng-container *ngIf="isNewMode">
New Content
</ng-container>

71
src/Squidex/app/features/content/pages/content/content-page.component.ts

@ -10,13 +10,7 @@ import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Observable, Subscription } from 'rxjs';
import {
ContentCreated,
ContentRemoved,
ContentStatusChanged,
ContentUpdated,
ContentVersionSelected
} from './../messages';
import { ContentVersionSelected } from './../messages';
import {
AppContext,
@ -27,6 +21,7 @@ import {
ContentsService,
fieldInvariant,
SchemaDetailsDto,
SchemasState,
Version
} from '@app/shared';
@ -39,10 +34,8 @@ import {
]
})
export class ContentPageComponent implements CanComponentDeactivate, OnDestroy, OnInit {
private contentStatusChangedSubscription: Subscription;
private contentDeletedSubscription: Subscription;
private contentUpdatedSubscription: Subscription;
private contentVersionSelectedSubscription: Subscription;
private selectedSchemaSubscription: Subscription;
public schema: SchemaDetailsDto;
@ -57,15 +50,14 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy,
constructor(public readonly ctx: AppContext,
private readonly contentsService: ContentsService,
private readonly router: Router
private readonly router: Router,
private readonly schemasState: SchemasState
) {
}
public ngOnDestroy() {
this.contentVersionSelectedSubscription.unsubscribe();
this.contentStatusChangedSubscription.unsubscribe();
this.contentUpdatedSubscription.unsubscribe();
this.contentDeletedSubscription.unsubscribe();
this.selectedSchemaSubscription.unsubscribe();
}
public ngOnInit() {
@ -75,40 +67,14 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy,
this.loadVersion(message.version);
});
this.contentDeletedSubscription =
this.ctx.bus.of(ContentRemoved)
.subscribe(message => {
if (this.content && message.content.id === this.content.id) {
this.router.navigate(['../'], { relativeTo: this.ctx.route });
}
});
this.contentUpdatedSubscription =
this.ctx.bus.of(ContentUpdated)
.subscribe(message => {
if (this.content && message.content.id === this.content.id) {
this.reloadContentForm(message.content);
}
});
this.contentStatusChangedSubscription =
this.ctx.bus.of(ContentStatusChanged)
.subscribe(message => {
if (this.content && message.content.id === this.content.id) {
this.content =
this.content.changeStatus(
message.content.scheduledTo || message.content.status,
message.content.scheduledAt,
message.content.lastModifiedBy,
message.content.version,
message.content.lastModified);
}
});
this.selectedSchemaSubscription =
this.schemasState.selectedSchema
.subscribe(schema => {
const routeData = allData(this.ctx.route);
this.setupLanguages(routeData);
this.setupContentForm(routeData.schema);
this.setupContentForm(schema!);
});
this.ctx.route.data.map(d => d.content)
.subscribe((content: ContentDto) => {
@ -129,7 +95,6 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy,
this.content = this.contentOld;
this.contentOld = null;
this.emitContentUpdated(this.content);
this.reloadContentForm(this.content);
}
}
@ -157,7 +122,6 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy,
this.ctx.notifyInfo('Content created successfully.');
this.emitContentCreated(this.content);
this.back();
}, error => {
this.ctx.notifyError(error);
@ -171,7 +135,6 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy,
this.ctx.notifyInfo('Content saved successfully.');
this.emitContentUpdated(content);
this.enableContentForm();
this.reloadContentForm(content);
}, error => {
@ -204,16 +167,8 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy,
}
}
private back() {
this.router.navigate(['../'], { relativeTo: this.ctx.route, replaceUrl: true });
}
private emitContentCreated(content: ContentDto) {
this.ctx.bus.emit(new ContentCreated(content));
}
private emitContentUpdated(content: ContentDto) {
this.ctx.bus.emit(new ContentUpdated(content));
public back() {
this.router.navigate([this.schema.name], { relativeTo: this.ctx.route.parent!.parent, replaceUrl: true });
}
private disableContentForm() {

65
src/Squidex/app/features/content/pages/contents/contents-page.component.html

@ -1,16 +1,14 @@
<sqx-title message="{app} | {schema} | Contents" parameter1="app" parameter2="schema" [value1]="ctx.appName" [value2]="schema?.displayName"></sqx-title>
<sqx-panel [desiredWidth]="isReadOnly ? '40rem' : '60rem'" contentClass="grid">
<sqx-panel desiredWidth="*" contentClass="grid">
<ng-container title>
<ng-container *ngIf="!isReadOnly && !isArchive">
Contents
</ng-container>
<ng-container *ngIf="isArchive">
<ng-container *ngIf="isArchive; else noArchive">
Archive
</ng-container>
<ng-container *ngIf="isReadOnly">
References
</ng-container>
<ng-template #noArchive>
Contents
</ng-template>
</ng-container>
<ng-container menu>
@ -19,40 +17,14 @@
</button>
<sqx-shortcut keys="ctrl+shift+r" (trigger)="load(true)"></sqx-shortcut>
<sqx-shortcut keys="ctrl+shift+f" (trigger)="inputFind.focus()"></sqx-shortcut>
<sqx-shortcut keys="ctrl+shift+g" (trigger)="newButton.click()" *ngIf="!isReadOnly"></sqx-shortcut>
<form class="form-inline" (ngSubmit)="search()">
<input class="form-control form-control-expandable" #inputFind [formControl]="contentsFilter" placeholder="Search for content" />
<a class="expand-search" (click)="searchModal.toggle()" #archive>
<i class="icon-caret-down"></i>
</a>
</form>
<sqx-onboarding-tooltip id="contentArchive" [for]="archive" position="bottomRight" after="60000">
Click this icon to show the advanced search menu and to show the archive!
</sqx-onboarding-tooltip>
<sqx-onboarding-tooltip id="contentFind" [for]="inputFind" position="bottomRight" after="120000">
Search for content using full text search over all fields and languages!
</sqx-onboarding-tooltip>
<div class="dropdown-menu" *sqxModalView="searchModal" [sqxModalTarget]="inputFind">
<sqx-search-form
[canArchive]="!isReadOnly"
(queryChanged)="contentsFilter.setValue($event, { emitEvent: false })"
[query]="contentsFilter.value"
(archivedChanged)="updateArchive($event)"
[archived]="isArchive">
</sqx-search-form>
</div>
<ng-container *ngIf="!isReadOnly && languages.length > 1">
<sqx-search-form (queryChanged)="search($event)" [query]="contentsQuery" enableShortcut="true"></sqx-search-form>
<ng-container *ngIf="languages.length > 1">
<sqx-language-selector class="languages-buttons" (selectedLanguageChanged)="selectLanguage($event)" [languages]="languages"></sqx-language-selector>
</ng-container>
<button *ngIf="!isReadOnly" class="btn btn-success" #newButton routerLink="new" title="New Content (CTRL + SHIFT + G)">
<button class="btn btn-success" #newButton routerLink="new" title="New Content (CTRL + SHIFT + G)">
<i class="icon-plus"></i> New
</button>
</ng-container>
@ -111,8 +83,8 @@
<div class="grid-content">
<div sqxIgnoreScrollbar>
<table class="table table-items table-fixed" *ngIf="contentItems" >
<tbody *ngIf="!isReadOnly">
<table class="table table-items table-fixed" *ngIf="contentItems">
<tbody>
<ng-template ngFor let-content [ngForOf]="contentItems" [ngForTrackBy]="trackByContent">
<tr [sqxContent]="content" [routerLink]="[content.id]" routerLinkActive="active"
[language]="languageSelected"
@ -129,17 +101,6 @@
<tr class="spacer"></tr>
</ng-template>
</tbody>
<tbody *ngIf="isReadOnly">
<ng-template ngFor let-content [ngForOf]="contentItems">
<tr [sqxContent]="content" dnd-draggable [dragData]="dropData(content)"
[language]="languageSelected"
[schemaFields]="contentFields"
[schema]="schema"
isReadOnly="true"></tr>
<tr class="spacer"></tr>
</ng-template>
</tbody>
</table>
</div>
</div>
@ -150,8 +111,6 @@
</ng-container>
</sqx-panel>
<router-outlet></router-outlet>
<ng-container *sqxModalView="dueTimeDialog;onRoot:true">
<sqx-modal-dialog (close)="cancelStatusChange()">
<ng-container title>

16
src/Squidex/app/features/content/pages/contents/contents-page.component.scss

@ -9,22 +9,6 @@
font-size: .8rem;
}
.form-inline {
position: relative;
}
.form-control-expandable {
padding-right: 1.5rem;
}
.expand-search {
@include absolute(8px, 8px, auto, auto);
color: $color-border-dark !important;
font-size: .9rem;
font-weight: normal;
cursor: pointer !important;
}
.selection {
background: $color-table-footer;
border-bottom: 2px solid $color-border;

83
src/Squidex/app/features/content/pages/contents/contents-page.component.ts

@ -6,16 +6,8 @@
*/
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable, Subscription } from 'rxjs';
import {
ContentCreated,
ContentRemoved,
ContentStatusChanged,
ContentUpdated
} from './../messages';
import {
allData,
AppContext,
@ -27,6 +19,7 @@ import {
ImmutableArray,
ModalView,
Pager,
SchemasState,
SchemaDetailsDto,
Versioned
} from '@app/shared';
@ -40,8 +33,7 @@ import {
]
})
export class ContentsPageComponent implements OnDestroy, OnInit {
private contentCreatedSubscription: Subscription;
private contentUpdatedSubscription: Subscription;
private selectedSchemaSubscription: Subscription;
public schema: SchemaDetailsDto;
@ -49,7 +41,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
public contentItems: ImmutableArray<ContentDto>;
public contentFields: FieldDto[];
public contentsFilter = new FormControl();
public contentsQuery = '';
public contentsPager = new Pager(0);
@ -70,58 +61,31 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
public languageParameter: string;
public isAllSelected = false;
public isReadOnly = false;
public isArchive = false;
constructor(public readonly ctx: AppContext,
private readonly contentsService: ContentsService
private readonly contentsService: ContentsService,
private readonly schemasState: SchemasState
) {
}
public ngOnDestroy() {
this.contentCreatedSubscription.unsubscribe();
this.contentUpdatedSubscription.unsubscribe();
this.selectedSchemaSubscription.unsubscribe();
}
public ngOnInit() {
this.contentCreatedSubscription =
this.ctx.bus.of(ContentCreated)
.subscribe(message => {
this.contentItems = this.contentItems.pushFront(message.content);
this.contentsPager = this.contentsPager.incrementCount();
});
this.contentUpdatedSubscription =
this.ctx.bus.of(ContentUpdated)
.subscribe(message => {
this.contentItems = this.contentItems.replaceBy('id', message.content, (o, n) => o.update(n.data, n.lastModifiedBy, n.version, n.lastModified));
});
const routeData = allData(this.ctx.route);
this.languages = routeData.appLanguages;
this.ctx.route.data.map(p => p.isReadOnly)
.subscribe(isReadOnly => {
this.isReadOnly = isReadOnly;
});
this.ctx.route.params.map(p => p.language)
.subscribe(language => {
this.languageSelected = this.languages.find(l => l.iso2Code === language) || this.languages.find(l => l.isMaster) || this.languages[0];
});
this.ctx.route.data.map(d => d.schema)
this.selectedSchemaSubscription =
this.schemasState.selectedSchema
.subscribe(schema => {
this.schema = schema;
this.schema = schema!;
this.resetContents();
this.load();
});
}
public dropData(content: ContentDto) {
return { content, schemaId: this.schema.id };
const routeData = allData(this.ctx.route);
this.languages = routeData.appLanguages;
}
public publishContent(content: ContentDto) {
@ -207,8 +171,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
content = content.changeStatus(status, dt, this.ctx.userToken, dto.version);
this.contentItems = this.contentItems.replaceBy('id', content);
this.emitContentStatusChanged(content);
}
});
}
@ -233,9 +195,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
public deleteContentItem(content: ContentDto): Observable<any> {
return this.contentsService.deleteContent(this.ctx.appName, this.schema.name, content.id, content.version)
.do(() => {
this.emitContentRemoved(content);
})
.catch(error => {
this.ctx.notifyError(error);
@ -247,8 +206,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
content = content.update(update.payload, this.ctx.userToken, update.version);
this.contentItems = this.contentItems.replaceBy('id', content);
this.emitContentUpdated(content);
}
public load(showInfo = false) {
@ -271,7 +228,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
}
public updateArchive(isArchive: boolean) {
this.contentsQuery = this.contentsFilter.value;
this.contentsPager = new Pager(0);
this.isArchive = isArchive;
@ -281,8 +237,8 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
this.load();
}
public search() {
this.contentsQuery = this.contentsFilter.value;
public search(query: string) {
this.contentsQuery = query;
this.contentsPager = new Pager(0);
this.load();
@ -349,18 +305,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
this.languageSelected = language;
}
private emitContentStatusChanged(content: ContentDto) {
this.ctx.bus.emit(new ContentStatusChanged(content));
}
private emitContentUpdated(content: ContentDto) {
this.ctx.bus.emit(new ContentUpdated(content));
}
private emitContentRemoved(content: ContentDto) {
this.ctx.bus.emit(new ContentRemoved(content));
}
public trackByContent(content: ContentDto): string {
return content.id;
}
@ -368,7 +312,6 @@ export class ContentsPageComponent implements OnDestroy, OnInit {
private resetContents() {
this.contentItems = ImmutableArray.empty<ContentDto>();
this.contentsQuery = '';
this.contentsFilter.setValue('');
this.contentsPager = new Pager(0);
this.selectedItems = {};

24
src/Squidex/app/features/content/pages/contents/search-form.component.html

@ -1,4 +1,25 @@
<div class="form-horizontal">
<ng-container *ngIf="enableShortcut">
<sqx-shortcut keys="ctrl+shift+f" (trigger)="inputFind.focus()"></sqx-shortcut>
</ng-container>
<form class="form-inline search-form" (ngSubmit)="search()">
<input class="form-control form-control-expandable" #inputFind [formControl]="contentsFilter" placeholder="Search for content" />
<a class="expand-search" (click)="searchModal.toggle()" #archive>
<i class="icon-caret-down"></i>
</a>
</form>
<sqx-onboarding-tooltip id="contentArchive" [for]="archive" position="bottomRight" after="60000">
Click this icon to show the advanced search menu and to show the archive!
</sqx-onboarding-tooltip>
<sqx-onboarding-tooltip id="contentFind" [for]="inputFind" position="bottomRight" after="120000">
Search for content using full text search over all fields and languages!
</sqx-onboarding-tooltip>
<div class="dropdown-menu" *sqxModalView="searchModal" [sqxModalTarget]="inputFind">
<div class="form-horizontal">
<div [formGroup]="searchForm">
<div class="form-group row">
<label class="col col-2 col-form-label" for="odataSearch">Text</label>
@ -35,4 +56,5 @@
<div class="link">
Read more about filtering in the <a href="https://docs.squidex.io/04-guides/02-api.html" target="_blank">Documentation</a>.
</div>
</div>
</div>

20
src/Squidex/app/features/content/pages/contents/search-form.component.scss

@ -1,6 +1,18 @@
@import '_vars';
@import '_mixins';
.search-form {
display: inline-block;
}
.form-inline {
position: relative;
}
.form-control-expandable {
padding-right: 1.5rem;
}
.form-horizontal {
padding: 1rem 1.5rem;
min-width: 25rem;
@ -14,6 +26,14 @@
text-align: right;
}
.expand-search {
@include absolute(8px, 8px, auto, auto);
color: $color-border-dark !important;
font-size: .9rem;
font-weight: normal;
cursor: pointer !important;
}
.link {
margin-top: 1.5rem;
font-size: .8rem;

29
src/Squidex/app/features/content/pages/contents/search-form.component.ts

@ -6,7 +6,9 @@
*/
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { FormBuilder, FormControl } from '@angular/forms';
import { ModalView } from '@app/shared';
@Component({
selector: 'sqx-search-form',
@ -15,8 +17,6 @@ import { FormBuilder } from '@angular/forms';
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SearchFormComponent implements OnChanges {
private queryValue = '';
@Input()
public query = '';
@ -32,6 +32,12 @@ export class SearchFormComponent implements OnChanges {
@Input()
public canArchive = true;
@Input()
public enableShortcut = false;
public contentsFilter = new FormControl();
public searchModal = new ModalView();
public searchForm =
this.formBuilder.group({
odataOrderBy: '',
@ -44,8 +50,18 @@ export class SearchFormComponent implements OnChanges {
) {
}
public search() {
this.invalidate(this.contentsFilter.value);
this.queryChanged.emit(this.contentsFilter.value);
}
public ngOnChanges() {
if (this.query === this.queryValue) {
this.invalidate(this.query);
}
private invalidate(query: string) {
if (query === this.contentsFilter.value) {
return;
}
@ -81,7 +97,7 @@ export class SearchFormComponent implements OnChanges {
odataOrderBy
}, { emitEvent: false });
this.queryValue = this.query;
this.contentsFilter.setValue(this.query);
}
public updateQuery() {
@ -112,8 +128,9 @@ export class SearchFormComponent implements OnChanges {
}
if (query !== this.query) {
this.queryValue = query;
this.queryChanged.emit(query);
}
this.contentsFilter.setValue(query);
}
}

30
src/Squidex/app/features/content/pages/messages.ts

@ -5,39 +5,9 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { ContentDto } from '@app/shared';
export class ContentCreated {
constructor(
public readonly content: ContentDto
) {
}
}
export class ContentUpdated {
constructor(
public readonly content: ContentDto
) {
}
}
export class ContentRemoved {
constructor(
public readonly content: ContentDto
) {
}
}
export class ContentVersionSelected {
constructor(
public readonly version: number
) {
}
}
export class ContentStatusChanged {
constructor(
public readonly content: ContentDto
) {
}
}

8
src/Squidex/app/features/content/shared/contents-selector.component.html

@ -4,13 +4,7 @@
</ng-container>
<ng-container tabs>
<form class="form-inline search-form" (ngSubmit)="search()">
<input class="form-control form-control-expandable" [formControl]="contentsFilter" placeholder="Search for content" />
<a class="expand-search" (click)="searchModal.toggle()" #archive>
<i class="icon-caret-down"></i>
</a>
</form>
<sqx-search-form (queryChanged)="search($event)"></sqx-search-form>
<button class="btn btn-link btn-secondary" (click)="load(true)">
<i class="icon-reset"></i> Refresh

28
src/Squidex/app/features/content/shared/contents-selector.component.scss

@ -1,34 +1,6 @@
@import '_vars';
@import '_mixins';
.content {
cursor: pointer;
}
.icon-plus {
font-size: .8rem;
}
.search-form {
display: inline-block;
}
.form-inline {
position: relative;
}
.form-control-expandable {
padding-right: 1.5rem;
}
.expand-search {
@include absolute(8px, 8px, auto, auto);
color: $color-border-dark !important;
font-size: .9rem;
font-weight: normal;
cursor: pointer !important;
}
:host /deep/ .modal-body {
background: $color-background;
}

6
src/Squidex/app/features/content/shared/contents-selector.component.ts

@ -6,7 +6,6 @@
*/
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import {
AppsState,
@ -42,7 +41,6 @@ export class ContentsSelectorComponent implements OnInit {
public searchModal = new ModalView();
public contentItems: ImmutableArray<ContentDto>;
public contentsFilter = new FormControl();
public contentsQuery = '';
public contentsPager = new Pager(0);
@ -81,8 +79,8 @@ export class ContentsSelectorComponent implements OnInit {
});
}
public search() {
this.contentsQuery = this.contentsFilter.value;
public search(query: string) {
this.contentsQuery = query;
this.contentsPager = new Pager(0);
this.load();

2
src/Squidex/app/features/content/shared/references-editor.component.html

@ -1,5 +1,5 @@
<div class="references-container" [class.disabled]="isDisabled">
<div class="drop-area-container" *ngIf="schema && !isDisabled">
<div class="drop-area-container" *ngIf="schema">
<div class="drop-area" (click)="selectorModal.show()">
click here to link a content.
</div>

2
src/Squidex/app/features/schemas/declarations.ts

@ -5,8 +5,6 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
export * from './guards/schema-must-exist.guard';
export * from './pages/schema/types/assets-ui.component';
export * from './pages/schema/types/assets-validation.component';
export * from './pages/schema/types/boolean-ui.component';

2
src/Squidex/app/features/schemas/module.ts

@ -10,6 +10,7 @@ import { RouterModule, Routes } from '@angular/router';
import { DndModule } from 'ng2-dnd';
import {
SchemaMustExistGuard,
SqxFrameworkModule,
SqxSharedModule
} from '@app/shared';
@ -36,7 +37,6 @@ import {
ReferencesValidationComponent,
SchemaEditFormComponent,
SchemaFormComponent,
SchemaMustExistGuard,
SchemaPageComponent,
SchemasPageComponent,
SchemaScriptsFormComponent,

38
src/Squidex/app/shared/guards/schema-must-exist-published.guard.ts

@ -0,0 +1,38 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from '@app/framework';
import { SchemasState } from './../state/schemas.state';
@Injectable()
export class SchemaMustExistPublishedGuard implements CanActivate {
constructor(
private readonly schemasState: SchemasState,
private readonly router: Router
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
const schemaName = allParams(route)['schemaName'];
const result =
this.schemasState.selectSchema(schemaName)
.do(dto => {
if (!dto || !dto.isPublished) {
this.router.navigate(['/404']);
}
})
.map(s => s !== null && s.isPublished);
return result;
}
}

6
src/Squidex/app/features/schemas/guards/schema-must-exist.guard.ts → src/Squidex/app/shared/guards/schema-must-exist.guard.ts

@ -9,7 +9,9 @@ import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams, SchemasState } from '@app/shared';
import { allParams } from '@app/framework';
import { SchemasState } from './../state/schemas.state';
@Injectable()
export class SchemaMustExistGuard implements CanActivate {
@ -29,7 +31,7 @@ export class SchemaMustExistGuard implements CanActivate {
this.router.navigate(['/404']);
}
})
.map(u => u !== null);
.map(s => s !== null);
return result;
}

2
src/Squidex/app/shared/internal.ts

@ -13,6 +13,8 @@ export * from './guards/resolve-app-languages.guard';
export * from './guards/resolve-content.guard';
export * from './guards/resolve-published-schema.guard';
export * from './guards/resolve-schema.guard';
export * from './guards/schema-must-exist-published.guard';
export * from './guards/schema-must-exist.guard';
export * from './guards/unset-app.guard';
export * from './interceptors/auth.interceptor';

4
src/Squidex/app/shared/module.ts

@ -51,6 +51,8 @@ import {
ResolveContentGuard,
ResolvePublishedSchemaGuard,
ResolveSchemaGuard,
SchemaMustExistGuard,
SchemaMustExistPublishedGuard,
SchemasService,
RulesService,
UIService,
@ -151,6 +153,8 @@ export class SqxSharedModule {
ResolvePublishedSchemaGuard,
ResolveSchemaGuard,
RulesService,
SchemaMustExistGuard,
SchemaMustExistPublishedGuard,
SchemasService,
SchemasState,
UIService,

Loading…
Cancel
Save