Browse Source

Update editor.

pull/1039/head
Sebastian 3 years ago
parent
commit
8f149db852
  1. 14
      backend/src/Squidex/Areas/IdentityServer/Config/IdentityServerServices.cs
  2. 2
      backend/src/Squidex/wwwroot/editor/squidex-editor.css
  3. 224
      backend/src/Squidex/wwwroot/editor/squidex-editor.js
  4. 7
      frontend/src/app/declarations.d.ts
  5. 6
      frontend/src/app/shared/components/forms/rich-editor.component.html
  6. 30
      frontend/src/app/shared/components/forms/rich-editor.component.ts

14
backend/src/Squidex/Areas/IdentityServer/Config/IdentityServerServices.cs

@ -81,12 +81,6 @@ public static class IdentityServerServices
})
.AddServer(builder =>
{
builder.AddEventHandler<ValidateTokenRequestContext>(builder =>
{
builder.UseSingletonHandler<TestHandler>()
.SetOrder(int.MinValue);
});
builder.AddEventHandler<ProcessSignInContext>(builder =>
{
builder.UseSingletonHandler<AlwaysAddScopeHandler>()
@ -177,11 +171,3 @@ public static class IdentityServerServices
endpointUris.Add(uri);
}
}
public sealed class TestHandler : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
public ValueTask HandleAsync(ValidateTokenRequestContext context)
{
return default;
}
}

2
backend/src/Squidex/wwwroot/editor/squidex-editor.css

@ -1 +1 @@
.remirror-theme{width:100%}.remirror-theme{position:relative}.remirror-theme *{box-sizing:border-box}.remirror-editor{min-height:300px!important;max-height:500px}.MuiStack-root>.MuiBox-root{margin-right:5px}.MuiBox-root>.MuiButtonBase-root{border-color:#dedfe3!important;border-radius:0}.MuiBox-root>.MuiButtonBase-root{border-left-width:0!important}.MuiBox-root>.MuiBox-root:first-child>.MuiButtonBase-root{border-left-width:1px!important}.MuiStack-root>.MuiBox-root>.MuiButtonBase-root:first-child{border-left-width:1px!important}.MuiButtonBase-root.Mui-selected:hover{background-color:#3284f4!important}.remirror-editor-wrapper{padding-top:0!important}.custom-icon path{fill:#0000008a}.remirror-theme div.ProseMirror{border:1px solid #dedfe3!important;border-radius:0!important;box-shadow:none!important}.MuiTooltip-popper>div{background-color:#1a2129;border-radius:0;font-size:85%;font-weight:400;padding:.5rem}.MuiMenu-paper{transform:none!important}.squidex-editor-disabled{pointer-events:none}.squidex-editor-menu{border:1px solid #dedfe3;border-bottom:0;padding:5px}.squidex-editor-counter{border:1px solid #dedfe3;border-top:0;font-size:85%;font-weight:400;opacity:.8;padding:4px 10px 4px 4px;text-align:right}.squidex-editor-image-view{border:1px solid #dedfe3;border-radius:0;display:inline-block;margin-top:15px;margin-bottom:15px;overflow:hidden}.squidex-editor-image-view .squidex-editor-button{bottom:10px;left:10px;position:absolute}.squidex-editor-image-element{display:block;max-width:400px;max-height:400px}.squidex-editor-image-info{left:10px;top:10px;position:absolute;background-color:#3284f4;color:#fff;font-size:85%;font-weight:400;padding:2px 6px}.squidex-editor-content-link{align-items:center;border-radius:2px;border:1px solid #dedfe3;padding:10px;display:flex;flex-direction:row;flex-wrap:nowrap;margin-top:10px;margin-bottom:10px}.squidex-editor-content-schema{display:block;overflow-x:hidden;overflow-y:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;min-width:0;width:auto;border-right:1px solid #c2c4cc;color:#8b8f9d;flex-shrink:0;padding-left:10px;padding-right:10px;width:200px}.squidex-editor-content-name{display:block;overflow-x:hidden;overflow-y:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;min-width:0;width:auto;padding-left:10px;padding-right:0}.squidex-editor-html{margin-bottom:10px;margin-top:10px;position:relative}.squidex-editor-html-label{left:6px;top:0;position:absolute;color:#8b8f9d;font-size:85%;font-weight:400}.squidex-editor-html textarea{font-family:monospace;padding:30px 20px 20px}.squidex-editor-button{background-color:#fff;border-radius:0;border:1px solid #dedfe3;bottom:10px;font-size:85%;font-weight:400;line-height:1;padding:6px 12px}.squidex-editor-button:hover{background-color:#f5f5f5}.squidex-editor-input{border:1px solid #dedfe3;border-radius:0;box-sizing:border-box;height:30px;margin-left:0;margin-right:5px;outline:none;padding:6px 12px}.squidex-editor-input:active{border-color:#3284f4}.squidex-editor-floating{border:1px solid #dedfe3}.squidex-editor-floating .MuiBox-root{margin-right:0!important}.squidex-editor-floating .MuiButtonBase-root{height:30px}.squidex-editor-modal-wrapper,.squidex-editor-modal-backdrop{bottom:0;left:0;right:0;top:0;position:absolute}.squidex-editor-modal-backdrop{background-color:#00000003}.squidex-editor-modal-window{left:50%;top:50%;background-color:#fff;border:0;border-radius:.25rem;box-sizing:border-box;box-shadow:0 3px 16px #0003;margin-top:-50px;margin-left:-150px;position:absolute;width:350px}.squidex-editor-modal-body{display:flex;flex-direction:row;flex-grow:1;padding-top:0!important}.squidex-editor-modal-body,.squidex-editor-modal-title{padding:15px}.squidex-editor-modal-title{font-size:85%}.squidex-editor-modal-window input{flex-grow:1}.b:before{content:"<a>";font-family:monospace;font-size:90%}.b:after{content:"</a>";font-family:monospace;font-size:90%}
.remirror-theme{width:100%}.remirror-theme{position:relative}.remirror-theme *{box-sizing:border-box}.remirror-editor{min-height:300px!important;max-height:500px}.MuiStack-root>.MuiBox-root{margin-right:5px}.MuiBox-root>.MuiButtonBase-root{border-color:#dedfe3!important;border-radius:0}.MuiBox-root>.MuiButtonBase-root{border-left-width:0!important}.MuiBox-root>.MuiBox-root:first-child>.MuiButtonBase-root{border-left-width:1px!important}.MuiStack-root>.MuiBox-root>.MuiButtonBase-root:first-child{border-left-width:1px!important}.MuiButtonBase-root.Mui-selected:hover{background-color:#3284f4!important}.remirror-editor-wrapper{padding-top:0!important}.custom-icon path{fill:#0000008a}.remirror-theme div.ProseMirror{border:1px solid #dedfe3!important;border-radius:0!important;box-shadow:none!important}.MuiTooltip-popper>div{background-color:#1a2129;border-radius:0;font-size:85%;font-weight:400;padding:.5rem}.MuiMenu-paper{transform:none!important}.squidex-editor-disabled{pointer-events:none}.squidex-editor-menu{border:1px solid #dedfe3;border-bottom:0;padding:5px}.squidex-editor-counter{border:1px solid #dedfe3;border-top:0;font-size:85%;font-weight:400;opacity:.8;padding:4px 10px 4px 4px;text-align:right}.squidex-editor-image-view{border:1px solid #dedfe3;border-radius:0;display:inline-block;margin-top:15px;margin-bottom:15px;overflow:hidden}.squidex-editor-image-buttons{bottom:10px;left:10px;position:absolute}.squidex-editor-image-element{display:block;max-width:400px;max-height:400px}.squidex-editor-image-info{left:10px;top:10px;position:absolute;background-color:#3284f4;color:#fff;font-size:85%;font-weight:400;padding:2px 6px}.squidex-editor-content-link{align-items:center;border-radius:2px;border:1px solid #dedfe3;padding:10px;display:flex;flex-direction:row;flex-wrap:nowrap;margin-top:10px;margin-bottom:10px}.squidex-editor-content-schema{display:block;overflow-x:hidden;overflow-y:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;min-width:0;width:auto;border-right:1px solid #c2c4cc;color:#8b8f9d;flex-shrink:0;padding-left:10px;padding-right:10px;width:200px}.squidex-editor-content-name{display:block;overflow-x:hidden;overflow-y:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;min-width:0;width:auto;padding-left:10px;padding-right:0}.squidex-editor-html{margin-bottom:10px;margin-top:10px;position:relative}.squidex-editor-html-label{left:6px;top:0;position:absolute;color:#8b8f9d;font-size:85%;font-weight:400}.squidex-editor-html textarea{font-family:monospace;padding:30px 20px 20px}.squidex-editor-button{align-items:center;background-color:#fff;border-radius:0;border:1px solid #dedfe3;bottom:10px;display:inline-flex;font-size:85%;font-weight:400;margin-right:5px;padding:6px 12px}.squidex-editor-button:hover{background-color:#f5f5f5}.squidex-editor-input{border:1px solid #dedfe3;border-radius:0;box-sizing:border-box;height:30px;margin-left:0;margin-right:5px;outline:none;padding:6px 12px}.squidex-editor-input:active{border-color:#3284f4}.squidex-editor-floating{border:1px solid #dedfe3}.squidex-editor-floating .MuiBox-root{margin-right:0!important}.squidex-editor-floating .MuiButtonBase-root{height:30px}.squidex-editor-modal-wrapper,.squidex-editor-modal-backdrop{bottom:0;left:0;right:0;top:0;position:absolute}.squidex-editor-modal-backdrop{background-color:#00000003}.squidex-editor-modal-window{left:50%;top:50%;background-color:#fff;border:0;border-radius:.25rem;box-sizing:border-box;box-shadow:0 3px 16px #0003;margin-top:-50px;margin-left:-150px;position:absolute;width:350px}.squidex-editor-modal-body{display:flex;flex-direction:row;flex-grow:1;padding-top:0!important}.squidex-editor-modal-body,.squidex-editor-modal-title{padding:15px}.squidex-editor-modal-title{font-size:85%}.squidex-editor-modal-window input{flex-grow:1}.b:before{content:"<a>";font-family:monospace;font-size:90%}.b:after{content:"</a>";font-family:monospace;font-size:90%}

224
backend/src/Squidex/wwwroot/editor/squidex-editor.js

File diff suppressed because one or more lines are too long

7
frontend/src/app/declarations.d.ts

@ -89,6 +89,13 @@ interface EditorProps {
// Called when content items should be selected.
onSelectContents?: OnSelectContents;
// Called when an asset is to be edited.
onEditAsset: (assetId: string) => void;
// Called when a content is to be edited.
onEditContent: (schemaName: string, contentId: string) => void;
// Called when a file needs to be uploaded.
onUpload?: (images: UploadRequest[]) => DelayedPromiseCreator<Asset>[];

6
frontend/src/app/shared/components/forms/rich-editor.component.html

@ -4,8 +4,12 @@
(assetSelect)="insertAssets($event)">
</sqx-asset-selector>
<sqx-asset-dialog *sqxModal="assetToEdit | async; let asset;isDialog:true" (dialogClose)="closeAssetDialog()"
[asset]="asset" >
</sqx-asset-dialog>
<sqx-content-selector *sqxModal="contentsDialog"
(contentSelect)="insertContents($event)"
(contentSelect)="insertContents($event)"
[language]="language"
[languages]="languages"
[schemaIds]="schemaIds">

30
frontend/src/app/shared/components/forms/rich-editor.component.ts

@ -7,8 +7,9 @@
import { AfterViewInit, booleanAttribute, ChangeDetectionStrategy, Component, ElementRef, EventEmitter, forwardRef, Input, OnDestroy, Output, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { BehaviorSubject, catchError, of, switchMap } from 'rxjs';
import { ContentDto } from '@app/shared';
import { ApiUrlConfig, AppsState, AssetDto, AssetUploaderState, DialogModel, getContentValue, LanguageDto, ResourceLoaderService, StatefulControlComponent, Types } from '@app/shared/internal';
import { ApiUrlConfig, AppsState, AssetDto, AssetsService, AssetUploaderState, DialogModel, getContentValue, LanguageDto, ResourceLoaderService, StatefulControlComponent, Types } from '@app/shared/internal';
export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true,
@ -24,6 +25,7 @@ export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RichEditorComponent extends StatefulControlComponent<{}, string> implements AfterViewInit, OnDestroy {
private readonly assetId = new BehaviorSubject<string | null>(null);
private editorWrapper: any;
private value?: string;
private currentContents?: ResolvablePromise<any>;
@ -62,16 +64,26 @@ export class RichEditorComponent extends StatefulControlComponent<{}, string> im
@ViewChild('editor', { static: false })
public editor!: ElementRef;
public assetsDialog = new DialogModel();
public chatDialog = new DialogModel();
public assetsDialog = new DialogModel();
public assetToEdit = this.assetId.pipe(
switchMap(id => {
if (id) {
return this.assetService.getAsset(this.appsState.appName, id);
} else {
return of<AssetDto | null>(null);
}
}),
catchError(() => of<AssetDto | null>(null)));
public contentsDialog = new DialogModel();
constructor(
private readonly apiUrl: ApiUrlConfig,
private readonly appsState: AppsState,
private readonly assetUploader: AssetUploaderState,
private readonly assetService: AssetsService,
private readonly resourceLoader: ResourceLoaderService,
) {
super({});
@ -126,6 +138,14 @@ export class RichEditorComponent extends StatefulControlComponent<{}, string> im
onChange: (value: string | undefined) => {
this.callChange(value);
},
onEditContent: (schemaName, id) => {
const url = this.apiUrl.buildUrl(`/app/${this.appsState.appName}/content/${schemaName}/${id}`);
window.open(url, '_blank');
},
onEditAsset: id => {
this.assetId.next(id);
},
appName: this.appsState.appName,
baseUrl: this.apiUrl.buildUrl(''),
canSelectAIText: this.hasChatBot,
@ -222,6 +242,10 @@ export class RichEditorComponent extends StatefulControlComponent<{}, string> im
private buildContent(content: ContentDto): Content {
return { ...content, title: buildContentTitle(content, this.language) };
}
public closeAssetDialog() {
this.assetId.next(null);
}
}
function buildContentTitle(content: ContentDto, language: LanguageDto) {

Loading…
Cancel
Save