Browse Source

Text editor.

pull/614/head
Sebastian 5 years ago
parent
commit
5a20fffb02
  1. 1
      backend/i18n/frontend_en.json
  2. 1
      backend/i18n/frontend_it.json
  3. 1
      backend/i18n/frontend_nl.json
  4. 1
      backend/i18n/source/frontend_en.json
  5. 18
      backend/src/Squidex.Infrastructure.MongoDb/MongoDb/DomainIdSerializer.cs
  6. 9
      backend/src/Squidex.Infrastructure.MongoDb/MongoDb/InstantSerializer.cs
  7. 9
      backend/src/Squidex.Infrastructure.MongoDb/MongoDb/RefTokenSerializer.cs
  8. 2
      frontend/app/features/content/shared/forms/field-editor.component.html
  9. 2
      frontend/app/features/dashboard/pages/dashboard-config.component.html
  10. 2
      frontend/app/features/schemas/pages/schema/export/schema-export-form.component.html
  11. 2
      frontend/app/features/schemas/pages/schemas/schema-form.component.html
  12. 1
      frontend/app/framework/angular/forms/editors/json-editor.component.html
  13. 26
      frontend/app/framework/angular/forms/editors/json-editor.component.scss
  14. 146
      frontend/app/framework/angular/forms/editors/json-editor.component.ts
  15. 1
      frontend/app/framework/declarations.ts
  16. 4
      frontend/app/framework/module.ts
  17. 6
      frontend/app/shared/components/assets/asset-dialog.component.html

1
backend/i18n/frontend_en.json

@ -331,6 +331,7 @@
"common.tagsAll": "All tags",
"common.time": "Time",
"common.update": "Update",
"common.upload": "Upload",
"common.url": "URL",
"common.users": "Users",
"common.value": "Value",

1
backend/i18n/frontend_it.json

@ -331,6 +331,7 @@
"common.tagsAll": "Tutti i tag",
"common.time": "Ora",
"common.update": "Aggiorna",
"common.upload": "Upload",
"common.url": "URL",
"common.users": "Utenti",
"common.value": "Valore",

1
backend/i18n/frontend_nl.json

@ -331,6 +331,7 @@
"common.tagsAll": "Alle tags",
"common.time": "Tijd",
"common.update": "Update",
"common.upload": "Upload",
"common.url": "URL",
"common.users": "Gebruikers",
"common.value": "Waarde",

1
backend/i18n/source/frontend_en.json

@ -331,6 +331,7 @@
"common.tagsAll": "All tags",
"common.time": "Time",
"common.update": "Update",
"common.upload": "Upload",
"common.url": "URL",
"common.users": "Users",
"common.value": "Value",

18
backend/src/Squidex.Infrastructure.MongoDb/MongoDb/DomainIdSerializer.cs

@ -6,7 +6,6 @@
// ==========================================================================
using System;
using System.Threading;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
@ -15,20 +14,15 @@ namespace Squidex.Infrastructure.MongoDb
{
public sealed class DomainIdSerializer : SerializerBase<DomainId>, IBsonPolymorphicSerializer, IRepresentationConfigurable<DomainIdSerializer>
{
private static int isRegistered;
public static void Register()
{
if (Interlocked.Increment(ref isRegistered) == 1)
try
{
BsonSerializer.RegisterSerializer(new DomainIdSerializer());
}
catch (BsonSerializationException)
{
try
{
BsonSerializer.RegisterSerializer(new DomainIdSerializer());
}
catch (BsonSerializationException)
{
return;
}
return;
}
}

9
backend/src/Squidex.Infrastructure.MongoDb/MongoDb/InstantSerializer.cs

@ -18,14 +18,7 @@ namespace Squidex.Infrastructure.MongoDb
{
try
{
try
{
BsonSerializer.RegisterSerializer(new InstantSerializer());
}
catch (BsonSerializationException)
{
return;
}
BsonSerializer.RegisterSerializer(new InstantSerializer());
}
catch (BsonSerializationException)
{

9
backend/src/Squidex.Infrastructure.MongoDb/MongoDb/RefTokenSerializer.cs

@ -17,14 +17,7 @@ namespace Squidex.Infrastructure.MongoDb
{
try
{
try
{
BsonSerializer.RegisterSerializer(new RefTokenSerializer());
}
catch (BsonSerializationException)
{
return;
}
BsonSerializer.RegisterSerializer(new RefTokenSerializer());
}
catch (BsonSerializationException)
{

2
frontend/app/features/content/shared/forms/field-editor.component.html

@ -51,7 +51,7 @@
<sqx-geolocation-editor [formControl]="editorControl"></sqx-geolocation-editor>
</ng-container>
<ng-container *ngSwitchCase="'Json'">
<sqx-json-editor height="350" [formControl]="editorControl"></sqx-json-editor>
<sqx-code-editor height="350" [formControl]="editorControl" valueMode="Json"></sqx-code-editor>
</ng-container>
<ng-container *ngSwitchCase="'Number'">
<ng-container [ngSwitch]="field.rawProperties.editor">

2
frontend/app/features/dashboard/pages/dashboard-config.component.html

@ -42,7 +42,7 @@
<ng-container content>
<div class="json-editor">
<sqx-json-editor [noBorder]="true" [(ngModel)]="expertConfig"></sqx-json-editor>
<sqx-code-editor [noBorder]="true" [(ngModel)]="expertConfig" valueMode="Json"></sqx-code-editor>
</div>
</ng-container>

2
frontend/app/features/schemas/pages/schema/export/schema-export-form.component.html

@ -28,6 +28,6 @@
</div>
<div class="inner-main">
<sqx-json-editor [noBorder]="true" formControlName="json"></sqx-json-editor>
<sqx-code-editor [noBorder]="true" formControlName="json" valueMode="Json"></sqx-code-editor>
</div>
</form>

2
frontend/app/features/schemas/pages/schemas/schema-form.component.html

@ -88,7 +88,7 @@
{{ 'common.hide' | sqxTranslate }}
</button>
<sqx-json-editor height="250" *ngIf="showImport" formControlName="importing"></sqx-json-editor>
<sqx-code-editor height="250" *ngIf="showImport" formControlName="importing" valueMode="Json"></sqx-code-editor>
</div>
</ng-container>

1
frontend/app/framework/angular/forms/editors/json-editor.component.html

@ -1 +0,0 @@
<div class="editor" [class.no-border]="noBorder" #editor></div>

26
frontend/app/framework/angular/forms/editors/json-editor.component.scss

@ -1,26 +0,0 @@
// sass-lint:disable class-name-format
$editor-height: 30rem;
:host ::ng-deep {
.ace_editor {
border: 1px solid $color-input;
&.no-border {
border: 0;
}
}
.ace_active-line,
.ace_gutter-active-line {
background: none !important;
}
.ace_gutter-active-line {
background: darken($color-border, 5%) !important;
}
.ace_gutter {
background: $color-border !important;
}
}

146
frontend/app/framework/angular/forms/editors/json-editor.component.ts

@ -1,146 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { ResourceLoaderService, StatefulControlComponent } from '@app/framework/internal';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { FocusComponent } from './../forms-helper';
declare var ace: any;
export const SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => JsonEditorComponent), multi: true
};
@Component({
selector: 'sqx-json-editor',
styleUrls: ['./json-editor.component.scss'],
templateUrl: './json-editor.component.html',
providers: [
SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class JsonEditorComponent extends StatefulControlComponent<{}, string> implements AfterViewInit, FocusComponent {
private valueChanged = new Subject();
private aceEditor: any;
private value: any;
private valueString: string;
@ViewChild('editor', { static: false })
public editor: ElementRef<HTMLDivElement>;
@Input()
public noBorder = false;
@Input()
public height = 0;
constructor(changeDetector: ChangeDetectorRef,
private readonly resourceLoader: ResourceLoaderService
) {
super(changeDetector, {});
}
public ngAfterViewInit() {
this.valueChanged.pipe(
debounceTime(500))
.subscribe(() => {
this.changeValue();
});
if (this.height) {
this.editor.nativeElement.style.height = `${this.height}px`;
}
this.resourceLoader.loadLocalScript('dependencies/ace/ace.js').then(() => {
this.aceEditor = ace.edit(this.editor.nativeElement);
this.aceEditor.getSession().setMode('ace/mode/javascript');
this.aceEditor.setReadOnly(this.snapshot.isDisabled);
this.aceEditor.setFontSize(14);
this.setValue(this.value);
this.aceEditor.on('blur', () => {
this.changeValue();
this.callTouched();
});
this.aceEditor.on('change', () => {
this.valueChanged.next();
});
this.detach();
});
}
public writeValue(obj: any) {
this.value = obj;
try {
this.valueString = JSON.stringify(obj);
} catch (e) {
this.valueString = '';
}
if (this.aceEditor) {
this.setValue(obj);
}
}
public setDisabledState(isDisabled: boolean): void {
super.setDisabledState(isDisabled);
if (this.aceEditor) {
this.aceEditor.setReadOnly(isDisabled);
}
}
public focus() {
if (this.aceEditor) {
this.aceEditor.focus();
}
}
private changeValue() {
const isValid = this.aceEditor.getSession().getAnnotations().length === 0;
let newValue: any = null;
if (isValid) {
try {
newValue = JSON.parse(this.aceEditor.getValue());
} catch (e) {
newValue = null;
}
}
const newValueString = JSON.stringify(newValue);
if (this.valueString !== newValueString) {
this.callChange(newValue);
}
this.value = newValue;
this.valueString = newValueString;
}
private setValue(value: any) {
if (value) {
const jsonString = JSON.stringify(value, undefined, 4);
this.aceEditor.setValue(jsonString);
} else {
this.aceEditor.setValue('');
}
this.aceEditor.clearSelection();
}
}

1
frontend/app/framework/declarations.ts

@ -19,7 +19,6 @@ export * from './angular/forms/editors/color-picker.component';
export * from './angular/forms/editors/date-time-editor.component';
export * from './angular/forms/editors/dropdown.component';
export * from './angular/forms/editors/iframe-editor.component';
export * from './angular/forms/editors/json-editor.component';
export * from './angular/forms/editors/localized-input.component';
export * from './angular/forms/editors/stars.component';
export * from './angular/forms/editors/tag-editor.component';

4
frontend/app/framework/module.ts

@ -12,7 +12,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ColorPickerModule } from 'ngx-color-picker';
import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterceptor, CanDeactivateGuard, CheckboxGroupComponent, ClipboardService, CodeComponent, CodeEditorComponent, ColorPickerComponent, ConfirmClickDirective, ControlErrorsComponent, CopyDirective, DarkenPipe, DatePipe, DateTimeEditorComponent, DayOfWeekPipe, DayPipe, DialogRendererComponent, DialogService, DisplayNamePipe, DropdownComponent, DurationPipe, EditableTitleComponent, ExternalLinkDirective, FileDropDirective, FileSizePipe, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, FromNowPipe, FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, IFrameEditorComponent, ImageSourceDirective, IndeterminateValueDirective, ISODatePipe, JsonEditorComponent, KeysPipe, KNumberPipe, LanguageSelectorComponent, LightenPipe, ListViewComponent, LoadingInterceptor, LoadingService, LocalizedInputComponent, LocalStoreService, MarkdownInlinePipe, MarkdownPipe, MessageBus, ModalDialogComponent, ModalDirective, ModalPlacementDirective, MoneyPipe, MonthPipe, OnboardingService, OnboardingTooltipComponent, PagerComponent, PanelComponent, PanelContainerDirective, ParentLinkDirective, PopupLinkDirective, ProgressBarComponent, ResizedDirective, ResizeService, ResourceLoaderService, RootViewComponent, SafeHtmlPipe, SafeUrlPipe, ScrollActiveDirective, ShortcutComponent, ShortcutService, ShortDatePipe, ShortTimePipe, StarsComponent, StatusIconComponent, StopClickDirective, SyncScollingDirective, SyncWidthDirective, TabRouterlinkDirective, TagEditorComponent, TemplateWrapperDirective, TempService, TitleComponent, TitleService, ToggleComponent, TooltipDirective, TransformInputDirective, TranslatePipe, VideoPlayerComponent } from './declarations';
import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterceptor, CanDeactivateGuard, CheckboxGroupComponent, ClipboardService, CodeComponent, CodeEditorComponent, ColorPickerComponent, ConfirmClickDirective, ControlErrorsComponent, CopyDirective, DarkenPipe, DatePipe, DateTimeEditorComponent, DayOfWeekPipe, DayPipe, DialogRendererComponent, DialogService, DisplayNamePipe, DropdownComponent, DurationPipe, EditableTitleComponent, ExternalLinkDirective, FileDropDirective, FileSizePipe, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, FromNowPipe, FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, IFrameEditorComponent, ImageSourceDirective, IndeterminateValueDirective, ISODatePipe, KeysPipe, KNumberPipe, LanguageSelectorComponent, LightenPipe, ListViewComponent, LoadingInterceptor, LoadingService, LocalizedInputComponent, LocalStoreService, MarkdownInlinePipe, MarkdownPipe, MessageBus, ModalDialogComponent, ModalDirective, ModalPlacementDirective, MoneyPipe, MonthPipe, OnboardingService, OnboardingTooltipComponent, PagerComponent, PanelComponent, PanelContainerDirective, ParentLinkDirective, PopupLinkDirective, ProgressBarComponent, ResizedDirective, ResizeService, ResourceLoaderService, RootViewComponent, SafeHtmlPipe, SafeUrlPipe, ScrollActiveDirective, ShortcutComponent, ShortcutService, ShortDatePipe, ShortTimePipe, StarsComponent, StatusIconComponent, StopClickDirective, SyncScollingDirective, SyncWidthDirective, TabRouterlinkDirective, TagEditorComponent, TemplateWrapperDirective, TempService, TitleComponent, TitleService, ToggleComponent, TooltipDirective, TransformInputDirective, TranslatePipe, VideoPlayerComponent } from './declarations';
@NgModule({
imports: [
@ -56,7 +56,6 @@ import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterc
ImageSourceDirective,
IndeterminateValueDirective,
ISODatePipe,
JsonEditorComponent,
KeysPipe,
KNumberPipe,
LanguageSelectorComponent,
@ -137,7 +136,6 @@ import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterc
ImageSourceDirective,
IndeterminateValueDirective,
ISODatePipe,
JsonEditorComponent,
KeysPipe,
KNumberPipe,
LanguageSelectorComponent,

6
frontend/app/shared/components/assets/asset-dialog.component.html

@ -42,7 +42,7 @@
</ng-container>
<ng-container *ngSwitchCase="1">
<button type="button" class="btn btn-primary ml-auto mr-4" (click)="cropImage()" [class.invisible]="!isUploadable" [disabled]="progress > 0">
{{ 'common.save' | sqxTranslate }}
{{ 'common.upload' | sqxTranslate }}
</button>
</ng-container>
<ng-container *ngSwitchCase="2">
@ -51,8 +51,8 @@
</button>
</ng-container>
<ng-container *ngSwitchCase="3">
<button type="button" class="btn btn-primary ml-auto mr-4" (click)="saveText()" [class.invisible]="!isEditable">
{{ 'common.save' | sqxTranslate }}
<button type="button" class="btn btn-primary ml-auto mr-4" (click)="saveText()" [class.invisible]="!isUploadable">
{{ 'common.upload' | sqxTranslate }}
</button>
</ng-container>
</ng-container>

Loading…
Cancel
Save