Browse Source

Test

pull/345/head
Sebastian Stehle 7 years ago
parent
commit
c6dcce7269
  1. 6
      src/Squidex/app/framework/angular/forms/checkbox-group.component.html
  2. 33
      src/Squidex/app/framework/angular/forms/checkbox-group.component.ts
  3. 18
      src/Squidex/app/framework/angular/forms/code-editor.component.ts
  4. 10
      src/Squidex/app/framework/angular/forms/date-time-editor.component.html
  5. 47
      src/Squidex/app/framework/angular/forms/date-time-editor.component.ts
  6. 30
      src/Squidex/app/framework/angular/forms/iframe-editor.component.ts
  7. 20
      src/Squidex/app/framework/angular/forms/json-editor.component.ts
  8. 3
      src/Squidex/app/framework/angular/forms/slider.component.html
  9. 51
      src/Squidex/app/framework/angular/forms/slider.component.scss
  10. 196
      src/Squidex/app/framework/angular/forms/slider.component.ts
  11. 21
      src/Squidex/app/framework/angular/forms/stars.component.ts
  12. 63
      src/Squidex/app/framework/angular/forms/tag-editor.component.ts
  13. 23
      src/Squidex/app/framework/angular/forms/toggle.component.ts
  14. 67
      src/Squidex/app/framework/angular/stateful.component.ts
  15. 1
      src/Squidex/app/framework/declarations.ts
  16. 3
      src/Squidex/app/framework/module.ts

6
src/Squidex/app/framework/angular/forms/checkbox-group.component.html

@ -1,9 +1,9 @@
<span class="form-check" *ngFor="let value of values">
<input type="checkbox" class="form-check-input" id="{{snapshot.controlId}}{{value}}"
(blur)="blur()"
<input type="checkbox" class="form-check-input" id="{{controlId}}{{value}}"
(blur)="callTouched()"
(change)="check($event.target.checked, value)"
[checked]="isChecked(value)"
[disabled]="snapshot.isDisabled">
<label class="form-check-label" for="{{snapshot.controlId}}{{value}}">{{value}}</label>
<label class="form-check-label" for="{{controlId}}{{value}}">{{value}}</label>
</span>

33
src/Squidex/app/framework/angular/forms/checkbox-group.component.ts

@ -6,11 +6,11 @@
*/
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import {
MathHelper,
StatefulComponent,
StatefulControlComponent,
Types
} from '@app/framework/internal';
@ -20,8 +20,6 @@ export const SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR: any = {
interface State {
checkedValues: string[];
controlId: string;
isDisabled: boolean;
}
@Component({
@ -31,39 +29,22 @@ interface State {
providers: [SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CheckboxGroupComponent extends StatefulComponent<State> implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class CheckboxGroupComponent extends StatefulControlComponent<State, string[]> {
public readonly controlId = MathHelper.guid();
@Input()
public values: string[] = [];
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {
controlId: MathHelper.guid(),
checkedValues: [],
isDisabled: false
checkedValues: []
});
}
public writeValue(obj: any) {
this.next({ checkedValues: Types.isArrayOfString(obj) ? obj.filter(x => this.values.indexOf(x) >= 0) : [] });
}
public setDisabledState(isDisabled: boolean): void {
this.next({ isDisabled });
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
const checkedValues = Types.isArrayOfString(obj) ? obj.filter(x => this.values.indexOf(x) >= 0) : [];
public blur() {
this.callTouched();
this.next({ checkedValues });
}
public check(isChecked: boolean, value: string) {

18
src/Squidex/app/framework/angular/forms/code-editor.component.ts

@ -6,12 +6,12 @@
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import {
PureComponent,
ExternalControlComponent,
ResourceLoaderService,
Types
} from '@app/framework/internal';
@ -29,9 +29,7 @@ export const SQX_JSCRIPT_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_JSCRIPT_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeEditorComponent extends PureComponent implements ControlValueAccessor, AfterViewInit {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class CodeEditorComponent extends ExternalControlComponent<string> implements AfterViewInit {
private valueChanged = new Subject();
private aceEditor: any;
private value: string;
@ -48,8 +46,6 @@ export class CodeEditorComponent extends PureComponent implements ControlValueAc
private readonly resourceLoader: ResourceLoaderService
) {
super(changeDetector);
changeDetector.detach();
}
public writeValue(obj: any) {
@ -68,14 +64,6 @@ export class CodeEditorComponent extends PureComponent implements ControlValueAc
}
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public ngAfterViewInit() {
this.valueChanged.pipe(
debounceTime(500))

10
src/Squidex/app/framework/angular/forms/date-time-editor.component.html

@ -1,19 +1,19 @@
<div>
<div class="form-inline">
<div class="form-group date-group">
<input type="text" class="form-control" [formControl]="dateControl" (blur)="touched()" #dateInput />
<input type="text" class="form-control" [formControl]="dateControl" (blur)="callTouched()" #dateInput />
</div>
<div class="form-group time-group" *ngIf="showTime">
<input type="text" class="form-control" [formControl]="timeControl" (blur)="touched()" />
<input type="text" class="form-control" [formControl]="timeControl" (blur)="callTouched()" />
</div>
<div class="form-group" *ngIf="showTime">
<button class="btn btn-secondary" [disabled]="isDisabled" (click)="writeNow()">Now</button>
<button class="btn btn-secondary" [disabled]="snapshot.isDisabled" (click)="writeNow()">Now</button>
</div>
<div class="form-group" *ngIf="!showTime">
<button class="btn btn-secondary" [disabled]="isDisabled" (click)="writeNow()">Today</button>
<button class="btn btn-secondary" [disabled]="snapshot.isDisabled" (click)="writeNow()">Today</button>
</div>
<div class="form-group" [class.hidden]="!hasValue" *ngIf="!hideClear">
<button class="btn btn-text clear" [disabled]="isDisabled" (click)="reset()">Clear</button>
<button class="btn btn-text clear" [disabled]="snapshot.isDisabled" (click)="reset()">Clear</button>
</div>
</div>
</div>

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

@ -5,12 +5,11 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core';
import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import * as moment from 'moment';
import { Subscription } from 'rxjs';
import { Types } from '@app/framework/internal';
import { StatefulControlComponent, Types } from '@app/framework/internal';
declare module 'pikaday/pikaday';
@ -27,15 +26,11 @@ export const SQX_DATE_TIME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_DATE_TIME_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy, OnInit, AfterViewInit {
private timeSubscription: Subscription;
private dateSubscription: Subscription;
export class DateTimeEditorComponent extends StatefulControlComponent<{}, string | null> implements OnInit, AfterViewInit {
private picker: any;
private timeValue: any | null = null;
private dateValue: any | null = null;
private suppressEvents = false;
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
@Input()
public mode: string;
@ -49,8 +44,6 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
@ViewChild('dateInput')
public dateInput: ElementRef;
public isDisabled = false;
public timeControl = new FormControl();
public dateControl = new FormControl();
@ -62,18 +55,12 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
return !!this.dateValue;
}
constructor(
private readonly changeDetector: ChangeDetectorRef
) {
}
public ngOnDestroy() {
this.dateSubscription.unsubscribe();
this.timeSubscription.unsubscribe();
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {});
}
public ngOnInit() {
this.timeSubscription =
this.observe(
this.timeControl.valueChanges.subscribe(value => {
if (!value || value.length === 0) {
this.timeValue = null;
@ -82,9 +69,9 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
this.updateValue();
});
}));
this.dateSubscription =
this.observe(
this.dateControl.valueChanges.subscribe(value => {
if (!value || value.length === 0) {
this.dateValue = null;
@ -93,7 +80,7 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
this.updateValue();
});
}));
}
public writeValue(obj: any) {
@ -114,7 +101,7 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
public setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
super.setDisabledState(isDisabled);
if (isDisabled) {
this.dateControl.disable({ emitEvent: false });
@ -123,8 +110,6 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
this.dateControl.enable({ emitEvent: false });
this.timeControl.enable({ emitEvent: false });
}
this.changeDetector.markForCheck();
}
public registerOnChange(fn: any) {
@ -144,25 +129,19 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
this.dateValue = this.picker.getMoment();
this.updateValue();
this.touched();
this.changeDetector.markForCheck();
this.callTouched();
}
});
this.updateControls();
}
public touched() {
this.callTouched();
}
public writeNow() {
this.writeValue(new Date().toUTCString());
this.updateControls();
this.updateValue();
this.touched();
this.callTouched();
return false;
}

30
src/Squidex/app/framework/angular/forms/iframe-editor.component.ts

@ -5,11 +5,11 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnInit, Renderer2, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { Types } from '@app/framework/internal';
import { ExternalControlComponent, Types } from '@app/framework/internal';
export const SQX_IFRAME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => IFrameEditorComponent), multi: true
@ -22,10 +22,7 @@ export const SQX_IFRAME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_IFRAME_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class IFrameEditorComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy {
private windowMessageListener: Function;
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class IFrameEditorComponent extends ExternalControlComponent<any> implements AfterViewInit, OnInit {
private value: any;
private isDisabled = false;
private isInitialized = false;
@ -41,14 +38,11 @@ export class IFrameEditorComponent implements ControlValueAccessor, AfterViewIni
public sanitizedUrl: SafeResourceUrl;
constructor(
constructor(changeDetector: ChangeDetectorRef,
private readonly sanitizer: DomSanitizer,
private readonly renderer: Renderer2
) {
}
public ngOnDestroy() {
this.windowMessageListener();
super(changeDetector);
}
public ngAfterViewInit() {
@ -56,7 +50,7 @@ export class IFrameEditorComponent implements ControlValueAccessor, AfterViewIni
}
public ngOnInit(): void {
this.windowMessageListener =
this.observe(
this.renderer.listen('window', 'message', (event: MessageEvent) => {
if (event.source === this.plugin.contentWindow) {
const { type } = event.data;
@ -84,7 +78,7 @@ export class IFrameEditorComponent implements ControlValueAccessor, AfterViewIni
this.callTouched();
}
}
});
}));
}
public writeValue(obj: any) {
@ -102,12 +96,4 @@ export class IFrameEditorComponent implements ControlValueAccessor, AfterViewIni
this.plugin.contentWindow.postMessage({ type: 'disabled', isDisabled: this.isDisabled }, '*');
}
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
}

20
src/Squidex/app/framework/angular/forms/json-editor.component.ts

@ -6,11 +6,11 @@
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { ResourceLoaderService } from '@app/framework/internal';
import { ExternalControlComponent, ResourceLoaderService } from '@app/framework/internal';
declare var ace: any;
@ -25,9 +25,7 @@ export const SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class JsonEditorComponent extends ExternalControlComponent<string> implements AfterViewInit {
private valueChanged = new Subject();
private aceEditor: any;
private value: any;
@ -35,12 +33,12 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit
private isDisabled = false;
@ViewChild('editor')
public editor: ElementRef;
public editor: ElementRef<HTMLDivElement>;
constructor(changeDetector: ChangeDetectorRef,
private readonly resourceLoader: ResourceLoaderService
) {
changeDetector.detach();
super(changeDetector);
}
public writeValue(obj: any) {
@ -65,14 +63,6 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit
}
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public ngAfterViewInit() {
this.valueChanged.pipe(
debounceTime(500))

3
src/Squidex/app/framework/angular/forms/slider.component.html

@ -1,3 +0,0 @@
<div class="slider-bar" #bar (click)="onBarMouseClick($event)" [class.disabled]="isDisabled">
<div class="slider-thumb" #thumb (mousedown)="onThumbMouseDown($event)" [class.disabled]="isDisabled"></div>
</div>

51
src/Squidex/app/framework/angular/forms/slider.component.scss

@ -1,51 +0,0 @@
@import '_mixins';
@import '_vars';
$bar-height: .8rem;
$thumb-size: 1.25rem;
$thumb-margin: ($thumb-size - $bar-height) * .5;
.slider {
&-bar {
& {
@include border-radius($bar-height * .5);
position: relative;
border: 1px solid $color-input-border;
margin-bottom: 1.25rem;
margin-top: .25rem;
margin-right: $thumb-size * .5;
background: $color-dark-foreground;
height: $bar-height;
}
&.disabled {
background: lighten($color-border, 5%);
}
}
&-thumb {
& {
@include border-radius($thumb-size * .5);
position: absolute;
width: $thumb-size;
height: $thumb-size;
border: 1px solid $color-input-border;
background: $color-dark-foreground;
margin-top: -$thumb-margin;
margin-left: -$thumb-size * .5;
}
&.disabled {
background: lighten($color-border, 5%);
}
&.focused {
border-color: $color-theme-blue;
}
}
}
.disabled {
pointer-events: none;
}

196
src/Squidex/app/framework/angular/forms/slider.component.ts

@ -1,196 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, Renderer2, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from '@app/framework/internal';
export const SQX_SLIDER_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderComponent), multi: true
};
@Component({
selector: 'sqx-slider',
styleUrls: ['./slider.component.scss'],
templateUrl: './slider.component.html',
providers: [SQX_SLIDER_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SliderComponent implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
private windowMouseMoveListener: Function | null = null;
private windowMouseUpListener: Function | null = null;
private centerStartOffset = 0;
private lastValue: number;
private value: number;
private isDragging = false;
@ViewChild('bar')
public bar: ElementRef<Element>;
@ViewChild('thumb')
public thumb: ElementRef<Element>;
@Input()
public min = 0;
@Input()
public max = 100;
@Input()
public step = 1;
public isDisabled = false;
constructor(
private readonly changeDetector: ChangeDetectorRef,
private readonly renderer: Renderer2
) {
}
public writeValue(obj: any) {
this.lastValue = this.value = Types.isNumber(obj) ? obj : 0;
this.updateThumbPosition();
this.changeDetector.markForCheck();
}
public setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
this.changeDetector.markForCheck();
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public onBarMouseClick(event: MouseEvent): boolean {
if (this.windowMouseMoveListener) {
return true;
}
const relativeValue = this.getRelativeX(event);
this.value = Math.round((relativeValue * (this.max - this.min) + this.min) / this.step) * this.step;
this.updateThumbPosition();
this.updateTouched();
this.updateValue();
return false;
}
public onThumbMouseDown(event: MouseEvent): boolean {
this.centerStartOffset = event.offsetX - this.thumb.nativeElement.clientWidth * 0.5;
this.windowMouseMoveListener =
this.renderer.listen('window', 'mousemove', (e: MouseEvent) => {
this.onMouseMove(e);
});
this.windowMouseUpListener =
this.renderer.listen('window', 'mouseup', () => {
this.onMouseUp();
});
this.renderer.addClass(this.thumb.nativeElement, 'focused');
this.isDragging = true;
return false;
}
private onMouseMove(event: MouseEvent): boolean {
if (!this.isDragging) {
return true;
}
const relativeValue = this.getRelativeX(event);
this.value = Math.round((relativeValue * (this.max - this.min) + this.min) / this.step) * this.step;
this.updateThumbPosition();
this.updateTouched();
return false;
}
private onMouseUp(): boolean {
this.updateValue();
setTimeout(() => {
this.releaseMouseHandlers();
this.renderer.removeClass(this.thumb.nativeElement, 'focused');
}, 10);
this.centerStartOffset = 0;
this.isDragging = false;
return false;
}
private getRelativeX(event: MouseEvent): number {
const parentOffsetX = this.getParentX(event, this.bar.nativeElement) - this.centerStartOffset;
const parentWidth = this.bar.nativeElement.clientWidth;
const relativeValue = Math.min(1, Math.max(0, (parentOffsetX - this.centerStartOffset) / parentWidth));
return relativeValue;
}
private getParentX(e: any, container: any): number {
const rect = container.getBoundingClientRect();
const x =
!!e.touches ?
e.touches[0].pageX :
e.pageX;
return x - rect.left;
}
private updateTouched() {
this.callTouched();
}
private updateValue() {
if (this.lastValue !== this.value) {
this.lastValue = this.value;
this.callChange(this.value);
}
}
private updateThumbPosition() {
const relativeValue = Math.min(1, Math.max(0, (this.value - this.min) / (this.max - this.min)));
this.renderer.setStyle(this.thumb.nativeElement, 'left', relativeValue * 100 + '%');
}
private releaseMouseHandlers() {
if (this.windowMouseMoveListener) {
this.windowMouseMoveListener();
this.windowMouseMoveListener = null;
}
if (this.windowMouseUpListener) {
this.windowMouseUpListener();
this.windowMouseUpListener = null;
}
this.isDragging = false;
}
}

21
src/Squidex/app/framework/angular/forms/stars.component.ts

@ -8,15 +8,13 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { StatefulComponent, Types } from '@app/framework/internal';
import { StatefulControlComponent, Types } from '@app/framework/internal';
export const SQX_STARS_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StarsComponent), multi: true
};
interface State {
isDisabled: boolean;
stars: number;
starsArray: number[];
@ -30,9 +28,7 @@ interface State {
providers: [SQX_STARS_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class StarsComponent extends StatefulComponent<State> implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class StarsComponent extends StatefulControlComponent<State, number | null> implements ControlValueAccessor {
private maximumStarsValue = 5;
@Input()
@ -58,7 +54,6 @@ export class StarsComponent extends StatefulComponent<State> implements ControlV
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {
isDisabled: false,
stars: -1,
starsArray: [1, 2, 3, 4, 5],
value: 1
@ -71,18 +66,6 @@ export class StarsComponent extends StatefulComponent<State> implements ControlV
this.next({ stars: value, value });
}
public setDisabledState(isDisabled: boolean): void {
this.next({ isDisabled });
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public setPreview(stars: number) {
if (this.snapshot.isDisabled) {
return;

63
src/Squidex/app/framework/angular/forms/tag-editor.component.ts

@ -5,12 +5,11 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subscription } from 'rxjs';
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
import { Types } from '@app/framework/internal';
import { StatefulControlComponent, Types } from '@app/framework/internal';
const KEY_COMMA = 188;
const KEY_DELETE = 8;
@ -75,6 +74,15 @@ const CACHED_SIZES: { [key: string]: number } = {};
let CACHED_FONT: string;
interface State {
hasFocus: boolean;
suggestedItems: string[];
suggestedIndex: number;
items: any[];
}
@Component({
selector: 'sqx-tag-editor',
styleUrls: ['./tag-editor.component.scss'],
@ -82,11 +90,7 @@ let CACHED_FONT: string;
providers: [SQX_TAG_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TagEditorComponent implements AfterViewInit, ControlValueAccessor, OnDestroy, OnInit {
private subscription: Subscription;
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class TagEditorComponent extends StatefulControlComponent<State, any[]> implements AfterViewInit, ControlValueAccessor, OnInit {
@Input()
public converter: Converter = new StringConverter();
@ -115,27 +119,20 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
public inputName = 'tag-editor';
@ViewChild('form')
public formElement: ElementRef<Element>;
public formElement: ElementRef<HTMLElement>;
@ViewChild('input')
public inputElement: ElementRef<HTMLInputElement>;
public hasFocus = false;
public suggestedItems: string[] = [];
public suggestedIndex = 0;
public items: any[] = [];
public addInput = new FormControl();
constructor(
private readonly changeDetector: ChangeDetectorRef
) {
}
public ngOnDestroy() {
this.subscription.unsubscribe();
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {
hasFocus: false,
suggestedItems: [],
suggestedIndex: 0,
items: []
});
}
public ngAfterViewInit() {
@ -149,7 +146,7 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
}
public ngOnInit() {
this.subscription =
this.observe(
this.addInput.valueChanges.pipe(
tap(() => {
this.resetSize();
@ -164,7 +161,7 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
distinctUntilChanged(),
map(query => {
if (Types.isArray(this.suggestions) && query && query.length > 0) {
return this.suggestions.filter(s => s.indexOf(query) >= 0 && this.items.indexOf(s) < 0);
return this.suggestions.filter(s => s.indexOf(query) >= 0 && this.snapshot.items.indexOf(s) < 0);
} else {
return [];
}
@ -172,7 +169,7 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
.subscribe(items => {
this.suggestedIndex = -1;
this.suggestedItems = items || [];
});
}));
}
public writeValue(obj: any) {
@ -189,6 +186,8 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
}
public setDisabledState(isDisabled: boolean): void {
super.setDisabledState(isDisabled);
if (isDisabled) {
this.addInput.disable();
} else {
@ -196,17 +195,9 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
}
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public focus() {
if (this.addInput.enabled) {
this.hasFocus = true;
this.next({ hasFocus: true });
}
}
@ -396,7 +387,7 @@ export class TagEditorComponent implements AfterViewInit, ControlValueAccessor,
}
private updateItems(items: any[]) {
this.items = items;
const items = items;
if (items.length === 0 && this.undefinedWhenEmpty) {
this.callChange(undefined);

23
src/Squidex/app/framework/angular/forms/toggle.component.ts

@ -10,14 +10,13 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from '@app/framework/internal';
import { StatefulComponent } from '../stateful.component';
import { StatefulControlComponent } from '../stateful.component';
export const SQX_TOGGLE_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ToggleComponent), multi: true
};
interface State {
isDisabled: boolean;
isChecked: boolean | null;
}
@ -27,17 +26,13 @@ interface State {
templateUrl: './toggle.component.html',
providers: [SQX_TOGGLE_CONTROL_VALUE_ACCESSOR]
})
export class ToggleComponent extends StatefulComponent<State> implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
export class ToggleComponent extends StatefulControlComponent<State, boolean | null> implements ControlValueAccessor {
@Input()
public threeStates = false;
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {
isChecked: null,
isDisabled: false
isChecked: null
});
}
@ -45,18 +40,6 @@ export class ToggleComponent extends StatefulComponent<State> implements Control
this.next({ isChecked: Types.isBoolean(obj) ? obj : null });
}
public setDisabledState(isDisabled: boolean): void {
this.next({ isDisabled });
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public changeState(event: MouseEvent) {
let { isDisabled, isChecked } = this.snapshot;

67
src/Squidex/app/framework/angular/stateful.component.ts

@ -6,6 +6,7 @@
*/
import { ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
import { Subscription } from 'rxjs';
import { Types } from './../utils/types';
@ -51,8 +52,74 @@ export abstract class StatefulComponent<T> extends State<T> implements OnDestroy
}
}
export interface FormControlState {
isDisabled: boolean;
}
export abstract class StatefulControlComponent<T, TValue> extends StatefulComponent<T & FormControlState> implements ControlValueAccessor {
private fnChanged = (v: any) => { /* NOOP */ };
private fnTouched = () => { /* NOOP */ };
constructor(changeDetector: ChangeDetectorRef, state: T) {
super(changeDetector, { ...state, isDisabled: false });
}
public registerOnChange(fn: any) {
this.fnChanged = fn;
}
public registerOnTouched(fn: any) {
this.fnTouched = fn;
}
public callTouched() {
this.fnTouched();
}
public callChange(value: TValue | null | undefined) {
this.fnChanged(value);
}
public setDisabledState(isDisabled: boolean): void {
this.next(state => { state.isDisabled = isDisabled; });
}
public abstract writeValue(obj: any): void;
}
export abstract class PureComponent extends StatefulComponent<any> {
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, {});
}
}
export abstract class ExternalControlComponent<TValue> extends PureComponent implements ControlValueAccessor {
private fnChanged = (v: any) => { /* NOOP */ };
private fnTouched = () => { /* NOOP */ };
constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector);
changeDetector.detach();
}
public registerOnChange(fn: any) {
this.fnChanged = fn;
}
public registerOnTouched(fn: any) {
this.fnTouched = fn;
}
protected callTouched() {
this.fnTouched();
}
protected callChange(value: TValue) {
this.fnChanged(value);
}
public abstract setDisabledState(isDisabled: boolean): void;
public abstract writeValue(obj: any): void;
}

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

@ -20,7 +20,6 @@ export * from './angular/forms/iframe-editor.component';
export * from './angular/forms/indeterminate-value.directive';
export * from './angular/forms/json-editor.component';
export * from './angular/forms/progress-bar.component';
export * from './angular/forms/slider.component';
export * from './angular/forms/stars.component';
export * from './angular/forms/tag-editor.component';
export * from './angular/forms/toggle.component';

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

@ -73,7 +73,6 @@ import {
ShortcutService,
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SortedDirective,
StarsComponent,
TagEditorComponent,
@ -143,7 +142,6 @@ import {
ShortcutComponent,
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SortedDirective,
StarsComponent,
TagEditorComponent,
@ -208,7 +206,6 @@ import {
ShortcutComponent,
ShortDatePipe,
ShortTimePipe,
SliderComponent,
SortedDirective,
StarsComponent,
TagEditorComponent,

Loading…
Cancel
Save