Browse Source

Update schema view.

pull/363/head
Sebastian Stehle 7 years ago
parent
commit
692081ad26
  1. 73
      src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs
  2. 4
      src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
  3. 10
      src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs
  4. 9
      src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  5. 10
      src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs
  6. 18
      src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDetailsDto.cs
  7. 24
      src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs
  8. 43
      src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemasDto.cs
  9. 4
      src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs
  10. 6
      src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs
  11. 19
      src/Squidex/app/features/schemas/pages/schema/field.component.html
  12. 25
      src/Squidex/app/features/schemas/pages/schema/field.component.ts
  13. 15
      src/Squidex/app/features/schemas/pages/schema/forms/field-form.component.ts
  14. 2
      src/Squidex/app/features/schemas/pages/schema/schema-edit-form.component.html
  15. 13
      src/Squidex/app/features/schemas/pages/schema/schema-edit-form.component.ts
  16. 11
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
  17. 5
      src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.html
  18. 17
      src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts
  19. 2
      src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.html
  20. 13
      src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.ts
  21. 4
      src/Squidex/app/shared/services/backups.service.ts
  22. 4
      src/Squidex/app/shared/services/plans.service.ts

73
src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs

@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas
switch (command) switch (command)
{ {
case AddField addField: case AddField addField:
return UpdateAsync(addField, c => return UpdateReturnAsync(addField, async c =>
{ {
GuardSchemaField.CanAdd(Snapshot.SchemaDef, c); GuardSchemaField.CanAdd(Snapshot.SchemaDef, c);
@ -65,135 +65,167 @@ namespace Squidex.Domain.Apps.Entities.Schemas
id = ((IArrayField)Snapshot.SchemaDef.FieldsById[c.ParentFieldId.Value]).FieldsByName[c.Name].Id; id = ((IArrayField)Snapshot.SchemaDef.FieldsById[c.ParentFieldId.Value]).FieldsByName[c.Name].Id;
} }
return EntityCreatedResult.Create(id, Version); return await GetRawStateAsync();
}); });
case CreateSchema createSchema: case CreateSchema createSchema:
return CreateAsync(createSchema, async c => return CreateReturnAsync(createSchema, async c =>
{ {
await GuardSchema.CanCreate(c, appProvider); await GuardSchema.CanCreate(c, appProvider);
Create(c); Create(c);
return await GetRawStateAsync();
}); });
case SynchronizeSchema synchronizeSchema: case SynchronizeSchema synchronizeSchema:
return UpdateAsync(synchronizeSchema, c => return UpdateReturnAsync(synchronizeSchema, async c =>
{ {
GuardSchema.CanSynchronize(c); GuardSchema.CanSynchronize(c);
Synchronize(c); Synchronize(c);
return await GetRawStateAsync();
}); });
case DeleteField deleteField: case DeleteField deleteField:
return UpdateAsync(deleteField, c => return UpdateReturnAsync(deleteField, async c =>
{ {
GuardSchemaField.CanDelete(Snapshot.SchemaDef, deleteField); GuardSchemaField.CanDelete(Snapshot.SchemaDef, deleteField);
DeleteField(c); DeleteField(c);
return await GetRawStateAsync();
}); });
case LockField lockField: case LockField lockField:
return UpdateAsync(lockField, c => return UpdateReturnAsync(lockField, async c =>
{ {
GuardSchemaField.CanLock(Snapshot.SchemaDef, lockField); GuardSchemaField.CanLock(Snapshot.SchemaDef, lockField);
LockField(c); LockField(c);
return await GetRawStateAsync();
}); });
case HideField hideField: case HideField hideField:
return UpdateAsync(hideField, c => return UpdateReturnAsync(hideField, async c =>
{ {
GuardSchemaField.CanHide(Snapshot.SchemaDef, c); GuardSchemaField.CanHide(Snapshot.SchemaDef, c);
HideField(c); HideField(c);
return await GetRawStateAsync();
}); });
case ShowField showField: case ShowField showField:
return UpdateAsync(showField, c => return UpdateReturnAsync(showField, async c =>
{ {
GuardSchemaField.CanShow(Snapshot.SchemaDef, c); GuardSchemaField.CanShow(Snapshot.SchemaDef, c);
ShowField(c); ShowField(c);
return await GetRawStateAsync();
}); });
case DisableField disableField: case DisableField disableField:
return UpdateAsync(disableField, c => return UpdateReturnAsync(disableField, async c =>
{ {
GuardSchemaField.CanDisable(Snapshot.SchemaDef, c); GuardSchemaField.CanDisable(Snapshot.SchemaDef, c);
DisableField(c); DisableField(c);
return await GetRawStateAsync();
}); });
case EnableField enableField: case EnableField enableField:
return UpdateAsync(enableField, c => return UpdateReturnAsync(enableField, async c =>
{ {
GuardSchemaField.CanEnable(Snapshot.SchemaDef, c); GuardSchemaField.CanEnable(Snapshot.SchemaDef, c);
EnableField(c); EnableField(c);
return await GetRawStateAsync();
}); });
case UpdateField updateField: case UpdateField updateField:
return UpdateAsync(updateField, c => return UpdateReturnAsync(updateField, async c =>
{ {
GuardSchemaField.CanUpdate(Snapshot.SchemaDef, c); GuardSchemaField.CanUpdate(Snapshot.SchemaDef, c);
UpdateField(c); UpdateField(c);
return await GetRawStateAsync();
}); });
case ReorderFields reorderFields: case ReorderFields reorderFields:
return UpdateAsync(reorderFields, c => return UpdateReturnAsync(reorderFields, async c =>
{ {
GuardSchema.CanReorder(Snapshot.SchemaDef, c); GuardSchema.CanReorder(Snapshot.SchemaDef, c);
Reorder(c); Reorder(c);
return await GetRawStateAsync();
}); });
case UpdateSchema updateSchema: case UpdateSchema updateSchema:
return UpdateAsync(updateSchema, c => return UpdateReturnAsync(updateSchema, async c =>
{ {
GuardSchema.CanUpdate(Snapshot.SchemaDef, c); GuardSchema.CanUpdate(Snapshot.SchemaDef, c);
Update(c); Update(c);
return await GetRawStateAsync();
}); });
case PublishSchema publishSchema: case PublishSchema publishSchema:
return UpdateAsync(publishSchema, c => return UpdateReturnAsync(publishSchema, async c =>
{ {
GuardSchema.CanPublish(Snapshot.SchemaDef, c); GuardSchema.CanPublish(Snapshot.SchemaDef, c);
Publish(c); Publish(c);
return await GetRawStateAsync();
}); });
case UnpublishSchema unpublishSchema: case UnpublishSchema unpublishSchema:
return UpdateAsync(unpublishSchema, c => return UpdateReturnAsync(unpublishSchema, async c =>
{ {
GuardSchema.CanUnpublish(Snapshot.SchemaDef, c); GuardSchema.CanUnpublish(Snapshot.SchemaDef, c);
Unpublish(c); Unpublish(c);
return await GetRawStateAsync();
}); });
case ConfigureScripts configureScripts: case ConfigureScripts configureScripts:
return UpdateAsync(configureScripts, c => return UpdateReturnAsync(configureScripts, async c =>
{ {
GuardSchema.CanConfigureScripts(Snapshot.SchemaDef, c); GuardSchema.CanConfigureScripts(Snapshot.SchemaDef, c);
ConfigureScripts(c); ConfigureScripts(c);
return await GetRawStateAsync();
}); });
case ChangeCategory changeCategory: case ChangeCategory changeCategory:
return UpdateAsync(changeCategory, c => return UpdateReturnAsync(changeCategory, async c =>
{ {
GuardSchema.CanChangeCategory(Snapshot.SchemaDef, c); GuardSchema.CanChangeCategory(Snapshot.SchemaDef, c);
ChangeCategory(c); ChangeCategory(c);
return await GetRawStateAsync();
}); });
case ConfigurePreviewUrls configurePreviewUrls: case ConfigurePreviewUrls configurePreviewUrls:
return UpdateAsync(configurePreviewUrls, c => return UpdateReturnAsync(configurePreviewUrls, async c =>
{ {
GuardSchema.CanConfigurePreviewUrls(c); GuardSchema.CanConfigurePreviewUrls(c);
ConfigurePreviewUrls(c); ConfigurePreviewUrls(c);
return await GetRawStateAsync();
}); });
case DeleteSchema deleteSchema: case DeleteSchema deleteSchema:
@ -381,6 +413,11 @@ namespace Squidex.Domain.Apps.Entities.Schemas
} }
} }
public Task<ISchemaEntity> GetRawStateAsync()
{
return Task.FromResult<ISchemaEntity>(Snapshot);
}
public Task<J<ISchemaEntity>> GetStateAsync() public Task<J<ISchemaEntity>> GetStateAsync()
{ {
return J.AsTask<ISchemaEntity>(Snapshot); return J.AsTask<ISchemaEntity>(Snapshot);

4
src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs

@ -109,10 +109,10 @@ namespace Squidex.Areas.Api.Controllers.Assets
if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys) if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
{ {
Response.Headers["Surrogate-Key"] = response.Items.ToSurrogateKeys(); Response.Headers["Surrogate-Key"] = response.ToSurrogateKeys();
} }
Response.Headers[HeaderNames.ETag] = response.Items.ToManyEtag(response.Total); Response.Headers[HeaderNames.ETag] = response.ToEtag();
return Ok(response); return Ok(response);
} }

10
src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs

@ -27,6 +27,16 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models
/// </summary> /// </summary>
public long Total { get; set; } public long Total { get; set; }
public string ToEtag()
{
return Items.ToManyEtag(Total);
}
public string ToSurrogateKeys()
{
return Items.ToSurrogateKeys();
}
public static AssetsDto FromAssets(IResultList<IAssetEntity> assets, ApiController controller, string app) public static AssetsDto FromAssets(IResultList<IAssetEntity> assets, ApiController controller, string app)
{ {
var response = new AssetsDto var response = new AssetsDto

9
src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs

@ -6,7 +6,6 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -132,10 +131,10 @@ namespace Squidex.Areas.Api.Controllers.Contents
if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys) if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
{ {
Response.Headers["Surrogate-Key"] = response.Items.ToSurrogateKeys(); Response.Headers["Surrogate-Key"] = response.ToSurrogateKeys();
} }
Response.Headers[HeaderNames.ETag] = response.Items.ToManyEtag(); Response.Headers[HeaderNames.ETag] = response.ToEtag();
return Ok(response); return Ok(response);
} }
@ -168,10 +167,10 @@ namespace Squidex.Areas.Api.Controllers.Contents
if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys) if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
{ {
Response.Headers["Surrogate-Key"] = response.Items.ToSurrogateKeys(); Response.Headers["Surrogate-Key"] = response.ToSurrogateKeys();
} }
Response.Headers[HeaderNames.ETag] = response.Items.ToManyEtag(response.Total); Response.Headers[HeaderNames.ETag] = response.ToEtag();
return Ok(response); return Ok(response);
} }

10
src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs

@ -26,6 +26,16 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models
/// </summary> /// </summary>
public ContentDto[] Items { get; set; } public ContentDto[] Items { get; set; }
public string ToEtag()
{
return Items.ToManyEtag(Total);
}
public string ToSurrogateKeys()
{
return Items.ToSurrogateKeys();
}
public static ContentsDto FromContents(IList<IContentEntity> contents, QueryContext context, ApiController controller, string app) public static ContentsDto FromContents(IList<IContentEntity> contents, QueryContext context, ApiController controller, string app)
{ {
var result = new ContentsDto var result = new ContentsDto

18
src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDetailsDto.cs

@ -37,19 +37,19 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models
public static SchemaDetailsDto FromSchemaWithDetails(ISchemaEntity schema, ApiController controller, string app) public static SchemaDetailsDto FromSchemaWithDetails(ISchemaEntity schema, ApiController controller, string app)
{ {
var response = new SchemaDetailsDto(); var result = new SchemaDetailsDto();
SimpleMapper.Map(schema, response); SimpleMapper.Map(schema, result);
SimpleMapper.Map(schema.SchemaDef, response); SimpleMapper.Map(schema.SchemaDef, result);
SimpleMapper.Map(schema.SchemaDef.Scripts, response.Scripts); SimpleMapper.Map(schema.SchemaDef.Scripts, result.Scripts);
SimpleMapper.Map(schema.SchemaDef.Properties, response.Properties); SimpleMapper.Map(schema.SchemaDef.Properties, result.Properties);
if (schema.SchemaDef.PreviewUrls.Count > 0) if (schema.SchemaDef.PreviewUrls.Count > 0)
{ {
response.PreviewUrls = new Dictionary<string, string>(schema.SchemaDef.PreviewUrls); result.PreviewUrls = new Dictionary<string, string>(schema.SchemaDef.PreviewUrls);
} }
response.Fields = new List<FieldDto>(); result.Fields = new List<FieldDto>();
foreach (var field in schema.SchemaDef.Fields) foreach (var field in schema.SchemaDef.Fields)
{ {
@ -82,10 +82,10 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models
} }
} }
response.Fields.Add(fieldDto); result.Fields.Add(fieldDto);
} }
return CreateLinks(response, controller, app); return (SchemaDetailsDto)result.CreateLinks(controller, app);
} }
} }
} }

24
src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs

@ -40,7 +40,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models
/// The schema properties. /// The schema properties.
/// </summary> /// </summary>
[Required] [Required]
public SchemaPropertiesDto Properties { get; set; } public SchemaPropertiesDto Properties { get; set; } = new SchemaPropertiesDto();
/// <summary> /// <summary>
/// Indicates if the schema is a singleton. /// Indicates if the schema is a singleton.
@ -81,27 +81,27 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models
public static SchemaDto FromSchema(ISchemaEntity schema, ApiController controller, string app) public static SchemaDto FromSchema(ISchemaEntity schema, ApiController controller, string app)
{ {
var response = new SchemaDto { Properties = new SchemaPropertiesDto() }; var result = new SchemaDto();
SimpleMapper.Map(schema, response); SimpleMapper.Map(schema, result);
SimpleMapper.Map(schema.SchemaDef, response); SimpleMapper.Map(schema.SchemaDef, result);
SimpleMapper.Map(schema.SchemaDef.Properties, response.Properties); SimpleMapper.Map(schema.SchemaDef.Properties, result.Properties);
return CreateLinks(response, controller, app); return result.CreateLinks(controller, app);
} }
protected static T CreateLinks<T>(T response, ApiController controller, string app) where T : SchemaDto protected virtual SchemaDto CreateLinks(ApiController controller, string app)
{ {
var values = new { app, name = response.Name }; var values = new { app, name = Name };
response.AddSelfLink(controller.Url<SchemasController>(x => nameof(x.GetSchema), values)); AddSelfLink(controller.Url<SchemasController>(x => nameof(x.GetSchema), values));
if (controller.HasPermission(Permissions.AppContentsRead, app, response.Name)) if (controller.HasPermission(Permissions.AppContentsRead, app, Name))
{ {
response.AddGetLink("contents", controller.Url<ContentsController>(x => nameof(x.GetContents), values)); AddGetLink("contents", controller.Url<ContentsController>(x => nameof(x.GetContents), values));
} }
return response; return this;
} }
} }
} }

43
src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemasDto.cs

@ -0,0 +1,43 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using System.Linq;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Web;
namespace Squidex.Areas.Api.Controllers.Schemas.Models
{
public sealed class SchemasDto : Resource
{
/// <summary>
/// The schemas.
/// </summary>
public SchemaDto[] Items { get; set; }
public string ToEtag()
{
return Items.ToManyEtag();
}
public static SchemasDto FromSchemas(IList<ISchemaEntity> schemas, ApiController controller, string app)
{
var result = new SchemasDto
{
Items = schemas.Select(x => SchemaDto.FromSchema(x, controller, app)).ToArray()
};
return result.CreateLinks(controller, app);
}
private SchemasDto CreateLinks(ApiController controller, string app)
{
return this;
}
}
}

4
src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs

@ -541,8 +541,8 @@ namespace Squidex.Areas.Api.Controllers.Schemas
{ {
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var response = context.Result<ISchemaEntity>(); var result = context.Result<ISchemaEntity>();
var response = SchemaDetailsDto.FromSchemaWithDetails(response, this, app); var response = SchemaDetailsDto.FromSchemaWithDetails(result, this, app);
return response; return response;
} }

6
src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs

@ -44,16 +44,16 @@ namespace Squidex.Areas.Api.Controllers.Schemas
/// </returns> /// </returns>
[HttpGet] [HttpGet]
[Route("apps/{app}/schemas/")] [Route("apps/{app}/schemas/")]
[ProducesResponseType(typeof(SchemaDto[]), 200)] [ProducesResponseType(typeof(SchemasDto), 200)]
[ApiPermission(Permissions.AppCommon)] [ApiPermission(Permissions.AppCommon)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetSchemas(string app) public async Task<IActionResult> GetSchemas(string app)
{ {
var schemas = await appProvider.GetSchemasAsync(AppId); var schemas = await appProvider.GetSchemasAsync(AppId);
var response = schemas.ToArray(x => SchemaDto.FromSchema(x, this, app)); var response = SchemasDto.FromSchemas(schemas, this, app);
Response.Headers[HeaderNames.ETag] = response.ToManyEtag(); Response.Headers[HeaderNames.ETag] = response.ToEtag();
return Ok(response); return Ok(response);
} }

19
src/Squidex/app/features/schemas/pages/schema/field.component.html

@ -20,7 +20,7 @@
</div> </div>
<div class="col col-options"> <div class="col col-options">
<div class="float-right"> <div class="float-right">
<button type="button" class="btn btn-secondary table-items-edit-button" [class.active]="editing" (click)="toggleEditing()"> <button type="button" class="btn btn-secondary table-items-edit-button" [class.active]="isEditing" (click)="toggleEditing()">
<i class="icon-settings"></i> <i class="icon-settings"></i>
</button> </button>
@ -30,21 +30,21 @@
</button> </button>
<div class="dropdown-menu" *sqxModalView="dropdown;closeAlways:true" [sqxModalTarget]="optionsButton" @fade> <div class="dropdown-menu" *sqxModalView="dropdown;closeAlways:true" [sqxModalTarget]="optionsButton" @fade>
<ng-container *ngIf="field.properties.isContentField"> <ng-container *ngIf="field.properties.isContentField">
<a class="dropdown-item" (click)="enableField()" *ngIf="field.isDisabled"> <a class="dropdown-item" (click)="enableField()" *ngIf="field | sqxHasLink:'enable'">
Enable in UI Enable in UI
</a> </a>
<a class="dropdown-item" (click)="disableField()" *ngIf="!field.isDisabled"> <a class="dropdown-item" (click)="disableField()" *ngIf="field | sqxHasLink:'disable'">
Disable in UI Disable in UI
</a> </a>
<a class="dropdown-item" (click)="hideField()" *ngIf="!field.isHidden && !field.isLocked"> <a class="dropdown-item" (click)="hideField()" *ngIf="field | sqxHasLink:'hide'">
Hide in API Hide in API
</a> </a>
<a class="dropdown-item" (click)="showField()" *ngIf="field.isHidden && !field.isLocked"> <a class="dropdown-item" (click)="showField()" *ngIf="field | sqxHasLink:'show'">
Show in API Show in API
</a> </a>
</ng-container> </ng-container>
<ng-container *ngIf="!field.isLocked"> <ng-container *ngIf="field | sqxHasLink:'lock'">
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" <a class="dropdown-item"
@ -53,10 +53,13 @@
confirmText="Do you really want to lock the field? Locked fields cannot be deleted or changed anymore."> confirmText="Do you really want to lock the field? Locked fields cannot be deleted or changed anymore.">
Lock and prevent changes Lock and prevent changes
</a> </a>
</ng-container>
<ng-container>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item dropdown-item-delete" <a class="dropdown-item dropdown-item-delete"
[class.disabled]="field | sqxHasNoLink:'delete'"
(sqxConfirmClick)="deleteField()" (sqxConfirmClick)="deleteField()"
confirmTitle="Delete field" confirmTitle="Delete field"
confirmText="Do you really want to delete the field?"> confirmText="Do you really want to delete the field?">
@ -70,7 +73,7 @@
</div> </div>
</div> </div>
<div class="table-items-row-details" *ngIf="editing"> <div class="table-items-row-details" *ngIf="isEditing">
<form [formGroup]="editForm.form" (ngSubmit)="save()"> <form [formGroup]="editForm.form" (ngSubmit)="save()">
<sqx-field-form <sqx-field-form
(cancel)="toggleEditing()" (cancel)="toggleEditing()"
@ -95,7 +98,7 @@
</div> </div>
</div> </div>
<div class="nested-field nested-field-add"> <div class="nested-field nested-field-add" *ngIf="isEditable">
<span class="nested-field-line-h"></span> <span class="nested-field-line-h"></span>
<button type="button" class="btn btn-success btn-sm" (click)="addFieldDialog.show()"> <button type="button" class="btn btn-success btn-sm" (click)="addFieldDialog.show()">

25
src/Squidex/app/features/schemas/pages/schema/field.component.ts

@ -13,6 +13,7 @@ import {
DialogModel, DialogModel,
EditFieldForm, EditFieldForm,
fadeAnimation, fadeAnimation,
hasAnyLink,
ImmutableArray, ImmutableArray,
ModalModel, ModalModel,
NestedFieldDto, NestedFieldDto,
@ -45,7 +46,9 @@ export class FieldComponent implements OnChanges {
public dropdown = new ModalModel(); public dropdown = new ModalModel();
public editing = false; public isEditing = false;
public isEditable = false;
public editForm = new EditFieldForm(this.formBuilder); public editForm = new EditFieldForm(this.formBuilder);
public addFieldDialog = new DialogModel(); public addFieldDialog = new DialogModel();
@ -58,18 +61,16 @@ export class FieldComponent implements OnChanges {
public ngOnChanges(changes: SimpleChanges) { public ngOnChanges(changes: SimpleChanges) {
if (changes['field']) { if (changes['field']) {
this.editForm.load(this.field.properties); this.isEditable = hasAnyLink(this.field, 'update');
if (this.field.isLocked) { this.editForm.load(this.field.properties);
this.editForm.form.disable();
}
} }
} }
public toggleEditing() { public toggleEditing() {
this.editing = !this.editing; this.isEditing = !this.isEditing;
if (this.editing) { if (this.isEditing) {
this.editForm.load(this.field.properties); this.editForm.load(this.field.properties);
} }
} }
@ -102,11 +103,11 @@ export class FieldComponent implements OnChanges {
this.schemasState.lockField(this.schema, this.field); this.schemasState.lockField(this.schema, this.field);
} }
public trackByField(index: number, field: NestedFieldDto) { public save() {
return field.fieldId + this.schema.id; if (!this.isEditable) {
return;
} }
public save() {
const value = this.editForm.submit(); const value = this.editForm.submit();
if (value) { if (value) {
@ -120,5 +121,9 @@ export class FieldComponent implements OnChanges {
}); });
} }
} }
public trackByField(index: number, field: NestedFieldDto) {
return field.fieldId + this.schema.id;
}
} }

15
src/Squidex/app/features/schemas/pages/schema/forms/field-form.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
import { Component, EventEmitter, Input, Output } from '@angular/core'; import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { import {
@ -32,7 +32,7 @@ import {
<div class="float-right" *ngIf="showButtons"> <div class="float-right" *ngIf="showButtons">
<button [disabled]="field.isLocked" type="reset" class="btn btn-secondary" (click)="cancel.emit()">Cancel</button> <button [disabled]="field.isLocked" type="reset" class="btn btn-secondary" (click)="cancel.emit()">Cancel</button>
<button [disabled]="field.isLocked" type="submit" class="btn btn-primary ml-1">Save</button> <button [disabled]="field.isLocked" type="submit" class="btn btn-primary ml-1" *ngIf="isEditable">Save</button>
</div> </div>
</div> </div>
@ -49,10 +49,13 @@ import {
</div> </div>
` `
}) })
export class FieldFormComponent { export class FieldFormComponent implements AfterViewInit {
@Input() @Input()
public showButtons: boolean; public showButtons: boolean;
@Input()
public isEditable: boolean;
@Input() @Input()
public editForm: FormGroup; public editForm: FormGroup;
@ -70,6 +73,12 @@ export class FieldFormComponent {
public selectedTab = 0; public selectedTab = 0;
public ngAfterViewInit() {
if (!this.isEditable) {
this.editForm.disable();
}
}
public selectTab(tab: number) { public selectTab(tab: number) {
this.selectedTab = tab; this.selectedTab = tab;
} }

2
src/Squidex/app/features/schemas/pages/schema/schema-edit-form.component.html

@ -30,7 +30,7 @@
<ng-container footer> <ng-container footer>
<button type="reset" class="float-left btn btn-secondary" (click)="emitComplete()">Cancel</button> <button type="reset" class="float-left btn btn-secondary" (click)="emitComplete()">Cancel</button>
<button type="submit" class="float-right btn btn-primary">Save</button> <button type="submit" class="float-right btn btn-primary" *ngIf="isEditable">Save</button>
</ng-container> </ng-container>
</sqx-modal-dialog> </sqx-modal-dialog>
</form> </form>

13
src/Squidex/app/features/schemas/pages/schema/schema-edit-form.component.ts

@ -10,6 +10,7 @@ import { FormBuilder } from '@angular/forms';
import { import {
EditSchemaForm, EditSchemaForm,
hasAnyLink,
SchemaDetailsDto, SchemaDetailsDto,
SchemasState SchemasState
} from '@app/shared'; } from '@app/shared';
@ -28,6 +29,8 @@ export class SchemaEditFormComponent implements OnInit {
public editForm = new EditSchemaForm(this.formBuilder); public editForm = new EditSchemaForm(this.formBuilder);
public isEditable = false;
constructor( constructor(
private readonly formBuilder: FormBuilder, private readonly formBuilder: FormBuilder,
private readonly schemasState: SchemasState private readonly schemasState: SchemasState
@ -35,7 +38,13 @@ export class SchemaEditFormComponent implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.isEditable = hasAnyLink(this.schema, 'update');
this.editForm.load(this.schema.properties); this.editForm.load(this.schema.properties);
if (!this.isEditable) {
this.editForm.form.disable();
}
} }
public emitComplete() { public emitComplete() {
@ -43,6 +52,10 @@ export class SchemaEditFormComponent implements OnInit {
} }
public saveSchema() { public saveSchema() {
if (!this.isEditable) {
return;
}
const value = this.editForm.submit(); const value = this.editForm.submit();
if (value) { if (value) {

11
src/Squidex/app/features/schemas/pages/schema/schema-page.component.html

@ -11,10 +11,10 @@
</button> </button>
<div class="btn-group mr-1" #buttonPublish> <div class="btn-group mr-1" #buttonPublish>
<button type="button" class="btn btn-publishing btn-toggle" [class.btn-success]="schema.isPublished" [disabled]="schema.isPublished" (click)="publish()"> <button type="button" class="btn btn-publishing btn-toggle" [class.btn-success]="schema.isPublished" [disabled]="schema | sqxHasNoLink:'publish'" (click)="publish()">
Published Published
</button> </button>
<button type="button" class="btn btn-publishing btn-toggle" [class.btn-danger]="!schema.isPublished" [disabled]="!schema.isPublished" (click)="unpublish()"> <button type="button" class="btn btn-publishing btn-toggle" [class.btn-danger]="!schema.isPublished" [disabled]="schema | sqxHasNoLink:'unpublish'" (click)="unpublish()">
Unpublished Unpublished
</button> </button>
</div> </div>
@ -37,6 +37,7 @@
Clone Clone
</a> </a>
<ng-container *ngIf="schema | sqxHasLink:'delete'">
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item dropdown-item-delete" <a class="dropdown-item dropdown-item-delete"
@ -45,6 +46,7 @@
confirmText="Do you really want to delete the schema?"> confirmText="Do you really want to delete the schema?">
Delete Delete
</a> </a>
</ng-container>
</div> </div>
</div> </div>
@ -61,13 +63,14 @@
<div class="table-items-row table-items-row-empty" *ngIf="schema && schema.fields.length === 0"> <div class="table-items-row table-items-row-empty" *ngIf="schema && schema.fields.length === 0">
No field created yet. No field created yet.
<button type="button" class="btn btn-success btn-sm ml-2" (click)="addFieldDialog.show()"> <button type="button" class="btn btn-success btn-sm ml-2" (click)="addFieldDialog.show()" *ngIf="schemasState.links | async | sqxHasLink:'addField'">
<i class="icon icon-plus"></i> Add Field <i class="icon icon-plus"></i> Add Field
</button> </button>
</div> </div>
<ng-container *ngIf="patternsState.patterns | async; let patterns"> <ng-container *ngIf="patternsState.patterns | async; let patterns">
<div class="schemas" <div class="schemas"
[disabled]="schema | sqxHasNoLink:'update'"
[sqxSortModel]="schema.fields" [sqxSortModel]="schema.fields"
(sqxSort)="sortFields($event)"> (sqxSort)="sortFields($event)">
<div *ngFor="let field of schema.fields; trackBy: trackByField.bind(this)"> <div *ngFor="let field of schema.fields; trackBy: trackByField.bind(this)">
@ -75,7 +78,7 @@
</div> </div>
</div> </div>
<button type="button" class="btn btn-success field-button" (click)="addFieldDialog.show()"> <button type="button" class="btn btn-success field-button" (click)="addFieldDialog.show()" *ngIf="schemasState.links | async | sqxHasLink:'addField'">
<i class="icon icon-plus field-button-icon"></i> <div class="field-button-text">Add Field</div> <i class="icon icon-plus field-button-icon"></i> <div class="field-button-text">Add Field</div>
</button> </button>
</ng-container> </ng-container>

5
src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.html

@ -29,6 +29,7 @@
<div class="col-auto col-options"> <div class="col-auto col-options">
<button type="button" class="btn btn-text-danger" <button type="button" class="btn btn-text-danger"
[disabled]="!isEditable"
(sqxConfirmClick)="editForm.remove(i)" (sqxConfirmClick)="editForm.remove(i)"
confirmTitle="Remove url" confirmTitle="Remove url"
confirmText="Do you really want to remove this url?"> confirmText="Do you really want to remove this url?">
@ -37,7 +38,7 @@
</div> </div>
</div> </div>
<div class="form-group row no-gutters" [formGroup]="addForm.form"> <div class="form-group row no-gutters" [formGroup]="addForm.form" *ngIf="isEditable">
<div class="col col-name pr-1"> <div class="col col-name pr-1">
<sqx-control-errors for="name" [submitted]="addForm.submitted | async"></sqx-control-errors> <sqx-control-errors for="name" [submitted]="addForm.submitted | async"></sqx-control-errors>
@ -65,7 +66,7 @@
<ng-container footer> <ng-container footer>
<button type="reset" class="float-left btn btn-secondary" (click)="emitComplete()" [disabled]="editForm.submitted | async">Cancel</button> <button type="reset" class="float-left btn btn-secondary" (click)="emitComplete()" [disabled]="editForm.submitted | async">Cancel</button>
<button type="submit" class="float-right btn btn-primary">Save</button> <button type="submit" class="float-right btn btn-primary" *ngIf="isEditable">Save</button>
</ng-container> </ng-container>
</sqx-modal-dialog> </sqx-modal-dialog>
</form> </form>

17
src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts

@ -11,6 +11,7 @@ import { FormBuilder } from '@angular/forms';
import { import {
AddPreviewUrlForm, AddPreviewUrlForm,
ConfigurePreviewUrlsForm, ConfigurePreviewUrlsForm,
hasAnyLink,
SchemaDetailsDto, SchemaDetailsDto,
SchemasState SchemasState
} from '@app/shared'; } from '@app/shared';
@ -31,6 +32,8 @@ export class SchemaPreviewUrlsFormComponent implements OnInit {
public editForm = new ConfigurePreviewUrlsForm(this.formBuilder); public editForm = new ConfigurePreviewUrlsForm(this.formBuilder);
public isEditable = false;
constructor( constructor(
private readonly formBuilder: FormBuilder, private readonly formBuilder: FormBuilder,
private readonly schemasState: SchemasState private readonly schemasState: SchemasState
@ -38,7 +41,13 @@ export class SchemaPreviewUrlsFormComponent implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.isEditable = hasAnyLink(this.schema, 'update');
this.editForm.load(this.schema.previewUrls); this.editForm.load(this.schema.previewUrls);
if (!this.isEditable) {
return;
}
} }
public emitComplete() { public emitComplete() {
@ -50,6 +59,10 @@ export class SchemaPreviewUrlsFormComponent implements OnInit {
} }
public add() { public add() {
if (!this.isEditable) {
return;
}
const value = this.addForm.submit(); const value = this.addForm.submit();
if (value) { if (value) {
@ -60,6 +73,10 @@ export class SchemaPreviewUrlsFormComponent implements OnInit {
} }
public saveSchema() { public saveSchema() {
if (!this.isEditable) {
return;
}
const value = this.editForm.submit(); const value = this.editForm.submit();
if (value) { if (value) {

2
src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.html

@ -24,7 +24,7 @@
<ng-container footer> <ng-container footer>
<button type="reset" class="float-left btn btn-secondary" (click)="emitComplete()" [disabled]="editForm.submitted | async">Cancel</button> <button type="reset" class="float-left btn btn-secondary" (click)="emitComplete()" [disabled]="editForm.submitted | async">Cancel</button>
<button type="submit" class="float-right btn btn-primary">Save</button> <button type="submit" class="float-right btn btn-primary" *ngIf="isEditable">Save</button>
</ng-container> </ng-container>
</sqx-modal-dialog> </sqx-modal-dialog>
</form> </form>

13
src/Squidex/app/features/schemas/pages/schema/schema-scripts-form.component.ts

@ -10,6 +10,7 @@ import { FormBuilder } from '@angular/forms';
import { import {
EditScriptsForm, EditScriptsForm,
hasAnyLink,
SchemaDetailsDto, SchemaDetailsDto,
SchemasState SchemasState
} from '@app/shared'; } from '@app/shared';
@ -30,6 +31,8 @@ export class SchemaScriptsFormComponent implements OnInit {
public editForm = new EditScriptsForm(this.formBuilder); public editForm = new EditScriptsForm(this.formBuilder);
public isEditable = false;
constructor( constructor(
private readonly formBuilder: FormBuilder, private readonly formBuilder: FormBuilder,
private readonly schemasState: SchemasState private readonly schemasState: SchemasState
@ -37,7 +40,13 @@ export class SchemaScriptsFormComponent implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.isEditable = hasAnyLink(this.schema, 'update');
this.editForm.load(this.schema.scripts); this.editForm.load(this.schema.scripts);
if (!this.isEditable) {
this.editForm.form.disable();
}
} }
public emitComplete() { public emitComplete() {
@ -49,6 +58,10 @@ export class SchemaScriptsFormComponent implements OnInit {
} }
public saveSchema() { public saveSchema() {
if (!this.isEditable) {
return;
}
const value = this.editForm.submit(); const value = this.editForm.submit();
if (value) { if (value) {

4
src/Squidex/app/shared/services/backups.service.ts

@ -14,7 +14,6 @@ import {
AnalyticsService, AnalyticsService,
ApiUrlConfig, ApiUrlConfig,
DateTime, DateTime,
Model,
pretifyError, pretifyError,
Resource, Resource,
ResourceLinks, ResourceLinks,
@ -41,7 +40,7 @@ export class BackupDto {
} }
} }
export class RestoreDto extends Model<BackupDto> { export class RestoreDto {
constructor( constructor(
public readonly url: string, public readonly url: string,
public readonly started: DateTime, public readonly started: DateTime,
@ -49,7 +48,6 @@ export class RestoreDto extends Model<BackupDto> {
public readonly status: string, public readonly status: string,
public readonly log: string[] public readonly log: string[]
) { ) {
super();
} }
} }

4
src/Squidex/app/shared/services/plans.service.ts

@ -15,7 +15,6 @@ import {
ApiUrlConfig, ApiUrlConfig,
HTTP, HTTP,
mapVersioned, mapVersioned,
Model,
pretifyError, pretifyError,
Version, Version,
Versioned Versioned
@ -28,7 +27,7 @@ export type PlansDto = Versioned<{
readonly plans: PlanDto[] readonly plans: PlanDto[]
}>; }>;
export class PlanDto extends Model<PlanDto> { export class PlanDto {
constructor( constructor(
public readonly id: string, public readonly id: string,
public readonly name: string, public readonly name: string,
@ -39,7 +38,6 @@ export class PlanDto extends Model<PlanDto> {
public readonly maxAssetSize: number, public readonly maxAssetSize: number,
public readonly maxContributors: number public readonly maxContributors: number
) { ) {
super();
} }
} }

Loading…
Cancel
Save