Browse Source

Tag selector for asset selector.

pull/320/head
Sebastian Stehle 8 years ago
parent
commit
f8ddd6b178
  1. 28
      src/Squidex/app/features/assets/pages/assets-page.component.html
  2. 18
      src/Squidex/app/features/assets/pages/assets-page.component.scss
  3. 4
      src/Squidex/app/features/assets/pages/assets-page.component.ts
  4. 7
      src/Squidex/app/framework/angular/forms/tag-editor.component.scss
  5. 28
      src/Squidex/app/framework/angular/forms/tag-editor.component.ts
  6. 9
      src/Squidex/app/shared/components/asset.component.scss
  7. 25
      src/Squidex/app/shared/components/assets-selector.component.html
  8. 20
      src/Squidex/app/shared/components/assets-selector.component.scss
  9. 4
      src/Squidex/app/shared/components/assets-selector.component.ts
  10. 8
      src/Squidex/app/shared/components/search-form.component.ts
  11. 18
      src/Squidex/app/shared/state/assets.state.ts

28
src/Squidex/app/features/assets/pages/assets-page.component.html

@ -14,15 +14,25 @@
<i class="icon-reset"></i> Refresh
</button>
</div>
<div class="col pl-1">
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<sqx-search-form formClass="form" placeholder="Search for assets" fieldExample="fileSize"
(queryChanged)="search($event)"
[query]="assetsState.assetsQuery | async"
[queries]="queries"
enableShortcut="true">
</sqx-search-form>
<div class="col pl-1" style="width: 300px">
<div class="row no-gutters search">
<div class="col col-6">
<sqx-tag-editor class="tags" singleLine="true" placeholder="Search by tags"
[suggestions]="assetsState.tagsNames | async"
[ngModel]="assetsState.selectedTagNames | async"
(ngModelChange)="selectTags($event)"
[undefinedWhenEmpty]="false">
</sqx-tag-editor>
</div>
<div class="col col-6">
<sqx-search-form formClass="form" placeholder="Search by asset name" fieldExample="fileSize"
(queryChanged)="search($event)"
[query]="assetsState.assetsQuery | async"
[queries]="queries"
enableShortcut="true">
</sqx-search-form>
</div>
</div>
</div>
</div>
</ng-container>

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

@ -4,4 +4,22 @@
.section {
border-top: 1px solid $color-border;
padding: 1rem;
}
:host /deep/ {
.search {
.form-control {
@include border-radius-right;
}
.tags {
@include border-radius-left;
border-right: 0;
&:focus,
&.focus {
z-index: 1000;
}
}
}
}

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

@ -51,6 +51,10 @@ export class AssetsPageComponent implements OnInit {
this.assetsState.toggleTag(tag).pipe(onErrorResumeNext()).subscribe();
}
public selectTags(tags: string[]) {
this.assetsState.selectTags(tags).pipe(onErrorResumeNext()).subscribe();
}
public resetTags() {
this.assetsState.resetTags().pipe(onErrorResumeNext()).subscribe();
}

7
src/Squidex/app/framework/angular/forms/tag-editor.component.scss

@ -3,6 +3,10 @@
$focus-color: #b3d3ff;
:host {
text-align: left;
}
.form-control {
& {
cursor: text;
@ -32,6 +36,9 @@ $focus-color: #b3d3ff;
div {
&.form-control {
height: auto;
text-align: left;
text-decoration: none;
position: relative;
}
}

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

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, 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';
@ -77,7 +77,7 @@ export const SQX_TAG_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
templateUrl: './tag-editor.component.html',
providers: [SQX_TAG_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class TagEditorComponent implements ControlValueAccessor, OnDestroy, OnInit {
export class TagEditorComponent implements AfterViewInit, ControlValueAccessor, OnDestroy, OnInit {
private subscription: Subscription;
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
@ -104,7 +104,7 @@ export class TagEditorComponent implements ControlValueAccessor, OnDestroy, OnIn
public class: string;
@Input()
public placeholder = 'Press comma (,) to add tag';
public placeholder = ', to add tag';
@Input()
public inputName = 'tag-editor';
@ -128,6 +128,10 @@ export class TagEditorComponent implements ControlValueAccessor, OnDestroy, OnIn
this.subscription.unsubscribe();
}
public ngAfterViewInit() {
this.resetSize();
}
public ngOnInit() {
this.subscription =
this.addInput.valueChanges.pipe(
@ -211,18 +215,12 @@ export class TagEditorComponent implements ControlValueAccessor, OnDestroy, OnIn
if (ctx) {
ctx.font = `${style.getPropertyValue('font-size')} ${style.getPropertyValue('font-family')}`;
let width = 0;
const widthText = ctx.measureText(this.inputElement.nativeElement.value).width;
const widthPlaceholder = ctx.measureText(this.placeholder).width;
if (this.singleLine) {
width = ctx.measureText(this.inputElement.nativeElement.value || this.placeholder).width;
} else {
const widthText = ctx.measureText(this.inputElement.nativeElement.value).width;
const widthPlaceholder = ctx.measureText(this.placeholder).width;
width = Math.max(widthText, widthPlaceholder);
}
const width = Math.max(widthText, widthPlaceholder);
this.inputElement.nativeElement.style.width = <any>((width + 20) + 'px');
this.inputElement.nativeElement.style.width = <any>((width + 5) + 'px');
}
}
@ -291,8 +289,8 @@ export class TagEditorComponent implements ControlValueAccessor, OnDestroy, OnIn
selection = 0;
}
if (selection >= this.items.length) {
selection = this.items.length - 1;
if (selection >= this.suggestedItems.length) {
selection = this.suggestedItems.length - 1;
}
this.suggestedIndex = selection;

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

@ -51,6 +51,15 @@
padding-right: 8px;
}
:host /deep/ {
.form-control {
&.disabled,
&:disabled {
background: transparent;
}
}
}
.card {
& {
@include overlay-container;

25
src/Squidex/app/shared/components/assets-selector.component.html

@ -5,16 +5,29 @@
<ng-container tabs>
<div class="row no-gutters">
<div class="col col-auto offset-lg-4">
<div class="col col-auto offset-lg-2">
<button class="btn btn-link btn-secondary" (click)="reload()">
<i class="icon-reset"></i> Refresh
</button>
</div>
<div class="col pl-1">
<sqx-search-form formClass="form" placeholder="Search for assets" fieldExample="fileSize"
[query]="state.assetsQuery | async"
(queryChanged)="search($event)">
</sqx-search-form>
<div class="col pl-1" style="width: 300px">
<div class="row no-gutters search">
<div class="col col-6">
<sqx-tag-editor class="tags" singleLine="true" placeholder="Search by tags"
[suggestions]="state.tagsNames | async"
[ngModel]="state.selectedTagNames | async"
(ngModelChange)="selectTags($event)"
[undefinedWhenEmpty]="false">
</sqx-tag-editor>
</div>
<div class="col col-6">
<sqx-search-form formClass="form" placeholder="Search by asset name" fieldExample="fileSize"
(queryChanged)="search($event)"
[query]="state.assetsQuery | async"
enableShortcut="true">
</sqx-search-form>
</div>
</div>
</div>
</div>
</ng-container>

20
src/Squidex/app/shared/components/assets-selector.component.scss

@ -1,2 +1,20 @@
@import '_vars';
@import '_mixins';
@import '_mixins';
:host /deep/ {
.search {
.form-control {
@include border-radius-right;
}
.tags {
@include border-radius-left;
border-right: 0;
&:focus,
&.focus {
z-index: 1000;
}
}
}
}

4
src/Squidex/app/shared/components/assets-selector.component.ts

@ -56,6 +56,10 @@ export class AssetsSelectorComponent implements OnInit {
this.selected.emit(Object.values(this.selectedAssets));
}
public selectTags(tags: string[]) {
this.state.selectTags(tags).pipe(onErrorResumeNext()).subscribe();
}
public selectAsset(asset: AssetDto) {
if (this.selectedAssets[asset.id]) {
delete this.selectedAssets[asset.id];

8
src/Squidex/app/shared/components/search-form.component.ts

@ -82,7 +82,9 @@ export class SearchFormComponent implements OnChanges, OnInit {
}
public ngOnInit() {
this.saveKey = this.queries.getSaveKey(this.contentsFilter.valueChanges);
if (this.queries) {
this.saveKey = this.queries.getSaveKey(this.contentsFilter.valueChanges);
}
}
public ngOnChanges() {
@ -98,7 +100,9 @@ export class SearchFormComponent implements OnChanges, OnInit {
const value = this.saveQueryForm.submit();
if (value) {
this.queries.add(value.name, this.contentsFilter.value);
if (this.queries) {
this.queries.add(value.name, this.contentsFilter.value);
}
this.saveQueryForm.submitCompleted();
}

18
src/Squidex/app/shared/state/assets.state.ts

@ -41,6 +41,10 @@ export class AssetsState extends State<Snapshot> {
this.tags.pipe(
distinctUntilChanged(), map(x => x.map(t => t.name)));
public selectedTagNames =
this.changes.pipe(
distinctUntilChanged(), map(x => Object.keys(x.tagsSelected)));
public assets =
this.changes.pipe(map(x => x.assets),
distinctUntilChanged());
@ -165,6 +169,20 @@ export class AssetsState extends State<Snapshot> {
return this.loadInternal();
}
public selectTags(tags: string[]): Observable<any> {
this.next(s => {
const tagsSelected = {};
for (let tag of tags) {
tagsSelected[tag] = true;
}
return { ...s, assetsPager: new Pager(0, 0, 30), tagsSelected };
});
return this.loadInternal();
}
public resetTags(): Observable<any> {
this.next(s => ({ ...s, assetsPager: new Pager(0, 0, 30), tagsSelected: {} }));

Loading…
Cancel
Save