Browse Source

Dragging improved

pull/65/head
Sebastian Stehle 9 years ago
parent
commit
6dfcde52da
  1. 3
      src/Squidex/app/features/apps/pages/apps-page.component.ts
  2. 6
      src/Squidex/app/features/assets/pages/assets-page.component.scss
  3. 2
      src/Squidex/app/features/assets/pages/assets-page.component.ts
  4. 6
      src/Squidex/app/features/content/pages/content/content-field.component.html
  5. 7
      src/Squidex/app/features/content/pages/content/content-page.component.html
  6. 10
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  7. 6
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  8. 8
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
  9. 2
      src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.ts
  10. 4
      src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts
  11. 4
      src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.ts
  12. 2
      src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts
  13. 4
      src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.ts
  14. 8
      src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts
  15. 4
      src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts
  16. 2
      src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts
  17. 4
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  18. 2
      src/Squidex/app/features/settings/pages/clients/clients-page.component.ts
  19. 4
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts
  20. 2
      src/Squidex/app/features/settings/pages/languages/languages-page.component.ts
  21. 2
      src/Squidex/app/framework/angular/control-errors.component.ts
  22. 2
      src/Squidex/app/framework/angular/date-time-editor.component.ts
  23. 3
      src/Squidex/app/framework/angular/file-drop.directive.ts
  24. 2
      src/Squidex/app/framework/angular/modal-view.directive.ts
  25. 35
      src/Squidex/app/framework/angular/square.directive.ts
  26. 2
      src/Squidex/app/framework/angular/stars.component.ts
  27. 1
      src/Squidex/app/framework/declarations.ts
  28. 3
      src/Squidex/app/framework/module.ts
  29. 4
      src/Squidex/app/framework/services/resource-loader.service.ts
  30. 6
      src/Squidex/app/framework/utils/modal-view.ts
  31. 4
      src/Squidex/app/shared/components/app-form.component.ts
  32. 6
      src/Squidex/app/shared/components/app.component-base.ts
  33. 109
      src/Squidex/app/shared/components/asset.component.html
  34. 5
      src/Squidex/app/shared/components/asset.component.scss
  35. 2
      src/Squidex/app/shared/components/asset.component.ts
  36. 8
      src/Squidex/app/shared/components/assets-editor.component.html
  37. 44
      src/Squidex/app/shared/components/assets-editor.component.scss
  38. 14
      src/Squidex/app/shared/components/assets-editor.component.ts
  39. 2
      src/Squidex/app/shared/components/history.component.ts
  40. 18
      src/Squidex/app/shared/components/pipes.ts
  41. 6
      src/Squidex/app/shared/guards/resolve-app-languages.guard.spec.ts
  42. 4
      src/Squidex/app/shared/guards/resolve-app-languages.guard.ts
  43. 6
      src/Squidex/app/shared/guards/resolve-content.guard.spec.ts
  44. 4
      src/Squidex/app/shared/guards/resolve-content.guard.ts
  45. 8
      src/Squidex/app/shared/guards/resolve-published-schema.guard.spec.ts
  46. 4
      src/Squidex/app/shared/guards/resolve-published-schema.guard.ts
  47. 6
      src/Squidex/app/shared/guards/resolve-schema.guard.spec.ts
  48. 4
      src/Squidex/app/shared/guards/resolve-schema.guard.ts
  49. 8
      src/Squidex/app/shared/services/app-clients.service.ts
  50. 6
      src/Squidex/app/shared/services/app-contributors.service.ts
  51. 8
      src/Squidex/app/shared/services/app-languages.service.ts
  52. 16
      src/Squidex/app/shared/services/assets.service.spec.ts
  53. 12
      src/Squidex/app/shared/services/assets.service.ts
  54. 2
      src/Squidex/app/shared/services/auth.service.ts
  55. 2
      src/Squidex/app/shared/services/contents.service.spec.ts
  56. 14
      src/Squidex/app/shared/services/contents.service.ts
  57. 34
      src/Squidex/app/shared/services/schemas.service.ts
  58. 2
      src/Squidex/app/shared/services/users.service.ts
  59. 4
      src/Squidex/app/theme/_vars.scss
  60. 26
      src/Squidex/package.json

3
src/Squidex/app/features/apps/pages/apps-page.component.ts

@ -24,8 +24,7 @@ import {
export class AppsPageComponent implements OnInit {
public addAppDialog = new ModalView();
public apps =
this.appsStore.apps.map(a => a || []);
public apps = this.appsStore.apps.map(a => a || []);
constructor(
private readonly appsStore: AppsStoreService

6
src/Squidex/app/features/assets/pages/assets-page.component.scss

@ -23,7 +23,7 @@
}
&-info {
color: $color-subtext;
color: darken($color-border, 30%);
}
&-button {
@ -52,8 +52,4 @@
.col-3 {
padding-left: 8px;
padding-right: 8px;
}
.dnd-sortable-drag {
border: 0;
}

2
src/Squidex/app/features/assets/pages/assets-page.component.ts

@ -56,7 +56,7 @@ export class AssetsPageComponent extends AppComponentBase implements OnInit {
private load() {
this.appName()
.switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, this.assertQuery, null, null))
.switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, this.assertQuery))
.subscribe(dtos => {
this.assetsItems = ImmutableArray.of(dtos.items);
this.assetsPager = this.assetsPager.setCount(dtos.total);

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

@ -90,11 +90,7 @@
<sqx-json-editor [formControlName]="language"></sqx-json-editor>
</div>
<div *ngSwitchCase="'Assets'">
<div class="assets-container">
<sqx-assets-editor [formControlName]="language"></sqx-assets-editor>
<a routerLink="assets" class="assets-link">Show Assets</a>
</div>
<sqx-assets-editor [formControlName]="language"></sqx-assets-editor>
</div>
</div>
</div>

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

@ -40,10 +40,13 @@
<sqx-content-field [field]="field" [fieldForm]="contentForm.controls[field.name]" [languages]="languages" [contentFormSubmitted]="contentFormSubmitted"></sqx-content-field>
</div>
</div>
<div class="panel-sidebar" *ngIf="!isNewMode">
<a class="panel-link" routerLink="history" routerLinkActive="active">
<div class="panel-sidebar">
<a class="panel-link" routerLink="history" routerLinkActive="active" *ngIf="!isNewMode">
<i class="icon-time"></i>
</a>
<a class="panel-link" routerLink="assets" routerLinkActive="active">
<i class="icon-media"></i>
</a>
</div>
</div>
</sqx-panel>

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

@ -46,7 +46,7 @@ export class ContentPageComponent extends AppComponentBase implements OnDestroy,
public contentFormSubmitted = false;
public contentForm: FormGroup;
public contentData: any = null;
public contentId: string;
public contentId: string | undefined;
public isNewMode = true;
@ -75,12 +75,12 @@ export class ContentPageComponent extends AppComponentBase implements OnDestroy,
}
});
this.route.parent.data.map(p => p['appLanguages'])
this.route.parent!.data.map(p => p['appLanguages'])
.subscribe((languages: AppLanguageDto[]) => {
this.languages = languages;
});
this.route.parent.data.map(p => p['schema'])
this.route.parent!.data.map(p => p['schema'])
.subscribe((schema: SchemaDetailsDto) => {
this.setupForm(schema);
});
@ -125,9 +125,9 @@ export class ContentPageComponent extends AppComponentBase implements OnDestroy,
});
} else {
this.appName()
.switchMap(app => this.contentsService.putContent(app, this.schema.name, this.contentId, data, this.version))
.switchMap(app => this.contentsService.putContent(app, this.schema.name, this.contentId!, data, this.version))
.subscribe(() => {
this.messageBus.publish(new ContentUpdated(this.contentId, data, this.version.value));
this.messageBus.publish(new ContentUpdated(this.contentId!, data, this.version.value));
this.notifyInfo('Content saved successfully.');
this.enable();

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

@ -53,9 +53,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
public languages: AppLanguageDto[] = [];
public languageSelected: AppLanguageDto;
public get columnWidth() {
return 100 / this.contentFields.length;
}
public columnWidth: number;
constructor(apps: AppsStoreService, notifications: NotificationService,
private readonly authService: AuthService,
@ -154,6 +152,8 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
private loadFields() {
this.contentFields = this.schema.fields.filter(x => x.properties.isListField);
this.columnWidth = 100 / this.contentFields.length;
if (this.contentFields.length === 0 && this.schema.fields.length > 0) {
this.contentFields = [this.schema.fields[0]];
}

8
src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts

@ -221,12 +221,12 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
if (this.addFieldForm.valid) {
this.addFieldForm.disable();
const properties = createProperties(this.addFieldForm.get('type').value);
const properties = createProperties(this.addFieldForm.get('type')!.value);
const requestDto = new AddFieldDto(this.addFieldForm.get('name').value, properties);
const requestDto = new AddFieldDto(this.addFieldForm.get('name')!.value, properties);
const reset = () => {
this.addFieldForm.get('name').reset();
this.addFieldForm.get('name')!.reset();
this.addFieldForm.enable();
this.addFieldFormSubmitted = false;
};
@ -236,7 +236,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
.subscribe(dto => {
const newField =
new FieldDto(parseInt(dto.id, 10),
this.addFieldForm.get('name').value,
this.addFieldForm.get('name')!.value,
false,
false,
properties);

2
src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.ts

@ -30,7 +30,7 @@ export class BooleanValidationComponent implements OnInit {
new FormControl(this.properties.defaultValue));
this.hideDefaultValue =
this.editForm.get('isRequired').valueChanges
this.editForm.get('isRequired')!.valueChanges
.startWith(this.properties.isRequired)
.map(x => !!x);
}

4
src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts

@ -48,12 +48,12 @@ export class DateTimeValidationComponent implements OnInit {
]));
this.hideDefaultValues =
this.editForm.get('isRequired').valueChanges
this.editForm.get('isRequired')!.valueChanges
.startWith(this.properties.isRequired)
.map(x => !!x);
this.hideDefaultValue =
this.editForm.get('calculatedDefaultValue').valueChanges
this.editForm.get('calculatedDefaultValue')!.valueChanges
.startWith(this.properties.calculatedDefaultValue)
.map(x => !!x);
}

4
src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.ts

@ -46,14 +46,14 @@ export class NumberUIComponent implements OnDestroy, OnInit {
new FormControl(this.properties.allowedValues, []));
this.hideAllowedValues =
this.editForm.get('editor').valueChanges
this.editForm.get('editor')!.valueChanges
.startWith(this.properties.editor)
.map(x => !x || x === 'Input' || x === 'Textarea');
this.editorSubscription =
this.hideAllowedValues.subscribe(isSelection => {
if (isSelection) {
this.editForm.get('allowedValues').setValue(undefined);
this.editForm.get('allowedValues')!.setValue(undefined);
}
});
}

2
src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts

@ -36,7 +36,7 @@ export class NumberValidationComponent implements OnInit {
new FormControl(this.properties.defaultValue));
this.hideDefaultValue =
this.editForm.get('isRequired').valueChanges
this.editForm.get('isRequired')!.valueChanges
.startWith(this.properties.isRequired)
.map(x => !!x);
}

4
src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.ts

@ -46,7 +46,7 @@ export class StringUIComponent implements OnDestroy, OnInit {
new FormControl(this.properties.allowedValues));
this.hideAllowedValues =
this.editForm.get('editor').valueChanges
this.editForm.get('editor')!.valueChanges
.startWith(this.properties.editor)
.map(x => !x || x === 'Input' || x === 'TextArea' || x === 'RichText' || x === 'Markdown');
@ -54,7 +54,7 @@ export class StringUIComponent implements OnDestroy, OnInit {
this.hideAllowedValues
.subscribe(isSelection => {
if (isSelection) {
this.editForm.get('allowedValues').setValue(undefined);
this.editForm.get('allowedValues')!.setValue(undefined);
}
});
}

8
src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts

@ -49,19 +49,19 @@ export class StringValidationComponent implements OnDestroy, OnInit {
new FormControl(this.properties.defaultValue));
this.hideDefaultValue =
this.editForm.get('isRequired').valueChanges
this.editForm.get('isRequired')!.valueChanges
.startWith(this.properties.isRequired)
.map(x => !!x);
this.hidePatternMessage =
this.editForm.get('pattern').valueChanges
this.editForm.get('pattern')!.valueChanges
.startWith('')
.map(x => !x || x.trim().length === 0);
this.patternSubscription =
this.editForm.get('pattern').valueChanges.subscribe((value: string) => {
this.editForm.get('pattern')!.valueChanges.subscribe((value: string) => {
if (!value || value.length === 0) {
this.editForm.get('patternMessage').setValue(undefined);
this.editForm.get('patternMessage')!.setValue(undefined);
}
});
}

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

@ -53,7 +53,7 @@ export class SchemaFormComponent {
});
public schemaName =
this.createForm.get('name').valueChanges.map(n => n || FALLBACK_NAME)
this.createForm.get('name')!.valueChanges.map(n => n || FALLBACK_NAME)
.startWith(FALLBACK_NAME);
constructor(
@ -76,7 +76,7 @@ export class SchemaFormComponent {
this.createForm.disable();
const schemaVersion = new Version();
const schemaName = this.createForm.get('name').value;
const schemaName = this.createForm.get('name')!.value;
const requestDto = new CreateSchemaDto(schemaName);

2
src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts

@ -112,7 +112,7 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy,
query = query || this.schemaQuery;
if (query && query.length > 0) {
schemas = schemas.filter(t => t.name.indexOf(query) >= 0);
schemas = schemas.filter(t => t.name.indexOf(query!) >= 0);
}
schemas =

4
src/Squidex/app/features/settings/pages/clients/client.component.ts

@ -73,7 +73,7 @@ export class ClientComponent {
}
public resetForm() {
this.renameForm.get('name').setValue(this.clientName);
this.renameForm.get('name')!.setValue(this.clientName);
}
public cancelRename() {
@ -94,7 +94,7 @@ export class ClientComponent {
public rename() {
try {
const newName = this.renameForm.get('name').value;
const newName = this.renameForm.get('name')!.value;
if (newName !== this.clientName) {
this.renaming.emit(newName);

2
src/Squidex/app/features/settings/pages/clients/clients-page.component.ts

@ -103,7 +103,7 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit {
if (this.addClientForm.valid) {
this.addClientForm.disable();
const requestDto = new CreateAppClientDto(this.addClientForm.get('name').value);
const requestDto = new CreateAppClientDto(this.addClientForm.get('name')!.value);
const reset = () => {
this.addClientFormSubmitted = false;

4
src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts

@ -43,7 +43,7 @@ export class UsersDataSource implements AutocompleteSource {
new AutocompleteItem(
user.displayName,
user.email,
user.pictureUrl,
user.pictureUrl!,
user));
}
}
@ -117,7 +117,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni
}
public assignContributor() {
const newContributor = new AppContributorDto(this.addContributorForm.get('user').value.model.id, 'Editor');
const newContributor = new AppContributorDto(this.addContributorForm.get('user')!.value.model.id, 'Editor');
this.appName()
.switchMap(app => this.appContributorsService.postContributor(app, newContributor, this.version))

2
src/Squidex/app/features/settings/pages/languages/languages-page.component.ts

@ -87,7 +87,7 @@ export class LanguagesPageComponent extends AppComponentBase implements OnInit {
}
public addLanguage() {
const request = new AddAppLanguageDto(this.addLanguageForm.get('language').value.iso2Code);
const request = new AddAppLanguageDto(this.addLanguageForm.get('language')!.value.iso2Code);
this.appName()
.switchMap(app => this.appLanguagesService.postLanguages(app, request, this.version))

2
src/Squidex/app/framework/angular/control-errors.component.ts

@ -55,7 +55,7 @@ export class ControlErrorsComponent implements OnChanges {
return null;
}
if (this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted)) {
if (this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted) && this.control.errors) {
const errors: string[] = [];
for (let key in <any>this.control.errors) {

2
src/Squidex/app/framework/angular/date-time-editor.component.ts

@ -156,7 +156,7 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnInit, Af
}
private updateValue() {
let result: string = null;
let result: string | null = null;
if ((this.dateValue && !this.dateValue.isValid()) || (this.timeValue && !this.timeValue.isValid())) {
result = 'Invalid DateTime';

3
src/Squidex/app/framework/angular/file-drop.directive.ts

@ -22,8 +22,9 @@ export class FileDropDirective {
) {
}
@HostListener('dragend', ['$event'])
@HostListener('dragleave', ['$event'])
public onDragLeave(event: DragDropEvent) {
public onDragEnd(event: DragDropEvent) {
const hasFiles = this.hasFiles(event.dataTransfer.types);
if (hasFiles) {

2
src/Squidex/app/framework/angular/modal-view.directive.ts

@ -14,7 +14,7 @@ import { ModalView } from './../utils/modal-view';
selector: '[sqxModalView]'
})
export class ModalViewDirective implements OnChanges, OnInit, OnDestroy {
private subscription: Subscription;
private subscription: Subscription | null;
private isEnabled = true;
private clickHandler: Function | null;
private renderedView: EmbeddedViewRef<any> | null = null;

35
src/Squidex/app/framework/angular/square.directive.ts

@ -1,35 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Directive, ElementRef, HostListener, OnInit, Renderer } from '@angular/core';
@Directive({
selector: '[sqxSquare]'
})
export class SquareDirective implements OnInit {
constructor(
private readonly element: ElementRef,
private readonly renderer: Renderer
) {
}
public ngOnInit() {
this.resize();
}
@HostListener('resize')
public onResize() {
this.resize();
}
private resize() {
const size = this.element.nativeElement.getBoundingClientRect();
this.renderer.setElementStyle(this.element.nativeElement, 'height', size.width + 'px');
}
}

2
src/Squidex/app/framework/angular/stars.component.ts

@ -84,7 +84,7 @@ export class StarsComponent implements ControlValueAccessor {
return;
}
this.stars = this.value;
this.stars = this.value || 0;
}
public reset() {

1
src/Squidex/app/framework/declarations.ts

@ -33,7 +33,6 @@ export * from './angular/rich-editor.component';
export * from './angular/scroll-active.directive';
export * from './angular/shortcut.component';
export * from './angular/slider.component';
export * from './angular/square.directive';
export * from './angular/stars.component';
export * from './angular/tag-editor.component';
export * from './angular/title.component';

3
src/Squidex/app/framework/module.ts

@ -50,7 +50,6 @@ import {
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SquareDirective,
StarsComponent,
TagEditorComponent,
TitleService,
@ -99,7 +98,6 @@ import {
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SquareDirective,
StarsComponent,
TagEditorComponent,
TitleComponent,
@ -138,7 +136,6 @@ import {
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SquareDirective,
StarsComponent,
TagEditorComponent,
TitleComponent,

4
src/Squidex/app/framework/services/resource-loader.service.ts

@ -52,7 +52,9 @@ export class ResourceLoaderService {
const node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(script, node);
if (node.parentNode) {
node.parentNode.insertBefore(script, node);
}
});
this.cache[key] = result;

6
src/Squidex/app/framework/utils/modal-view.ts

@ -9,16 +9,18 @@ import { BehaviorSubject, Observable } from 'rxjs';
export class ModalView {
private readonly isOpen$: BehaviorSubject<boolean>;
private static openView: ModalView;
private readonly isOpenChanges$: Observable<boolean>;
private static openView: ModalView | null = null;
public get isOpen(): Observable<boolean> {
return this.isOpen$.distinctUntilChanged();
return this.isOpenChanges$;
}
constructor(isOpen = false,
public readonly closeAlways: boolean = false
) {
this.isOpen$ = new BehaviorSubject(isOpen);
this.isOpenChanges$ = this.isOpen$.distinctUntilChanged();
}
public show() {

4
src/Squidex/app/shared/components/app-form.component.ts

@ -43,7 +43,7 @@ export class AppFormComponent {
});
public appName =
this.createForm.get('name').valueChanges.map(n => n || FALLBACK_NAME)
this.createForm.get('name')!.valueChanges.map(n => n || FALLBACK_NAME)
.startWith(FALLBACK_NAME);
constructor(
@ -64,7 +64,7 @@ export class AppFormComponent {
if (this.createForm.valid) {
this.createForm.disable();
const request = new CreateAppDto(this.createForm.get('name').value);
const request = new CreateAppDto(this.createForm.get('name')!.value);
this.appsStore.createApp(request)
.subscribe(dto => {

6
src/Squidex/app/shared/components/app.component-base.ts

@ -12,14 +12,18 @@ import { AppsStoreService, NotificationService } from './../declarations-base';
import { ComponentBase } from './component-base';
export abstract class AppComponentBase extends ComponentBase {
private appName$: Observable<string>;
constructor(notifications: NotificationService,
private readonly appsStore: AppsStoreService
) {
super(notifications);
this.appName$ = this.appsStore.selectedApp.map(a => a!.name).take(1);
}
public appName(): Observable<string> {
return this.appsStore.selectedApp.map(a => a!.name).take(1);
return this.appName$;
}
}

109
src/Squidex/app/shared/components/asset.component.html

@ -1,68 +1,67 @@
<div class="asset">
<div class="card" (sqxFileDrop)="updateFile($event)" sqxSquare dnd-draggable [dragEnabled]="!!asset" [dragData]="asset">
<div class="card-block">
<div class="file-preview" *ngIf="asset && progress == 0" [@fade]>
<span class="file-type" *ngIf="fileType">
{{fileType}}
</span>
<div class="card" (sqxFileDrop)="updateFile($event)" dnd-draggable [dragEnabled]="!!asset" [dragData]="asset">
<div class="card-block">
<div class="file-preview" *ngIf="asset && progress == 0" [@fade]>
<span class="file-type" *ngIf="fileType">
{{fileType}}
</span>
<div *ngIf="asset.isImage" class="file-image">
<img [sqxImageSource]="previewUrl">
</div>
<div *ngIf="!asset.isImage" class="file-icon-container">
<img class="file-icon" [attr.src]="fileIcon">
</div>
<div class="file-overlay">
<div class="file-overlay-background"></div>
<div *ngIf="asset.isImage" class="file-image">
<img [sqxImageSource]="previewUrl">
</div>
<div *ngIf="!asset.isImage" class="file-icon-container">
<img class="file-icon" [attr.src]="fileIcon">
</div>
<a class="file-edit" (click)="renameDialog.show()">
<i class="icon-pencil"></i>
</a>
<a class="file-download" [attr.href]="fileUrl" target="_blank">
<i class="icon-download"></i>
</a>
<div class="file-overlay">
<div class="file-overlay-background"></div>
<a class="file-edit" (click)="renameDialog.show()">
<i class="icon-pencil"></i>
<span *ngIf="!closeMode">
<a class="file-delete" (click)="deleting.emit(asset)">
<i class="icon-delete"></i>
</a>
<a class="file-download" [attr.href]="fileUrl" target="_blank">
<i class="icon-download"></i>
</span>
<span *ngIf="closeMode">
<a class="file-delete" (click)="closing.emit(asset)">
<i class="icon-close"></i>
</a>
</span>
<span *ngIf="!closeMode">
<a class="file-delete" (click)="deleting.emit(asset)">
<i class="icon-delete"></i>
</a>
</span>
<span *ngIf="closeMode">
<a class="file-delete" (click)="closing.emit(asset)">
<i class="icon-close"></i>
</a>
</span>
<span class="file-overlay-type" *ngIf="fileType">
{{fileType}}
</span>
<span class="file-user">
<i class="icon-user"></i> {{asset.lastModifiedBy | userNameRef}}
</span>
<span class="file-modified">
{{asset.lastModified | fromNow}}
</span>
</div>
<span class="file-overlay-type" *ngIf="fileType">
{{fileType}}
</span>
<span class="file-user">
<i class="icon-user"></i> {{asset.lastModifiedBy | userNameRef}}
</span>
<span class="file-modified">
{{asset.lastModified | fromNow}}
</span>
</div>
</div>
<div class="card-footer">
<div class="file-name" [attr.title]="fileName">
{{fileName}}
</div>
<div class="file-info">
{{fileInfo}}
</div>
</div>
<div class="card-footer" dnd-draggable-handle>
<div class="file-name" [attr.title]="fileName">
{{fileName}}
</div>
<div *ngIf="progress > 0">
<sqx-progress-bar class="upload-progress" style="width: 120px; height: 120px" mode="Circle" [value]="progress"></sqx-progress-bar>
<div class="file-info">
{{fileInfo}}
</div>
<div class="drop-overlay">
<div class="drop-overlay-background"></div>
</div>
<span class="drop-overlay-text">Drop to update</span>
</div>
<div class="upload-progress" *ngIf="progress > 0">
<sqx-progress-bar mode="Circle" [value]="progress"></sqx-progress-bar>
</div>
<div class="drop-overlay">
<div class="drop-overlay-background"></div>
<span class="drop-overlay-text">Drop to update</span>
</div>
</div>

5
src/Squidex/app/shared/components/asset.component.scss

@ -9,7 +9,7 @@
@mixin overlay {
& {
@include transition(opacity.4s ease);
@include transition(opacity .4s ease);
@include absolute(0, 0, 0, 0);
@include opacity(0);
color: $color-dark-foreground;
@ -70,6 +70,7 @@
.card {
& {
@include overlay-container;
height: $asset-height;
}
&.drag {
@ -92,7 +93,7 @@
}
.upload-progress {
margin: 60px 70px;
@include absolute(2rem, 2rem, 2rem, 2rem);
}
.file {

2
src/Squidex/app/shared/components/asset.component.ts

@ -109,8 +109,6 @@ export class AssetComponent extends AppComponentBase implements OnInit {
result.pixelWidth,
result.pixelHeight,
result.version);
this.updateAsset(asset);
this.loaded.emit(asset);
} else {
this.progress = result;

8
src/Squidex/app/shared/components/assets-editor.component.html

@ -1,5 +1,11 @@
<div class="assets-container" (sqxFileDrop)="addFiles($event)" dnd-droppable (onDropSuccess)="onAssetDropped($event.dragData)">
<div class="assets-container">
<div class="row">
<div class="col-4 drop-area-container">
<div class="drop-area" dnd-droppable (onDropSuccess)="onAssetDropped($event.dragData)" (sqxFileDrop)="addFiles($event)">
Drop files or assets here to add them.
</div>
</div>
<sqx-asset class="col-4" *ngFor="let file of newAssets" [initFile]="file"
(failed)="onAssetFailed(file)"
(loaded)="onAssetLoaded(file, $event)">

44
src/Squidex/app/shared/components/assets-editor.component.scss

@ -4,29 +4,47 @@
.assets {
&-container {
& {
border: 2px solid $color-input;
background: $color-input;
background: $color-background;
overflow-x: hidden;
overflow-y: auto;
overflow-y: scroll;
padding: 1rem;
padding-bottom: 0;
height: 240px;
height: $asset-height + 2rem;
}
}
}
&.drag {
border-color: darken($color-border, 10%);
border-style: dashed;
cursor: copy;
}
.drop-area {
& {
@include transition(border-color .4s ease);
border: 2px dashed $color-border;
height: $asset-height;
font-size: 1.2rem;
font-weight: normal;
text-align: center;
padding: 3rem 2rem;
color: darken($color-border, 30%);
}
&-container {
padding-bottom: 1rem;
}
&.drag,
&.dnd-drag-over,
&.dnd-drag-enter {
border-color: darken($color-border, 10%);
cursor: copy;
color: darken($color-border, 40%);
}
}
.row {
margin-left: -8px;
margin-right: -8px;
margin-left: -.5rem;
margin-right: -.5rem;
}
.col-4 {
padding-left: 8px;
padding-right: 8px;
padding-left: .5rem;
padding-right: .5rem;
}

14
src/Squidex/app/shared/components/assets-editor.component.ts

@ -48,11 +48,11 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
}
public writeValue(value: any) {
if (!value) {
this.oldAssets = ImmutableArray.empty<AssetDto>();
} else {
this.oldAssets = ImmutableArray.empty<AssetDto>();
if (value) {
this.appName()
.switchMap(app => this.assetsService.getAssets(app, 10000, 0, null, null, value))
.switchMap(app => this.assetsService.getAssets(app, 10000, 0, undefined, undefined, value))
.subscribe(dtos => {
this.oldAssets = ImmutableArray.of(dtos.items);
});
@ -79,13 +79,13 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
public onAssetLoaded(file: File, asset: AssetDto) {
this.newAssets = this.newAssets.remove(file);
this.oldAssets = this.oldAssets.push(asset);
this.oldAssets = this.oldAssets.pushFront(asset);
this.updateValue();
}
public onAssetDropped(asset: AssetDto) {
this.oldAssets = this.oldAssets.push(asset);
this.oldAssets = this.oldAssets.pushFront(asset);
this.updateValue();
}
@ -99,7 +99,7 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
}
private updateValue() {
let ids = this.oldAssets.values.map(x => x.id);
let ids: string[] | null = this.oldAssets.values.map(x => x.id);
if (ids.length === 0) {
ids = null;

2
src/Squidex/app/shared/components/history.component.ts

@ -31,7 +31,7 @@ const REPLACEMENT_TEMP = '$TEMP$';
export class HistoryComponent extends AppComponentBase {
public get channel(): string {
let result = this.route.snapshot.data['channel'];
let params = this.route.parent.snapshot.params;
let params = this.route.parent!.snapshot.params;
for (let key in params) {
if (params.hasOwnProperty(key)) {

18
src/Squidex/app/shared/components/pipes.ts

@ -12,7 +12,7 @@ import { UsersProviderService } from './../declarations-base';
class UserAsyncPipe implements OnDestroy {
private lastUserId: string;
private lastValue: string;
private lastValue: string | null = null;
private subscription: Subscription;
constructor(
@ -27,7 +27,7 @@ class UserAsyncPipe implements OnDestroy {
}
}
protected transformInternal(userId: string, transform: (users: UsersProviderService) => Observable<string>): string {
protected transformInternal(userId: string, transform: (users: UsersProviderService) => Observable<string | null>): string | null {
if (this.lastUserId !== userId) {
this.lastUserId = userId;
@ -55,7 +55,7 @@ export class UserNamePipe extends UserAsyncPipe implements PipeTransform {
super(users, changeDetector);
}
public transform(userId: string, placeholder = 'Me'): string {
public transform(userId: string, placeholder = 'Me'): string | null {
return super.transformInternal(userId, users => users.getUser(userId, placeholder).map(u => u.displayName));
}
}
@ -69,7 +69,7 @@ export class UserNameRefPipe extends UserAsyncPipe implements PipeTransform {
super(users, changeDetector);
}
public transform(userId: string, placeholder = 'Me'): string {
public transform(userId: string, placeholder = 'Me'): string | null {
return super.transformInternal(userId, users => {
const parts = userId.split(':');
@ -95,7 +95,7 @@ export class UserEmailPipe extends UserAsyncPipe implements PipeTransform {
super(users, changeDetector);
}
public transform(userId: string): string {
public transform(userId: string): string | null {
return super.transformInternal(userId, users => users.getUser(userId).map(u => u.email));
}
}
@ -109,14 +109,14 @@ export class UserEmailRefPipe extends UserAsyncPipe implements PipeTransform {
super(users, changeDetector);
}
public transform(userId: string): string {
public transform(userId: string): string | null {
return super.transformInternal(userId, users => {
const parts = userId.split(':');
if (parts[0] === 'subject') {
return users.getUser(parts[1]).map(u => u.email);
} else {
return null;
return Observable.of(null);
}
});
}
@ -131,7 +131,7 @@ export class UserPicturePipe extends UserAsyncPipe implements PipeTransform {
super(users, changeDetector);
}
public transform(userId: string): string {
public transform(userId: string): string | null {
return super.transformInternal(userId, users => users.getUser(userId).map(u => u.pictureUrl));
}
}
@ -145,7 +145,7 @@ export class UserPictureRefPipe extends UserAsyncPipe implements PipeTransform {
super(users, changeDetector);
}
public transform(userId: string): string {
public transform(userId: string): string | null {
return super.transformInternal(userId, users => {
const parts = userId.split(':');

6
src/Squidex/app/shared/guards/resolve-app-languages.guard.spec.ts

@ -33,7 +33,7 @@ describe('ResolveAppLanguagesGuard', () => {
});
it('should navigate to 404 page if languages are not found', (done) => {
appLanguagesService.setup(x => x.getLanguages('my-app', null))
appLanguagesService.setup(x => x.getLanguages('my-app'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
@ -49,7 +49,7 @@ describe('ResolveAppLanguagesGuard', () => {
});
it('should navigate to 404 page if languages loading fails', (done) => {
appLanguagesService.setup(x => x.getLanguages('my-app', null))
appLanguagesService.setup(x => x.getLanguages('my-app'))
.returns(() => Observable.throw(null!));
const router = new RouterMockup();
@ -67,7 +67,7 @@ describe('ResolveAppLanguagesGuard', () => {
it('should return schema if loading succeeded', (done) => {
const languages: AppLanguageDto[] = [];
appLanguagesService.setup(x => x.getLanguages('my-app', null))
appLanguagesService.setup(x => x.getLanguages('my-app'))
.returns(() => Observable.of(languages));
const router = new RouterMockup();

4
src/Squidex/app/shared/guards/resolve-app-languages.guard.ts

@ -26,7 +26,7 @@ export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[]> {
}
const result =
this.appLanguagesService.getLanguages(appName, null).toPromise()
this.appLanguagesService.getLanguages(appName).toPromise()
.then(dto => {
if (!dto) {
this.router.navigate(['/404']);
@ -50,7 +50,7 @@ export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[]> {
while (route) {
result = route.params[name];
if (result) {
if (result || !route.parent) {
break;
}

6
src/Squidex/app/shared/guards/resolve-content.guard.spec.ts

@ -43,7 +43,7 @@ describe('ResolveContentGuard', () => {
});
it('should navigate to 404 page if schema is not found', (done) => {
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123', null))
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
@ -59,7 +59,7 @@ describe('ResolveContentGuard', () => {
});
it('should navigate to 404 page if schema loading fails', (done) => {
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123', null))
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123'))
.returns(() => Observable.throw(null!));
const router = new RouterMockup();
@ -77,7 +77,7 @@ describe('ResolveContentGuard', () => {
it('should return schema if loading succeeded', (done) => {
const schema = {};
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123', null))
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();

4
src/Squidex/app/shared/guards/resolve-content.guard.ts

@ -28,7 +28,7 @@ export class ResolveContentGuard implements Resolve<ContentDto> {
}
const result =
this.contentsService.getContent(appName, schemaName, contentId, null).toPromise()
this.contentsService.getContent(appName, schemaName, contentId).toPromise()
.then(dto => {
if (!dto) {
this.router.navigate(['/404']);
@ -52,7 +52,7 @@ export class ResolveContentGuard implements Resolve<ContentDto> {
while (route) {
result = route.params[name];
if (result) {
if (result || !route.parent) {
break;
}

8
src/Squidex/app/shared/guards/resolve-published-schema.guard.spec.ts

@ -38,7 +38,7 @@ describe('ResolvePublishedSchemaGuard', () => {
});
it('should navigate to 404 page if schema is not found', (done) => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
@ -54,7 +54,7 @@ describe('ResolvePublishedSchemaGuard', () => {
});
it('should navigate to 404 page if schema loading fails', (done) => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.throw(null));
const router = new RouterMockup();
@ -72,7 +72,7 @@ describe('ResolvePublishedSchemaGuard', () => {
it('should navigate to 404 page if schema not published', (done) => {
const schema = { isPublished: false };
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();
@ -90,7 +90,7 @@ describe('ResolvePublishedSchemaGuard', () => {
it('should return schema if loading succeeded', (done) => {
const schema = { isPublished: true };
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();

4
src/Squidex/app/shared/guards/resolve-published-schema.guard.ts

@ -27,7 +27,7 @@ export class ResolvePublishedSchemaGuard implements Resolve<SchemaDetailsDto> {
}
const result =
this.schemasService.getSchema(appName, schemaName, null).toPromise()
this.schemasService.getSchema(appName, schemaName).toPromise()
.then(dto => {
if (!dto || !dto.isPublished) {
this.router.navigate(['/404']);
@ -51,7 +51,7 @@ export class ResolvePublishedSchemaGuard implements Resolve<SchemaDetailsDto> {
while (route) {
result = route.params[name];
if (result) {
if (result || !route.parent) {
break;
}

6
src/Squidex/app/shared/guards/resolve-schema.guard.spec.ts

@ -38,7 +38,7 @@ describe('ResolveSchemaGuard', () => {
});
it('should navigate to 404 page if schema is not found', (done) => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
@ -54,7 +54,7 @@ describe('ResolveSchemaGuard', () => {
});
it('should navigate to 404 page if schema loading fails', (done) => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.throw(null!));
const router = new RouterMockup();
@ -72,7 +72,7 @@ describe('ResolveSchemaGuard', () => {
it('should return schema if loading succeeded', (done) => {
const schema = {};
schemasService.setup(x => x.getSchema('my-app', 'my-schema', null))
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();

4
src/Squidex/app/shared/guards/resolve-schema.guard.ts

@ -27,7 +27,7 @@ export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto> {
}
const result =
this.schemasService.getSchema(appName, schemaName, null).toPromise()
this.schemasService.getSchema(appName, schemaName).toPromise()
.then(dto => {
if (!dto) {
this.router.navigate(['/404']);
@ -51,7 +51,7 @@ export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto> {
while (route) {
result = route.params[name];
if (result) {
if (result || !route.parent) {
break;
}

8
src/Squidex/app/shared/services/app-clients.service.ts

@ -54,7 +54,7 @@ export class AppClientsService {
) {
}
public getClients(appName: string, version: Version): Observable<AppClientDto[]> {
public getClients(appName: string, version?: Version): Observable<AppClientDto[]> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`);
return this.authService.authGet(url, version)
@ -72,7 +72,7 @@ export class AppClientsService {
.catchError('Failed to load clients. Please reload.');
}
public postClient(appName: string, dto: CreateAppClientDto, version: Version): Observable<AppClientDto> {
public postClient(appName: string, dto: CreateAppClientDto, version?: Version): Observable<AppClientDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`);
return this.authService.authPost(url, dto, version)
@ -86,14 +86,14 @@ export class AppClientsService {
.catchError('Failed to add client. Please reload.');
}
public updateClient(appName: string, id: string, dto: UpdateAppClientDto, version: Version): Observable<any> {
public updateClient(appName: string, id: string, dto: UpdateAppClientDto, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients/${id}`);
return this.authService.authPut(url, dto, version)
.catchError('Failed to revoke client. Please reload.');
}
public deleteClient(appName: string, id: string, version: Version): Observable<any> {
public deleteClient(appName: string, id: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients/${id}`);
return this.authService.authDelete(url, version)

6
src/Squidex/app/shared/services/app-contributors.service.ts

@ -29,7 +29,7 @@ export class AppContributorsService {
) {
}
public getContributors(appName: string, version: Version): Observable<AppContributorDto[]> {
public getContributors(appName: string, version?: Version): Observable<AppContributorDto[]> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors`);
return this.authService.authGet(url, version)
@ -46,14 +46,14 @@ export class AppContributorsService {
.catchError('Failed to load contributors. Please reload.');
}
public postContributor(appName: string, dto: AppContributorDto, version: Version): Observable<any> {
public postContributor(appName: string, dto: AppContributorDto, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors`);
return this.authService.authPost(url, dto, version)
.catchError('Failed to add contributors. Please reload.');
}
public deleteContributor(appName: string, contributorId: string, version: Version): Observable<any> {
public deleteContributor(appName: string, contributorId: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors/${contributorId}`);
return this.authService.authDelete(url, version)

8
src/Squidex/app/shared/services/app-languages.service.ts

@ -44,7 +44,7 @@ export class AppLanguagesService {
) {
}
public getLanguages(appName: string, version: Version): Observable<AppLanguageDto[]> {
public getLanguages(appName: string, version?: Version): Observable<AppLanguageDto[]> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages`);
return this.authService.authGet(url, version)
@ -62,7 +62,7 @@ export class AppLanguagesService {
.catchError('Failed to load languages. Please reload.');
}
public postLanguages(appName: string, dto: AddAppLanguageDto, version: Version): Observable<AppLanguageDto> {
public postLanguages(appName: string, dto: AddAppLanguageDto, version?: Version): Observable<AppLanguageDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages`);
return this.authService.authPost(url, dto, version)
@ -76,14 +76,14 @@ export class AppLanguagesService {
.catchError('Failed to add language. Please reload.');
}
public updateLanguage(appName: string, languageCode: string, dto: UpdateAppLanguageDto, version: Version): Observable<any> {
public updateLanguage(appName: string, languageCode: string, dto: UpdateAppLanguageDto, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages/${languageCode}`);
return this.authService.authPut(url, dto, version)
.catchError('Failed to change language. Please reload.');
}
public deleteLanguage(appName: string, languageCode: string, version: Version): Observable<any> {
public deleteLanguage(appName: string, languageCode: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages/${languageCode}`);
return this.authService.authDelete(url, version)

16
src/Squidex/app/shared/services/assets.service.spec.ts

@ -37,7 +37,7 @@ describe('AssetsService', () => {
}
};
progressHttp = Mock.ofInstance(new ProgressHttp(null, null, factory, null));
progressHttp = Mock.ofInstance(new ProgressHttp(null!, null!, factory, null!));
progressHttp.setup(x => x.withUploadProgressListener(It.isAny())).returns(() => <any> progressHttp.object);
authService = Mock.ofType(AuthService);
@ -90,7 +90,7 @@ describe('AssetsService', () => {
let assets: AssetsDto | null = null;
assetsService.getAssets('my-app', 17, 13, null, null, null).subscribe(result => {
assetsService.getAssets('my-app', 17, 13).subscribe(result => {
assets = result;
}).unsubscribe();
@ -151,7 +151,7 @@ describe('AssetsService', () => {
let assets: AssetDto | null = null;
assetsService.getAsset('my-app', '123', null).subscribe(result => {
assetsService.getAsset('my-app', '123').subscribe(result => {
assets = result;
}).unsubscribe();
@ -188,7 +188,7 @@ describe('AssetsService', () => {
let assets: AssetsDto | null = null;
assetsService.getAssets('my-app', 17, 13, 'my-query', null, null).subscribe(result => {
assetsService.getAssets('my-app', 17, 13, 'my-query').subscribe(result => {
assets = result;
}).unsubscribe();
@ -211,7 +211,7 @@ describe('AssetsService', () => {
let assets: AssetsDto | null = null;
assetsService.getAssets('my-app', 17, 13, null, ['text/plain', 'image/png'], null).subscribe(result => {
assetsService.getAssets('my-app', 17, 13, undefined, ['text/plain', 'image/png']).subscribe(result => {
assets = result;
}).unsubscribe();
@ -234,7 +234,7 @@ describe('AssetsService', () => {
let assets: AssetsDto | null = null;
assetsService.getAssets('my-app', 17, 13, null, null, ['12', '23']).subscribe(result => {
assetsService.getAssets('my-app', 17, 13, undefined, undefined, ['12', '23']).subscribe(result => {
assets = result;
}).unsubscribe();
@ -264,7 +264,7 @@ describe('AssetsService', () => {
let asset: AssetCreatedDto | null = null;
assetsService.uploadFile('my-app', null).subscribe(result => {
assetsService.uploadFile('my-app', null!).subscribe(result => {
asset = <AssetCreatedDto>result;
});
@ -303,7 +303,7 @@ describe('AssetsService', () => {
let asset: AssetReplacedDto | null = null;
assetsService.replaceFile('my-app', '123', null, version).subscribe(result => {
assetsService.replaceFile('my-app', '123', null!, version).subscribe(result => {
asset = <AssetReplacedDto>result;
});

12
src/Squidex/app/shared/services/assets.service.ts

@ -89,7 +89,7 @@ export class AssetsService {
) {
}
public getAssets(appName: string, take: number, skip: number, query: string, mimeTypes: string[], ids: string[]): Observable<AssetsDto> {
public getAssets(appName: string, take: number, skip: number, query?: string, mimeTypes?: string[], ids?: string[]): Observable<AssetsDto> {
let queries: string[] = [];
if (mimeTypes && mimeTypes.length > 0) {
@ -142,7 +142,7 @@ export class AssetsService {
const content = new FormData();
const headers = new Headers({
'Authorization': `${this.authService.user.user.token_type} ${this.authService.user.user.access_token}`
'Authorization': `${this.authService.user!.user.token_type} ${this.authService.user!.user.access_token}`
});
content.append('file', file);
@ -173,7 +173,7 @@ export class AssetsService {
});
}
public getAsset(appName: string, id: string, version: Version): Observable<AssetDto> {
public getAsset(appName: string, id: string, version?: Version): Observable<AssetDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`);
return this.authService.authGet(url)
@ -203,7 +203,7 @@ export class AssetsService {
const content = new FormData();
const headers = new Headers({
'Authorization': `${this.authService.user.user.token_type} ${this.authService.user.user.access_token}`
'Authorization': `${this.authService.user!.user.token_type} ${this.authService.user!.user.access_token}`
});
if (version && version.value.length > 0) {
@ -236,14 +236,14 @@ export class AssetsService {
});
}
public putAsset(appName: string, id: string, dto: UpdateAssetDto, version: Version): Observable<any> {
public putAsset(appName: string, id: string, dto: UpdateAssetDto, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`);
return this.authService.authPut(url, dto, version)
.catchError('Failed to delete asset. Please reload.');
}
public deleteAsset(appName: string, id: string, version: Version): Observable<any> {
public deleteAsset(appName: string, id: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`);
return this.authService.authDelete(url, version)

2
src/Squidex/app/shared/services/auth.service.ts

@ -196,7 +196,7 @@ export class AuthService {
private checkResponse(responseStream: Observable<Response>, version?: Version) {
return responseStream
.do((response: Response) => {
if (version && response.status.toString().indexOf('2') === 0) {
if (version && response.status.toString().indexOf('2') === 0 && response.headers) {
const etag = response.headers.get('etag');
if (etag) {

2
src/Squidex/app/shared/services/contents.service.spec.ts

@ -63,7 +63,7 @@ describe('ContentsService', () => {
let contents: ContentsDto | null = null;
contentsService.getContents('my-app', 'my-schema', 17, 13, null).subscribe(result => {
contentsService.getContents('my-app', 'my-schema', 17, 13).subscribe(result => {
contents = result;
}).unsubscribe();

14
src/Squidex/app/shared/services/contents.service.ts

@ -48,7 +48,7 @@ export class ContentsService {
) {
}
public getContents(appName: string, schemaName: string, take: number, skip: number, query: string): Observable<ContentsDto> {
public getContents(appName: string, schemaName: string, take: number, skip: number, query?: string): Observable<ContentsDto> {
let fullQuery = query ? query.trim() : '';
if (fullQuery.length > 0) {
@ -91,7 +91,7 @@ export class ContentsService {
.catchError('Failed to load contents. Please reload.');
}
public getContent(appName: string, schemaName: string, id: string, version: Version): Observable<ContentDto> {
public getContent(appName: string, schemaName: string, id: string, version?: Version): Observable<ContentDto> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}?hidden=true`);
return this.authService.authGet(url, version)
@ -110,7 +110,7 @@ export class ContentsService {
.catchError('Failed to load content. Please reload.');
}
public postContent(appName: string, schemaName: string, dto: any, publish: boolean, version: Version): Observable<ContentDto> {
public postContent(appName: string, schemaName: string, dto: any, publish: boolean, version?: Version): Observable<ContentDto> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}?publish=${publish}`);
return this.authService.authPost(url, dto, version)
@ -129,28 +129,28 @@ export class ContentsService {
.catchError('Failed to create content. Please reload.');
}
public putContent(appName: string, schemaName: string, id: string, dto: any, version: Version): Observable<any> {
public putContent(appName: string, schemaName: string, id: string, dto: any, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}`);
return this.authService.authPut(url, dto, version)
.catchError('Failed to update content. Please reload.');
}
public publishContent(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
public publishContent(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}/publish`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to publish content. Please reload.');
}
public unpublishContent(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
public unpublishContent(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}/unpublish`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to unpublish content. Please reload.');
}
public deleteContent(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
public deleteContent(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}`);
return this.authService.authDelete(url, version)

34
src/Squidex/app/shared/services/schemas.service.ts

@ -113,9 +113,9 @@ export class FieldDto {
export abstract class FieldPropertiesDto {
constructor(
public readonly fieldType: string,
public readonly label: string,
public readonly hints: string,
public readonly placeholder: string,
public readonly label: string | undefined,
public readonly hints: string | undefined,
public readonly placeholder: string | undefined,
public readonly isRequired: boolean,
public readonly isListField: boolean,
public readonly isLocalizable: boolean
@ -275,7 +275,7 @@ export class SchemasService {
.catchError('Failed to load schemas. Please reload.');
}
public getSchema(appName: string, id: string, version: Version): Observable<SchemaDetailsDto> {
public getSchema(appName: string, id: string, version?: Version): Observable<SchemaDetailsDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${id}`);
return this.authService.authGet(url)
@ -311,7 +311,7 @@ export class SchemasService {
.catchError('Failed to load schema. Please reload.');
}
public postSchema(appName: string, dto: CreateSchemaDto, version: Version): Observable<EntityCreatedDto> {
public postSchema(appName: string, dto: CreateSchemaDto, version?: Version): Observable<EntityCreatedDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas`);
return this.authService.authPost(url, dto, version)
@ -322,7 +322,7 @@ export class SchemasService {
.catchError('Failed to create schema. Please reload.');
}
public postField(appName: string, schemaName: string, dto: AddFieldDto, version: Version): Observable<EntityCreatedDto> {
public postField(appName: string, schemaName: string, dto: AddFieldDto, version?: Version): Observable<EntityCreatedDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields`);
return this.authService.authPost(url, dto, version)
@ -333,77 +333,77 @@ export class SchemasService {
.catchError('Failed to add field. Please reload.');
}
public putSchema(appName: string, schemaName: string, dto: UpdateSchemaDto, version: Version): Observable<any> {
public putSchema(appName: string, schemaName: string, dto: UpdateSchemaDto, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}`);
return this.authService.authPut(url, dto, version)
.catchError('Failed to update schema. Please reload.');
}
public putFieldOrdering(appName: string, schemaName: string, dto: number[], version: Version): Observable<any> {
public putFieldOrdering(appName: string, schemaName: string, dto: number[], version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/ordering`);
return this.authService.authPut(url, { fieldIds: dto }, version)
.catchError('Failed to reorder fields. Please reload.');
}
public publishSchema(appName: string, schemaName: string, version: Version): Observable<any> {
public publishSchema(appName: string, schemaName: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/publish`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to publish schema. Please reload.');
}
public unpublishSchema(appName: string, schemaName: string, version: Version): Observable<any> {
public unpublishSchema(appName: string, schemaName: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/unpublish`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to unpublish schema. Please reload.');
}
public putField(appName: string, schemaName: string, fieldId: number, dto: UpdateFieldDto, version: Version): Observable<any> {
public putField(appName: string, schemaName: string, fieldId: number, dto: UpdateFieldDto, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}`);
return this.authService.authPut(url, dto, version)
.catchError('Failed to update field. Please reload.');
}
public enableField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
public enableField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/enable`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to enable field. Please reload.');
}
public disableField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
public disableField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/disable`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to disable field. Please reload.');
}
public showField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
public showField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/show`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to show field. Please reload.');
}
public hideField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
public hideField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/hide`);
return this.authService.authPut(url, {}, version)
.catchError('Failed to hide field. Please reload.');
}
public deleteField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
public deleteField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}`);
return this.authService.authDelete(url, version)
.catchError('Failed to delete field. Please reload.');
}
public deleteSchema(appName: string, schemaName: string, version: Version): Observable<any> {
public deleteSchema(appName: string, schemaName: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}`);
return this.authService.authDelete(url, version)

2
src/Squidex/app/shared/services/users.service.ts

@ -26,7 +26,7 @@ export class UserDto {
public readonly id: string,
public readonly email: string,
public readonly displayName: string,
public readonly pictureUrl: string,
public readonly pictureUrl: string | null,
public readonly isLocked: boolean
) {
}

4
src/Squidex/app/theme/_vars.scss

@ -59,4 +59,6 @@ $size-sidebar-width: 7rem;
$panel-padding: 1.5rem;
$panel-header: 5.4rem;
$panel-sidebar: 3.75rem;
$panel-light-background: #fff;
$panel-light-background: #fff;
$asset-height: 13rem;

26
src/Squidex/package.json

@ -15,15 +15,15 @@
"build:clean": "rimraf wwwroot/build"
},
"dependencies": {
"@angular/animations": "4.0.2",
"@angular/common": "4.0.2",
"@angular/compiler": "4.0.2",
"@angular/core": "4.0.2",
"@angular/forms": "4.0.2",
"@angular/http": "4.0.2",
"@angular/platform-browser": "4.0.2",
"@angular/platform-browser-dynamic": "4.0.2",
"@angular/router": "4.0.2",
"@angular/animations": "4.1.0",
"@angular/common": "4.1.0",
"@angular/compiler": "4.1.0",
"@angular/core": "4.1.0",
"@angular/forms": "4.1.0",
"@angular/http": "4.1.0",
"@angular/platform-browser": "4.1.0",
"@angular/platform-browser-dynamic": "4.1.0",
"@angular/router": "4.1.0",
"angular-progress-http": "0.5.0",
"babel-polyfill": "6.23.0",
"bootstrap": "4.0.0-alpha.6",
@ -36,11 +36,11 @@
"progressbar.js": "1.0.1",
"redoc": "1.14.0",
"rxjs": "5.3.0",
"zone.js": "0.8.8"
"zone.js": "0.8.9"
},
"devDependencies": {
"@angular/compiler-cli": "4.0.2",
"@angular/tsc-wrapped": "4.0.2",
"@angular/compiler-cli": "4.1.0",
"@angular/tsc-wrapped": "4.1.0",
"@ngtools/webpack": "1.3.1",
"@types/core-js": "0.9.35",
"@types/jasmine": "2.5.43",
@ -79,7 +79,7 @@
"tslint": "4.5.1",
"tslint-loader": "3.5.3",
"typemoq": "1.5.0",
"typescript": "2.2.2",
"typescript": "2.3.1",
"underscore": "1.8.3",
"webpack": "2.4.1",
"webpack-dev-server": "2.4.5",

Loading…
Cancel
Save