Browse Source

rich text editor assets selector changes

- show only image mime types (jpeg, png and gif)
    - hide edit, download and delete icons on asset listing
    - use absolute urls for inserted images
pull/159/head
sowobm 8 years ago
parent
commit
bf65ebe9a4
  1. 37
      src/Squidex/app/framework/angular/rich-editor.component.html
  2. 36
      src/Squidex/app/framework/angular/rich-editor.component.scss
  3. 141
      src/Squidex/app/framework/angular/rich-editor.component.ts
  4. 8
      src/Squidex/app/shared/components/asset.component.html
  5. 3
      src/Squidex/app/shared/components/asset.component.ts
  6. 2
      src/Squidex/app/shared/components/rich-editor.component.html
  7. 5
      src/Squidex/app/shared/components/rich-editor.component.ts

37
src/Squidex/app/framework/angular/rich-editor.component.html

@ -1,37 +0,0 @@
<div class="editor" #editor></div>
<div class="modal asset-selector" *sqxModalView="assetsDialog;onRoot:true">
<div class="modal-backdrop"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mce-title">Select an asset</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="cancelSelectAsset()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="assetsForm" (ngSubmit)="selecteAsset()">
<div class="form-group">
<label for="asset-name">Name</label>
<sqx-control-errors for="name" [submitted]="selecteAsset"></sqx-control-errors>
<input type="text" class="form-control" id="asset-name" formControlName="name" autocomplete="off" sqxFocusOnInit />
</div>
<div class="row">
<sqx-asset class="col-3" *ngFor="let asset of assetsItems" [asset]="asset"></sqx-asset>
</div>
<div class="form-group clearfix text-right">
<button type="submit" class="btn btn-sm btn-success">Select</button>
<button type="reset" class="btn btn-sm btn-secondary" (click)="cancelSelectAsset()">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>

36
src/Squidex/app/framework/angular/rich-editor.component.scss

@ -1,36 +0,0 @@
@import '_mixins';
@import '_vars';
.editor {
background: $color-dark-foreground;
border: 1px solid $color-input;
height: 30rem;
}
.asset-selector {
z-index: 65560;
.modal-header {
background: transparent;
border-bottom: 1px solid #c5c5c5;
.modal-title {
text-decoration: none;
color: #333;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
text-shadow: none;
}
}
.modal-content {
width: 100%;
border-radius: 0;
-webkit-border-radius: 0;
}
.modal-dialog {
max-width: 900px;
}
.btn {
border-radius: 0;
}
}

141
src/Squidex/app/framework/angular/rich-editor.component.ts

@ -1,141 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { AfterViewInit, Component, forwardRef, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormBuilder } from '@angular/forms';
import { Types } from './../utils/types';
import { ResourceLoaderService } from './../services/resource-loader.service';
import { AppComponentBase } from './../../shared/components/app.component-base';
import { ModalView, AppsStoreService, AssetDto, AssetsService, ImmutableArray, DialogService, AuthService, Pager } from './../../shared/declarations-base';
declare var tinymce: any;
export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true
};
@Component({
selector: 'sqx-rich-editor',
styleUrls: ['./rich-editor.component.scss'],
templateUrl: './rich-editor.component.html',
providers: [SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class RichEditorComponent extends AppComponentBase implements ControlValueAccessor, AfterViewInit, OnDestroy, OnInit {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
private tinyEditor: any;
private tinyInitTimer: any;
private value: string;
private isDisabled = false;
public assetsItems: ImmutableArray<AssetDto>;
public assetsPager = new Pager(0, 0, 12);
@ViewChild('editor')
public editor: ElementRef;
public assetsDialog = new ModalView();
public assetsForm = this.formBuilder.group({
name: ['']
});
constructor(dialogs: DialogService, apps: AppsStoreService, authService: AuthService,
private readonly resourceLoader: ResourceLoaderService,
private readonly formBuilder: FormBuilder,
private readonly assetsService: AssetsService
) {
super(dialogs, apps, authService);
}
public ngOnInit() {
this.appNameOnce()
.switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip))
.subscribe(dtos => {
this.assetsItems = ImmutableArray.of(dtos.items);
this.assetsPager = this.assetsPager.setCount(dtos.total);
}, error => {
this.notifyError(error);
});
}
public ngOnDestroy() {
clearTimeout(this.tinyInitTimer);
tinymce.remove(this.editor);
}
public ngAfterViewInit() {
const self = this;
this.resourceLoader.loadScript('https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.4/tinymce.min.js').then(() => {
tinymce.init({
setup: (editor: any) => {
self.tinyEditor = editor;
self.tinyEditor.setMode(this.isDisabled ? 'readonly' : 'design');
self.tinyEditor.on('change', () => {
const value = editor.getContent();
if (this.value !== value) {
this.value = value;
self.callChange(value);
}
});
self.tinyEditor.on('blur', () => {
self.callTouched();
});
this.tinyInitTimer =
setTimeout(() => {
self.tinyEditor.setContent(this.value || '');
}, 500);
},
removed_menuitems: 'newdocument', plugins: 'code,image', target: this.editor.nativeElement, file_picker_types: 'image', file_picker_callback: (cb: any, value: any, meta: any) => {
self.assetsDialog.show();
}
});
});
}
public writeValue(value: string) {
this.value = Types.isString(value) ? value : '';
if (this.tinyEditor) {
this.tinyEditor.setContent(this.value);
}
}
public setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
if (this.tinyEditor) {
this.tinyEditor.setMode(isDisabled ? 'readonly' : 'design');
}
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public selecteAsset() {
console.log('Selecting asset ' + this.assetsForm.controls['name'].value);
}
public cancelSelectAsset() {
console.log('asset selection canceled');
this.assetsDialog.hide();
}
}

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

@ -15,17 +15,17 @@
<div class="file-overlay">
<div class="file-overlay-background"></div>
<a class="file-edit" (click)="renameDialog.show()">
<a class="file-edit" (click)="renameDialog.show()" *ngIf="!hideIcons">
<i class="icon-pencil"></i>
</a>
<a class="file-download" [attr.href]="asset | sqxAssetUrl" target="_blank">
<a class="file-download" [attr.href]="asset | sqxAssetUrl" target="_blank" *ngIf="!hideIcons">
<i class="icon-download"></i>
</a>
<a class="file-delete" (click)="deleting.emit(asset)" *ngIf="!closeMode">
<a class="file-delete" (click)="deleting.emit(asset)" *ngIf="!closeMode && !hideIcons">
<i class="icon-delete"></i>
</a>
<a class="file-delete" (click)="closing.emit(asset)" *ngIf="closeMode">
<a class="file-delete" (click)="closing.emit(asset)" *ngIf="closeMode && !hideIcons">
<i class="icon-close"></i>
</a>

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

@ -44,6 +44,9 @@ export class AssetComponent extends AppComponentBase implements OnInit {
@Input()
public closeMode = false;
@Input()
public hideIcons = false;
@Output()
public loaded = new EventEmitter<AssetDto>();

2
src/Squidex/app/shared/components/rich-editor.component.html

@ -15,7 +15,7 @@
<div class="modal-body">
<form [formGroup]="assetsForm" (ngSubmit)="closeAssetDialog()">
<div class="row">
<sqx-asset class="col-3" *ngFor="let asset of assetsItems" [asset]="asset" (clicked)="onAssetClicked($event)" ></sqx-asset>
<sqx-asset class="col-3" *ngFor="let asset of assetsItems" [asset]="asset" [hideIcons]="true" (clicked)="onAssetClicked($event)" ></sqx-asset>
</div>
<div class="clearfix" *ngIf="assetsPager.numberOfItems > 0">
<div class="float-right pagination">

5
src/Squidex/app/shared/components/rich-editor.component.ts

@ -35,6 +35,7 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu
public assetsItems: ImmutableArray<AssetDto>;
public assetsPager = new Pager(0, 0, 12);
private assetUrlGenerator: AssetUrlPipe;
private assetsMimeTypes: Array<string> = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'];
@ViewChild('editor')
public editor: ElementRef;
@ -56,7 +57,7 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu
private load() {
this.appNameOnce()
.switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip))
.switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, undefined, this.assetsMimeTypes))
.subscribe(dtos => {
this.assetsItems = ImmutableArray.of(dtos.items);
this.assetsPager = this.assetsPager.setCount(dtos.total);
@ -111,7 +112,7 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu
self.tinyEditor.setContent(this.value || '');
}, 500);
},
removed_menuitems: 'newdocument', plugins: 'code,image', target: this.editor.nativeElement, file_picker_types: 'image', file_picker_callback: (cb: any, value: any, meta: any) => {
removed_menuitems: 'newdocument', plugins: 'code,image', target: this.editor.nativeElement, file_picker_types: 'image', convert_urls: false, file_picker_callback: (cb: any, value: any, meta: any) => {
self.load();
self.assetsDialog.show();
self.assetSelectorClickHandler = {

Loading…
Cancel
Save