mirror of https://github.com/Squidex/squidex.git
16 changed files with 335 additions and 100 deletions
@ -0,0 +1,70 @@ |
|||
<sqx-modal-dialog (close)="complete()" large="true" fullHeight="true" contentClass="grid"> |
|||
<ng-container title> |
|||
Select contents |
|||
</ng-container> |
|||
|
|||
<ng-container tabs> |
|||
<form class="form-inline search-form" (ngSubmit)="search()"> |
|||
<input class="form-control form-control-expandable" [formControl]="contentsFilter" placeholder="Search for content" /> |
|||
|
|||
<a class="expand-search" (click)="searchModal.toggle()" #archive> |
|||
<i class="icon-caret-down"></i> |
|||
</a> |
|||
</form> |
|||
|
|||
<button class="btn btn-link btn-secondary" (click)="load(true)"> |
|||
<i class="icon-reset"></i> Refresh |
|||
</button> |
|||
</ng-container> |
|||
|
|||
<ng-container content> |
|||
<div class="grid-header"> |
|||
<table class="table table-items table-fixed" *ngIf="contentItems"> |
|||
<thead> |
|||
<tr> |
|||
<th class="cell-select"> |
|||
<input type="checkbox" class="form-control" [ngModel]="isAllSelected" (ngModelChange)="selectAll($event)" /> |
|||
</th> |
|||
<th class="cell-auto" *ngFor="let field of schemaFields"> |
|||
<span class="field">{{field.displayName}}</span> |
|||
</th> |
|||
<th class="cell-time"> |
|||
Updated |
|||
</th> |
|||
<th class="cell-user"> |
|||
By |
|||
</th> |
|||
</tr> |
|||
</thead> |
|||
</table> |
|||
</div> |
|||
|
|||
<div class="grid-content"> |
|||
<div sqxIgnoreScrollbar> |
|||
<table class="table table-items table-fixed" *ngIf="contentItems"> |
|||
<tbody> |
|||
<ng-template ngFor let-content [ngForOf]="contentItems" [ngForTrackBy]="trackByContent"> |
|||
<tr [sqxContent]="content" |
|||
[selected]="isItemSelected(content)" |
|||
(selectedChange)="onContentSelected(content)" |
|||
[language]="languageSelected" |
|||
[schemaFields]="schemaFields" |
|||
[schema]="schema" |
|||
isReadOnly="true"></tr> |
|||
<tr class="spacer"></tr> |
|||
</ng-template> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="grid-footer"> |
|||
<sqx-pager [pager]="contentsPager"></sqx-pager> |
|||
</div> |
|||
</ng-container> |
|||
|
|||
<ng-container footer> |
|||
<button type="reset" class="float-left btn btn-secondary" (click)="complete()">Cancel</button> |
|||
<button type="submit" class="float-right btn btn-success" (click)="select()" [disabled]="selectionCount === 0">Link selected contents ({{selectionCount}})</button> |
|||
</ng-container> |
|||
</sqx-modal-dialog> |
|||
@ -0,0 +1,38 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.content { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.icon-plus { |
|||
font-size: .8rem; |
|||
} |
|||
|
|||
.search-form { |
|||
display: inline-block; |
|||
} |
|||
|
|||
.form-inline { |
|||
position: relative; |
|||
} |
|||
|
|||
.form-control-expandable { |
|||
padding-right: 1.5rem; |
|||
} |
|||
|
|||
.expand-search { |
|||
@include absolute(8px, 8px, auto, auto); |
|||
color: $color-border-dark !important; |
|||
font-size: .9rem; |
|||
font-weight: normal; |
|||
cursor: pointer !important; |
|||
} |
|||
|
|||
:host /deep/ .modal-body { |
|||
background: $color-background; |
|||
} |
|||
|
|||
:host /deep/ .modal-tabs { |
|||
background: $color-dark-foreground; |
|||
} |
|||
@ -0,0 +1,147 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; |
|||
import { FormControl } from '@angular/forms'; |
|||
|
|||
import { |
|||
AppsState, |
|||
ContentDto, |
|||
ContentsService, |
|||
DialogService, |
|||
FieldDto, |
|||
ImmutableArray, |
|||
ModalView, |
|||
Pager, |
|||
SchemaDetailsDto, |
|||
LanguageDto |
|||
} from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-contents-selector', |
|||
styleUrls: ['./contents-selector.component.scss'], |
|||
templateUrl: './contents-selector.component.html' |
|||
}) |
|||
export class ContentsSelectorComponent implements OnInit { |
|||
@Input() |
|||
public language: LanguageDto[]; |
|||
|
|||
@Input() |
|||
public schema: SchemaDetailsDto; |
|||
|
|||
@Input() |
|||
public schemaFields: FieldDto[]; |
|||
|
|||
@Output() |
|||
public selected = new EventEmitter<ContentDto[]>(); |
|||
|
|||
public searchModal = new ModalView(); |
|||
|
|||
public contentItems: ImmutableArray<ContentDto>; |
|||
public contentsFilter = new FormControl(); |
|||
public contentsQuery = ''; |
|||
public contentsPager = new Pager(0); |
|||
|
|||
public selectedItems: { [id: string]: ContentDto; } = {}; |
|||
public selectionCount = 0; |
|||
|
|||
public isAllSelected = false; |
|||
|
|||
constructor( |
|||
private readonly appsState: AppsState, |
|||
private readonly contentsService: ContentsService, |
|||
private readonly dialogs: DialogService |
|||
) { |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
this.load(); |
|||
} |
|||
|
|||
public load(showInfo = false) { |
|||
this.contentsService.getContents(this.appsState.appName, this.schema.name, this.contentsPager.pageSize, this.contentsPager.skip, this.contentsQuery, undefined, false) |
|||
.finally(() => { |
|||
this.selectedItems = {}; |
|||
|
|||
this.updateSelectionSummary(); |
|||
}) |
|||
.subscribe(dtos => { |
|||
this.contentItems = ImmutableArray.of(dtos.items); |
|||
this.contentsPager = this.contentsPager.setCount(dtos.total); |
|||
|
|||
if (showInfo) { |
|||
this.dialogs.notifyInfo('Contents reloaded.'); |
|||
} |
|||
}, error => { |
|||
this.dialogs.notifyError(error); |
|||
}); |
|||
} |
|||
|
|||
public search() { |
|||
this.contentsQuery = this.contentsFilter.value; |
|||
this.contentsPager = new Pager(0); |
|||
|
|||
this.load(); |
|||
} |
|||
|
|||
public goNext() { |
|||
this.contentsPager = this.contentsPager.goNext(); |
|||
|
|||
this.load(); |
|||
} |
|||
|
|||
public goPrev() { |
|||
this.contentsPager = this.contentsPager.goPrev(); |
|||
|
|||
this.load(); |
|||
} |
|||
|
|||
public isItemSelected(content: ContentDto) { |
|||
return this.selectedItems[content.id]; |
|||
} |
|||
|
|||
public complete() { |
|||
this.selected.emit([]); |
|||
} |
|||
|
|||
public select() { |
|||
this.selected.emit(Object.values(this.selectedItems)); |
|||
} |
|||
|
|||
public selectAll(isSelected: boolean) { |
|||
this.selectedItems = {}; |
|||
|
|||
if (isSelected) { |
|||
for (let content of this.contentItems.values) { |
|||
this.selectedItems[content.id] = content; |
|||
} |
|||
} |
|||
|
|||
this.updateSelectionSummary(); |
|||
} |
|||
|
|||
public onContentSelected(content: ContentDto) { |
|||
if (this.selectedItems[content.id]) { |
|||
delete this.selectedItems[content.id]; |
|||
} else { |
|||
this.selectedItems[content.id] = content; |
|||
} |
|||
|
|||
this.updateSelectionSummary(); |
|||
} |
|||
|
|||
private updateSelectionSummary() { |
|||
this.selectionCount = Object.keys(this.selectedItems).length; |
|||
|
|||
this.isAllSelected = this.selectionCount === this.contentItems.length; |
|||
} |
|||
|
|||
public trackByContent(content: ContentDto): string { |
|||
return content.id; |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue