Merge pull request #4725 from GabrielInTheWorld/form-control
Separates the attachment field to a custom component
This commit is contained in:
commit
596b9516e6
@ -21,7 +21,6 @@
|
|||||||
<div *ngIf="itemObserver.value.length > 0">
|
<div *ngIf="itemObserver.value.length > 0">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="form"
|
|
||||||
[formControl]="form.get('agenda_parent_id')"
|
[formControl]="form.get('agenda_parent_id')"
|
||||||
[multiple]="false"
|
[multiple]="false"
|
||||||
[includeNone]="true"
|
[includeNone]="true"
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<div class="attachment-container" *ngIf="controlName">
|
||||||
|
<os-search-value-selector
|
||||||
|
class="selector"
|
||||||
|
ngDefaultControl
|
||||||
|
[multiple]="true"
|
||||||
|
listname="{{ 'Attachments' | translate }}"
|
||||||
|
[formControl]="controlName"
|
||||||
|
[InputListValues]="mediaFileList"
|
||||||
|
></os-search-value-selector>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
mat-icon-button
|
||||||
|
(click)="openUploadDialog(uploadDialog)"
|
||||||
|
*osPerms="'mediafiles.can_upload'"
|
||||||
|
>
|
||||||
|
<mat-icon>cloud_upload</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- upload file dialog -->
|
||||||
|
<ng-template #uploadDialog>
|
||||||
|
<h1 mat-dialog-title>
|
||||||
|
<span translate>Upload files</span>
|
||||||
|
</h1>
|
||||||
|
<os-media-upload-content
|
||||||
|
(uploadSuccessEvent)="uploadSuccess($event)"
|
||||||
|
(errorEvent)="uploadError($event)"
|
||||||
|
></os-media-upload-content>
|
||||||
|
</ng-template>
|
@ -0,0 +1,14 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.attachment-container {
|
||||||
|
justify-content: space-between;
|
||||||
|
display: flex;
|
||||||
|
.selector {
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
.mat-icon-button {
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, TestBed, ComponentFixture } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AttachmentControlComponent } from './attachment-control.component';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
|
describe('AttachmentControlComponent', () => {
|
||||||
|
let component: AttachmentControlComponent;
|
||||||
|
let fixture: ComponentFixture<AttachmentControlComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AttachmentControlComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,107 @@
|
|||||||
|
import { Component, OnInit, TemplateRef, Output, EventEmitter, Input } from '@angular/core';
|
||||||
|
import { MatDialog } from '@angular/material';
|
||||||
|
import { FormControl, ControlValueAccessor } from '@angular/forms';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
|
import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service';
|
||||||
|
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'os-attachment-control',
|
||||||
|
templateUrl: './attachment-control.component.html',
|
||||||
|
styleUrls: ['./attachment-control.component.scss']
|
||||||
|
})
|
||||||
|
export class AttachmentControlComponent implements OnInit, ControlValueAccessor {
|
||||||
|
/**
|
||||||
|
* Output for an error handler
|
||||||
|
*/
|
||||||
|
@Output()
|
||||||
|
public errorHandler: EventEmitter<string> = new EventEmitter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The form-control name to access the value for the form-control
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
public controlName: FormControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file list that is necessary for the `SearchValueSelector`
|
||||||
|
*/
|
||||||
|
public mediaFileList: BehaviorSubject<ViewMediafile[]> = new BehaviorSubject([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*
|
||||||
|
* @param dialogService Reference to the `MatDialog`
|
||||||
|
* @param mediaService Reference for the `MediaFileRepositoryService`
|
||||||
|
*/
|
||||||
|
public constructor(private dialogService: MatDialog, private mediaService: MediafileRepositoryService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init method
|
||||||
|
*/
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.mediaFileList = this.mediaService.getViewModelListBehaviorSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to open a given dialog
|
||||||
|
*
|
||||||
|
* @param dialog the dialog to open
|
||||||
|
*/
|
||||||
|
public openUploadDialog(dialog: TemplateRef<string>): void {
|
||||||
|
this.dialogService.open(dialog, {
|
||||||
|
width: '750px',
|
||||||
|
maxWidth: '90vw',
|
||||||
|
maxHeight: '90vh'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to set the value for the `SearchValueSelector` after successful upload
|
||||||
|
*
|
||||||
|
* @param fileIDs a list with the ids of the uploaded files
|
||||||
|
*/
|
||||||
|
public uploadSuccess(fileIDs: number[]): void {
|
||||||
|
if (this.controlName) {
|
||||||
|
const newValues = [...this.controlName.value, ...fileIDs];
|
||||||
|
this.controlName.setValue(newValues);
|
||||||
|
this.dialogService.closeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to emit an occurring error.
|
||||||
|
*
|
||||||
|
* @param error The occurring error
|
||||||
|
*/
|
||||||
|
public uploadError(error: string): void {
|
||||||
|
this.errorHandler.emit(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to write a new value to the form.
|
||||||
|
* Satisfy the interface.
|
||||||
|
*
|
||||||
|
* @param value The new value for this form.
|
||||||
|
*/
|
||||||
|
public writeValue(value: any): void {
|
||||||
|
if (value && this.controlName) {
|
||||||
|
this.controlName.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function executed when the control's value changed.
|
||||||
|
*
|
||||||
|
* @param fn the function that is executed.
|
||||||
|
*/
|
||||||
|
public registerOnChange(fn: any): void {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To satisfy the interface
|
||||||
|
*
|
||||||
|
* @param fn the registered callback function for onBlur-events.
|
||||||
|
*/
|
||||||
|
public registerOnTouched(fn: any): void {}
|
||||||
|
}
|
@ -36,10 +36,8 @@
|
|||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
*ngIf="searchList"
|
*ngIf="searchList"
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="extensionFieldForm"
|
|
||||||
[formControl]="extensionFieldForm.get('list')"
|
[formControl]="extensionFieldForm.get('list')"
|
||||||
[fullWidth]="true"
|
[fullWidth]="true"
|
||||||
[multiple]="false"
|
|
||||||
[InputListValues]="searchList"
|
[InputListValues]="searchList"
|
||||||
[listname]="searchListLabel"
|
[listname]="searchListLabel"
|
||||||
></os-search-value-selector>
|
></os-search-value-selector>
|
||||||
|
@ -1,25 +1,14 @@
|
|||||||
<mat-form-field [formGroup]="form" [style.display]="fullWidth ? 'block' : 'inline-block'">
|
<mat-form-field [style.display]="fullWidth ? 'block' : 'inline-block'">
|
||||||
<mat-select [formControl]="formControl" placeholder="{{ listname | translate }}" [multiple]="multiple" #thisSelector>
|
<mat-select [formControl]="formControl" placeholder="{{ listname | translate }}" [multiple]="multiple" #thisSelector>
|
||||||
<ngx-mat-select-search [formControl]="filterControl"></ngx-mat-select-search>
|
<ngx-mat-select-search ngModel (ngModelChange)="onSearch($event)"></ngx-mat-select-search>
|
||||||
<div *ngIf="!multiple && includeNone">
|
<div *ngIf="!multiple && includeNone">
|
||||||
<mat-option [value]="null">
|
<mat-option [value]="null">
|
||||||
<span>–</span>
|
<span>–</span>
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
</div>
|
</div>
|
||||||
<mat-option *ngFor="let selectedItem of filteredItems | async" [value]="selectedItem.id">
|
<mat-option *ngFor="let selectedItem of getFilteredItems()" [value]="selectedItem.id">
|
||||||
{{ selectedItem.getTitle() | translate }}
|
{{ selectedItem.getTitle() | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div *ngIf="dispSelected">
|
|
||||||
<p>
|
|
||||||
<span translate>Selected values</span>:
|
|
||||||
</p>
|
|
||||||
<mat-chip-list #chipList>
|
|
||||||
<mat-chip *ngFor="let selectedItem of thisSelector?.value" (removed)="remove(selectedItem)">
|
|
||||||
{{ selectedItem.name }}
|
|
||||||
<mat-icon (click)="remove(selectedItem)">cancel</mat-icon>
|
|
||||||
</mat-chip>
|
|
||||||
</mat-chip-list>
|
|
||||||
</div>
|
|
||||||
|
@ -45,7 +45,6 @@ describe('SearchValueSelectorComponent', () => {
|
|||||||
const formGroup = formBuilder.group({
|
const formGroup = formBuilder.group({
|
||||||
testArray: []
|
testArray: []
|
||||||
});
|
});
|
||||||
hostComponent.searchValueSelectorComponent.form = formGroup;
|
|
||||||
hostComponent.searchValueSelectorComponent.formControl = <FormControl>formGroup.get('testArray');
|
hostComponent.searchValueSelectorComponent.formControl = <FormControl>formGroup.get('testArray');
|
||||||
|
|
||||||
hostFixture.detectChanges();
|
hostFixture.detectChanges();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component, OnInit, Input, ViewChild, OnDestroy } from '@angular/core';
|
import { Component, Input, ViewChild, OnDestroy } from '@angular/core';
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
import { MatSelect } from '@angular/material/select';
|
import { MatSelect } from '@angular/material';
|
||||||
|
|
||||||
import { Subject, ReplaySubject, BehaviorSubject, Subscription } from 'rxjs';
|
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { auditTime } from 'rxjs/operators';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { Selectable } from '../selectable';
|
import { Selectable } from '../selectable';
|
||||||
@ -25,7 +25,6 @@ import { Selectable } from '../selectable';
|
|||||||
* [multiple]="true"
|
* [multiple]="true"
|
||||||
* placeholder="Placeholder"
|
* placeholder="Placeholder"
|
||||||
* [InputListValues]="myListValues"
|
* [InputListValues]="myListValues"
|
||||||
* [form]="myform_name"
|
|
||||||
* [formControl]="myformcontrol">
|
* [formControl]="myformcontrol">
|
||||||
* </os-search-value-selector>
|
* </os-search-value-selector>
|
||||||
* ```
|
* ```
|
||||||
@ -37,38 +36,27 @@ import { Selectable } from '../selectable';
|
|||||||
templateUrl: './search-value-selector.component.html',
|
templateUrl: './search-value-selector.component.html',
|
||||||
styleUrls: ['./search-value-selector.component.scss']
|
styleUrls: ['./search-value-selector.component.scss']
|
||||||
})
|
})
|
||||||
export class SearchValueSelectorComponent implements OnInit, OnDestroy {
|
export class SearchValueSelectorComponent implements OnDestroy {
|
||||||
/**
|
|
||||||
* ngModel variable - Deprecated with Angular 7
|
|
||||||
* DO NOT USE: READ AT remove() FUNCTION!
|
|
||||||
*/
|
|
||||||
public myModel = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Control for the filtering of the list
|
|
||||||
*/
|
|
||||||
public filterControl = new FormControl();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of the filtered content, when entering something in the search bar
|
|
||||||
*/
|
|
||||||
public filteredItems: ReplaySubject<Selectable[]> = new ReplaySubject<Selectable[]>(1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The inputlist subject.
|
|
||||||
*/
|
|
||||||
private _inputListSubject: BehaviorSubject<Selectable[]>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the current subscription to _inputListSubject.
|
* Saves the current subscription to _inputListSubject.
|
||||||
*/
|
*/
|
||||||
private _inputListSubscription: Subscription = null;
|
private _inputListSubscription: Subscription = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of the search input
|
||||||
|
*/
|
||||||
|
private searchValue = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All items
|
||||||
|
*/
|
||||||
|
private selectableItems: Selectable[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decide if this should be a single or multi-select-field
|
* Decide if this should be a single or multi-select-field
|
||||||
*/
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
public multiple: boolean;
|
public multiple = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decide, if none should be included, if multiple is false.
|
* Decide, if none should be included, if multiple is false.
|
||||||
@ -95,9 +83,14 @@ export class SearchValueSelectorComponent implements OnInit, OnDestroy {
|
|||||||
if (this._inputListSubscription) {
|
if (this._inputListSubscription) {
|
||||||
this._inputListSubscription.unsubscribe();
|
this._inputListSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
this._inputListSubject = value;
|
// this.inputSubject = value;
|
||||||
this._inputListSubscription = this._inputListSubject.subscribe(() => {
|
this._inputListSubscription = value.pipe(auditTime(10)).subscribe(items => {
|
||||||
this.filterItems();
|
this.selectableItems = items;
|
||||||
|
if (this.formControl) {
|
||||||
|
items.length === 0
|
||||||
|
? this.formControl.disable({ emitEvent: false })
|
||||||
|
: this.formControl.enable({ emitEvent: false });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,56 +100,23 @@ export class SearchValueSelectorComponent implements OnInit, OnDestroy {
|
|||||||
@Input()
|
@Input()
|
||||||
public listname: String;
|
public listname: String;
|
||||||
|
|
||||||
/**
|
|
||||||
* Form Group
|
|
||||||
*/
|
|
||||||
@Input()
|
|
||||||
public form: FormGroup;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the Form
|
* Name of the Form
|
||||||
*/
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
public formControl: FormControl;
|
public formControl: FormControl;
|
||||||
|
|
||||||
/**
|
|
||||||
* DO NOT USE UNTIL BUG IN UPSTREAM ARE RESOLVED!
|
|
||||||
* READ AT FUNCTION remove()
|
|
||||||
*
|
|
||||||
* Displayes the selected Items as Chip-List
|
|
||||||
*/
|
|
||||||
// @Input()
|
|
||||||
public dispSelected = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MultiSelect Component
|
* The MultiSelect Component
|
||||||
*/
|
*/
|
||||||
@ViewChild('thisSelector', { static: true })
|
@ViewChild('thisSelector', { static: true })
|
||||||
public thisSelector: MatSelect;
|
public thisSelector: MatSelect;
|
||||||
|
|
||||||
/**
|
|
||||||
* Subject that emits when the component has been destroyed
|
|
||||||
*/
|
|
||||||
private _onDestroy = new Subject<void>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty constructor
|
* Empty constructor
|
||||||
*/
|
*/
|
||||||
public constructor(protected translate: TranslateService) {}
|
public constructor(protected translate: TranslateService) {}
|
||||||
|
|
||||||
/**
|
|
||||||
* onInit with filter ans subscription on filter
|
|
||||||
*/
|
|
||||||
public ngOnInit(): void {
|
|
||||||
if (this._inputListSubject) {
|
|
||||||
this.filteredItems.next(this._inputListSubject.getValue());
|
|
||||||
}
|
|
||||||
// listen to value changes
|
|
||||||
this.filterControl.valueChanges.pipe(takeUntil(this._onDestroy)).subscribe(() => {
|
|
||||||
this.filterItems();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsubscribe on destroing.
|
* Unsubscribe on destroing.
|
||||||
*/
|
*/
|
||||||
@ -164,53 +124,31 @@ export class SearchValueSelectorComponent implements OnInit, OnDestroy {
|
|||||||
if (this._inputListSubscription) {
|
if (this._inputListSubscription) {
|
||||||
this._inputListSubscription.unsubscribe();
|
this._inputListSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
this._onDestroy.next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the filter function itself
|
* Function to get a list filtered by the entered search value.
|
||||||
|
*
|
||||||
|
* @returns The filtered list of items.
|
||||||
*/
|
*/
|
||||||
private filterItems(): void {
|
public getFilteredItems(): Selectable[] {
|
||||||
if (!this._inputListSubject) {
|
if (this.selectableItems) {
|
||||||
return;
|
return this.selectableItems.filter(
|
||||||
}
|
item =>
|
||||||
// get the search keyword
|
item
|
||||||
let search = this.filterControl.value;
|
|
||||||
if (!search) {
|
|
||||||
this.filteredItems.next(this._inputListSubject.getValue());
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
search = search.toLowerCase();
|
|
||||||
}
|
|
||||||
// filter the values
|
|
||||||
this.filteredItems.next(
|
|
||||||
this._inputListSubject.getValue().filter(
|
|
||||||
selectedItem =>
|
|
||||||
selectedItem
|
|
||||||
.toString()
|
.toString()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.indexOf(search) > -1
|
.indexOf(this.searchValue) > -1
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the dispSelected value is marked as true, a chipList should be shown below the
|
* Function to set the search value.
|
||||||
* selection list. Unfortunately it is not possible (yet) to change the datamodel in the backend
|
*
|
||||||
* https://github.com/angular/material2/issues/10085 - therefore you can display the values in two
|
* @param searchValue the new value the user is searching for.
|
||||||
* places, but can't reflect the changes in both places. Until this can be done this will be unused code
|
|
||||||
* @param item the selected item to be removed
|
|
||||||
*/
|
*/
|
||||||
public remove(item: Selectable): void {
|
public onSearch(searchValue: string): void {
|
||||||
const myArr = this.thisSelector.value;
|
this.searchValue = searchValue.toLowerCase();
|
||||||
const index = myArr.indexOf(item, 0);
|
|
||||||
// my model was the form according to fix
|
|
||||||
// https://github.com/angular/material2/issues/10044
|
|
||||||
// but this causes bad behaviour and will be depricated in Angular 7
|
|
||||||
this.myModel = this.myModel.slice(index, 1);
|
|
||||||
if (index > -1) {
|
|
||||||
myArr.splice(index, 1);
|
|
||||||
}
|
|
||||||
this.thisSelector.value = myArr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ import { IconContainerComponent } from './components/icon-container/icon-contain
|
|||||||
import { ListViewTableComponent } from './components/list-view-table/list-view-table.component';
|
import { ListViewTableComponent } from './components/list-view-table/list-view-table.component';
|
||||||
import { AgendaContentObjectFormComponent } from './components/agenda-content-object-form/agenda-content-object-form.component';
|
import { AgendaContentObjectFormComponent } from './components/agenda-content-object-form/agenda-content-object-form.component';
|
||||||
import { ExtensionFieldComponent } from './components/extension-field/extension-field.component';
|
import { ExtensionFieldComponent } from './components/extension-field/extension-field.component';
|
||||||
|
import { AttachmentControlComponent } from './components/attachment-control/attachment-control.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Share Module for all "dumb" components and pipes.
|
* Share Module for all "dumb" components and pipes.
|
||||||
@ -214,6 +215,7 @@ import { ExtensionFieldComponent } from './components/extension-field/extension-
|
|||||||
SlideContainerComponent,
|
SlideContainerComponent,
|
||||||
CountdownTimeComponent,
|
CountdownTimeComponent,
|
||||||
MediaUploadContentComponent,
|
MediaUploadContentComponent,
|
||||||
|
AttachmentControlComponent,
|
||||||
PrecisionPipe,
|
PrecisionPipe,
|
||||||
SpeakerButtonComponent,
|
SpeakerButtonComponent,
|
||||||
GridLayoutComponent,
|
GridLayoutComponent,
|
||||||
@ -262,7 +264,8 @@ import { ExtensionFieldComponent } from './components/extension-field/extension-
|
|||||||
IconContainerComponent,
|
IconContainerComponent,
|
||||||
ListViewTableComponent,
|
ListViewTableComponent,
|
||||||
AgendaContentObjectFormComponent,
|
AgendaContentObjectFormComponent,
|
||||||
ExtensionFieldComponent
|
ExtensionFieldComponent,
|
||||||
|
AttachmentControlComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: DateAdapter, useClass: OpenSlidesDateAdapter },
|
{ provide: DateAdapter, useClass: OpenSlidesDateAdapter },
|
||||||
|
@ -121,9 +121,7 @@
|
|||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
class="search-users"
|
class="search-users"
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="addSpeakerForm"
|
|
||||||
[formControl]="addSpeakerForm.get('user_id')"
|
[formControl]="addSpeakerForm.get('user_id')"
|
||||||
[multiple]="false"
|
|
||||||
listname="{{ 'Select or search new speaker ...' | translate }}"
|
listname="{{ 'Select or search new speaker ...' | translate }}"
|
||||||
[InputListValues]="filteredUsers"
|
[InputListValues]="filteredUsers"
|
||||||
></os-search-value-selector>
|
></os-search-value-selector>
|
||||||
|
@ -195,7 +195,6 @@
|
|||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
class="search-bar"
|
class="search-bar"
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="candidatesForm"
|
|
||||||
[formControl]="candidatesForm.get('userId')"
|
[formControl]="candidatesForm.get('userId')"
|
||||||
[multiple]="false"
|
[multiple]="false"
|
||||||
listname="{{ 'Select a new candidate' | translate }}"
|
listname="{{ 'Select a new candidate' | translate }}"
|
||||||
@ -259,7 +258,6 @@
|
|||||||
<div class="content-field" *ngIf="tagsAvailable">
|
<div class="content-field" *ngIf="tagsAvailable">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="assignmentForm"
|
|
||||||
[formControl]="assignmentForm.get('tags_id')"
|
[formControl]="assignmentForm.get('tags_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
[includeNone]="true"
|
[includeNone]="true"
|
||||||
@ -269,15 +267,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Attachments -->
|
<!-- Attachments -->
|
||||||
<div class="content-field" *ngIf="mediafilesAvailable">
|
<div class="content-field">
|
||||||
<os-search-value-selector
|
<os-attachment-control (errorHandler)="raiseError($event)" [controlName]="assignmentForm.get('attachments_id')"></os-attachment-control>
|
||||||
ngDefaultControl
|
|
||||||
[form]="assignmentForm"
|
|
||||||
[formControl]="assignmentForm.get('attachments_id')"
|
|
||||||
[multiple]="true"
|
|
||||||
listname="{{ 'Election documents' | translate }}"
|
|
||||||
[InputListValues]="mediafilesObserver"
|
|
||||||
></os-search-value-selector>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<os-agenda-content-object-form *ngIf="newAssignment" [form]="assignmentForm"></os-agenda-content-object-form>
|
<os-agenda-content-object-form *ngIf="newAssignment" [form]="assignmentForm"></os-agenda-content-object-form>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
<span>
|
<span>
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="modelSelectForm"
|
|
||||||
[formControl]="modelSelectForm.get('model')"
|
[formControl]="modelSelectForm.get('model')"
|
||||||
[multiple]="false"
|
[multiple]="false"
|
||||||
[includeNone]="false"
|
[includeNone]="false"
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
<p>
|
<p>
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="createForm"
|
|
||||||
[formControl]="this.createForm.get('read_groups_id')"
|
[formControl]="this.createForm.get('read_groups_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
listname="Groups with read permissions"
|
listname="Groups with read permissions"
|
||||||
@ -31,7 +30,6 @@
|
|||||||
<p>
|
<p>
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="createForm"
|
|
||||||
[formControl]="this.createForm.get('write_groups_id')"
|
[formControl]="this.createForm.get('write_groups_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
listname="Groups with write permissions"
|
listname="Groups with write permissions"
|
||||||
@ -93,7 +91,6 @@
|
|||||||
<p>
|
<p>
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="updateForm"
|
|
||||||
[formControl]="this.updateForm.get('read_groups_id')"
|
[formControl]="this.updateForm.get('read_groups_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
listname="Groups with read permissions"
|
listname="Groups with read permissions"
|
||||||
@ -103,7 +100,6 @@
|
|||||||
<p>
|
<p>
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="updateForm"
|
|
||||||
[formControl]="this.updateForm.get('write_groups_id')"
|
[formControl]="this.updateForm.get('write_groups_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
listname="Groups with write permissions"
|
listname="Groups with write permissions"
|
||||||
|
@ -37,9 +37,7 @@
|
|||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
class="search-users"
|
class="search-users"
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="addSubmitterForm"
|
|
||||||
[formControl]="addSubmitterForm.get('userId')"
|
[formControl]="addSubmitterForm.get('userId')"
|
||||||
[multiple]="false"
|
|
||||||
listname="{{ 'Select or search new submitter ...' | translate }}"
|
listname="{{ 'Select or search new submitter ...' | translate }}"
|
||||||
[InputListValues]="users"
|
[InputListValues]="users"
|
||||||
></os-search-value-selector>
|
></os-search-value-selector>
|
||||||
|
@ -581,7 +581,6 @@
|
|||||||
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
|
||||||
[formControl]="contentForm.get('submitters_id')"
|
[formControl]="contentForm.get('submitters_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
listname="{{ 'Submitters' | translate }}"
|
listname="{{ 'Submitters' | translate }}"
|
||||||
@ -763,9 +762,7 @@
|
|||||||
<div class="content-field" *ngIf="newMotion && categoryObserver.value.length > 0">
|
<div class="content-field" *ngIf="newMotion && categoryObserver.value.length > 0">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
|
||||||
[formControl]="contentForm.get('category_id')"
|
[formControl]="contentForm.get('category_id')"
|
||||||
[multiple]="false"
|
|
||||||
[includeNone]="true"
|
[includeNone]="true"
|
||||||
listname="{{ 'Category' | translate }}"
|
listname="{{ 'Category' | translate }}"
|
||||||
[InputListValues]="categoryObserver"
|
[InputListValues]="categoryObserver"
|
||||||
@ -783,24 +780,8 @@
|
|||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
</mat-list>
|
</mat-list>
|
||||||
</div>
|
</div>
|
||||||
<div *osPerms="'motions.can_manage'; and: editMotion" class="shortened-selector">
|
<div *osPerms="'motions.can_manage'; and: editMotion">
|
||||||
<os-search-value-selector
|
<os-attachment-control (errorHandler)="showUploadError($event)" [controlName]="contentForm.get('attachments_id')"></os-attachment-control>
|
||||||
class="selector"
|
|
||||||
ngDefaultControl
|
|
||||||
[form]="contentForm"
|
|
||||||
[formControl]="contentForm.get('attachments_id')"
|
|
||||||
[multiple]="true"
|
|
||||||
listname="{{ 'Attachments' | translate }}"
|
|
||||||
[InputListValues]="mediafilesObserver"
|
|
||||||
></os-search-value-selector>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
mat-icon-button
|
|
||||||
(click)="onUploadAttachmentsButton(uploadDialog)"
|
|
||||||
*osPerms="'mediafiles.can_upload'"
|
|
||||||
>
|
|
||||||
<mat-icon>cloud_upload</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -813,7 +794,6 @@
|
|||||||
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
|
||||||
[formControl]="contentForm.get('supporters_id')"
|
[formControl]="contentForm.get('supporters_id')"
|
||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
listname="{{ 'Supporters' | translate }}"
|
listname="{{ 'Supporters' | translate }}"
|
||||||
@ -827,9 +807,7 @@
|
|||||||
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
|
||||||
[formControl]="contentForm.get('workflow_id')"
|
[formControl]="contentForm.get('workflow_id')"
|
||||||
[multiple]="false"
|
|
||||||
listname="{{ 'Workflow' | translate }}"
|
listname="{{ 'Workflow' | translate }}"
|
||||||
[InputListValues]="workflowObserver"
|
[InputListValues]="workflowObserver"
|
||||||
></os-search-value-selector>
|
></os-search-value-selector>
|
||||||
@ -966,14 +944,3 @@
|
|||||||
Final print template
|
Final print template
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<!-- upload file dialog -->
|
|
||||||
<ng-template #uploadDialog>
|
|
||||||
<h1 mat-dialog-title>
|
|
||||||
<span translate>Upload files</span>
|
|
||||||
</h1>
|
|
||||||
<os-media-upload-content
|
|
||||||
(uploadSuccessEvent)="uploadSuccess($event)"
|
|
||||||
(errorEvent)="showUploadError($event)"
|
|
||||||
></os-media-upload-content>
|
|
||||||
</ng-template>
|
|
||||||
|
@ -231,14 +231,3 @@ span {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortened-selector {
|
|
||||||
justify-content: space-between;
|
|
||||||
display: flex;
|
|
||||||
.selector {
|
|
||||||
width: 95%;
|
|
||||||
}
|
|
||||||
.mat-icon-button {
|
|
||||||
top: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
|
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
|
||||||
import { Component, OnInit, OnDestroy, ElementRef, HostListener, TemplateRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ElementRef, HostListener } from '@angular/core';
|
||||||
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
||||||
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
|
||||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||||
@ -20,7 +20,6 @@ import { ItemRepositoryService } from 'app/core/repositories/agenda/item-reposit
|
|||||||
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
||||||
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
||||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||||
import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service';
|
|
||||||
import { Motion } from 'app/shared/models/motions/motion';
|
import { Motion } from 'app/shared/models/motions/motion';
|
||||||
import {
|
import {
|
||||||
MotionChangeRecommendationDialogComponentData,
|
MotionChangeRecommendationDialogComponentData,
|
||||||
@ -56,7 +55,6 @@ import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block';
|
|||||||
import { ViewCategory } from 'app/site/motions/models/view-category';
|
import { ViewCategory } from 'app/site/motions/models/view-category';
|
||||||
import { ViewCreateMotion } from 'app/site/motions/models/view-create-motion';
|
import { ViewCreateMotion } from 'app/site/motions/models/view-create-motion';
|
||||||
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
||||||
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
|
||||||
import { ViewMotionChangeRecommendation } from 'app/site/motions/models/view-motion-change-recommendation';
|
import { ViewMotionChangeRecommendation } from 'app/site/motions/models/view-motion-change-recommendation';
|
||||||
import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph';
|
import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph';
|
||||||
import { ViewTag } from 'app/site/tags/models/view-tag';
|
import { ViewTag } from 'app/site/tags/models/view-tag';
|
||||||
@ -250,11 +248,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
|||||||
*/
|
*/
|
||||||
public blockObserver: BehaviorSubject<ViewMotionBlock[]>;
|
public blockObserver: BehaviorSubject<ViewMotionBlock[]>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Subject for mediafiles
|
|
||||||
*/
|
|
||||||
public mediafilesObserver: BehaviorSubject<ViewMediafile[]>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subject for tags
|
* Subject for tags
|
||||||
*/
|
*/
|
||||||
@ -445,7 +438,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
|||||||
private userRepo: UserRepositoryService,
|
private userRepo: UserRepositoryService,
|
||||||
private notifyService: NotifyService,
|
private notifyService: NotifyService,
|
||||||
private tagRepo: TagRepositoryService,
|
private tagRepo: TagRepositoryService,
|
||||||
private mediaFilerepo: MediafileRepositoryService,
|
|
||||||
private workflowRepo: WorkflowRepositoryService,
|
private workflowRepo: WorkflowRepositoryService,
|
||||||
private blockRepo: MotionBlockRepositoryService,
|
private blockRepo: MotionBlockRepositoryService,
|
||||||
private itemRepo: ItemRepositoryService,
|
private itemRepo: ItemRepositoryService,
|
||||||
@ -462,7 +454,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
|||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
// get required information from the repositories
|
// get required information from the repositories
|
||||||
this.tagObserver = this.tagRepo.getViewModelListBehaviorSubject();
|
this.tagObserver = this.tagRepo.getViewModelListBehaviorSubject();
|
||||||
this.mediafilesObserver = this.mediaFilerepo.getViewModelListBehaviorSubject();
|
|
||||||
this.workflowObserver = this.workflowRepo.getViewModelListBehaviorSubject();
|
this.workflowObserver = this.workflowRepo.getViewModelListBehaviorSubject();
|
||||||
this.blockObserver = this.blockRepo.getViewModelListBehaviorSubject();
|
this.blockObserver = this.blockRepo.getViewModelListBehaviorSubject();
|
||||||
this.motionObserver = this.repo.getViewModelListBehaviorSubject();
|
this.motionObserver = this.repo.getViewModelListBehaviorSubject();
|
||||||
@ -501,17 +492,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
|||||||
this.configService
|
this.configService
|
||||||
.get<boolean>('motions_show_sequential_numbers')
|
.get<boolean>('motions_show_sequential_numbers')
|
||||||
.subscribe(shown => (this.showSequential = shown));
|
.subscribe(shown => (this.showSequential = shown));
|
||||||
// disable the selector for attachments if there are none
|
|
||||||
this.mediafilesObserver.subscribe(() => {
|
|
||||||
if (this.contentForm) {
|
|
||||||
const attachmentsCtrl = this.contentForm.get('attachments_id');
|
|
||||||
if (this.mediafilesObserver.value.length === 0) {
|
|
||||||
attachmentsCtrl.disable();
|
|
||||||
} else {
|
|
||||||
attachmentsCtrl.enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update statute paragraphs
|
// Update statute paragraphs
|
||||||
this.statuteRepo.getViewModelListObservable().subscribe(newViewStatuteParagraphs => {
|
this.statuteRepo.getViewModelListObservable().subscribe(newViewStatuteParagraphs => {
|
||||||
@ -1546,30 +1526,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
|||||||
this.personalNoteService.savePersonalNote(this.motion, this.motion.personalNote).then(null, this.raiseError);
|
this.personalNoteService.savePersonalNote(this.motion, this.motion.personalNote).then(null, this.raiseError);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for the upload attachments button
|
|
||||||
*/
|
|
||||||
public onUploadAttachmentsButton(templateRef: TemplateRef<string>): void {
|
|
||||||
this.dialogService.open(templateRef, {
|
|
||||||
maxHeight: '90vh',
|
|
||||||
width: '750px',
|
|
||||||
maxWidth: '90vw'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for successful uploads.
|
|
||||||
* Adds the IDs of the upload process to the mediafile selector
|
|
||||||
*
|
|
||||||
* @param fileIds the ids of the uploads if they were successful
|
|
||||||
*/
|
|
||||||
public uploadSuccess(fileIds: number[]): void {
|
|
||||||
const currentAttachments = this.contentForm.get('attachments_id').value as number[];
|
|
||||||
const newAttachments = [...currentAttachments, ...fileIds];
|
|
||||||
this.contentForm.get('attachments_id').setValue(newAttachments);
|
|
||||||
this.dialogService.closeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for upload errors
|
* Handler for upload errors
|
||||||
*
|
*
|
||||||
|
@ -68,14 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Attachments -->
|
<!-- Attachments -->
|
||||||
<os-search-value-selector
|
<os-attachment-control [controlName]="topicForm.get('attachments_id')" (errorHandler)="raiseError($event)"></os-attachment-control>
|
||||||
ngDefaultControl
|
|
||||||
[form]="topicForm"
|
|
||||||
[formControl]="topicForm.get('attachments_id')"
|
|
||||||
[multiple]="true"
|
|
||||||
listname="{{ 'Attachments' | translate }}"
|
|
||||||
[InputListValues]="mediafilesObserver"
|
|
||||||
></os-search-value-selector>
|
|
||||||
|
|
||||||
<div *ngIf="newTopic">
|
<div *ngIf="newTopic">
|
||||||
<!-- Visibility -->
|
<!-- Visibility -->
|
||||||
@ -93,9 +86,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="topicForm"
|
|
||||||
[formControl]="topicForm.get('agenda_parent_id')"
|
[formControl]="topicForm.get('agenda_parent_id')"
|
||||||
[multiple]="false"
|
|
||||||
[includeNone]="true"
|
[includeNone]="true"
|
||||||
listname="{{ 'Parent agenda item' | translate }}"
|
listname="{{ 'Parent agenda item' | translate }}"
|
||||||
[InputListValues]="itemObserver"
|
[InputListValues]="itemObserver"
|
||||||
|
@ -15,10 +15,8 @@ import { BehaviorSubject } from 'rxjs';
|
|||||||
import { ItemVisibilityChoices } from 'app/shared/models/agenda/item';
|
import { ItemVisibilityChoices } from 'app/shared/models/agenda/item';
|
||||||
import { CreateTopic } from '../../models/create-topic';
|
import { CreateTopic } from '../../models/create-topic';
|
||||||
import { Topic } from 'app/shared/models/topics/topic';
|
import { Topic } from 'app/shared/models/topics/topic';
|
||||||
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
|
||||||
import { ViewItem } from 'app/site/agenda/models/view-item';
|
|
||||||
import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service';
|
|
||||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||||
|
import { ViewItem } from 'app/site/agenda/models/view-item';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detail page for topics.
|
* Detail page for topics.
|
||||||
@ -49,11 +47,6 @@ export class TopicDetailComponent extends BaseViewComponent {
|
|||||||
*/
|
*/
|
||||||
public topicForm: FormGroup;
|
public topicForm: FormGroup;
|
||||||
|
|
||||||
/**
|
|
||||||
* Subject for mediafiles
|
|
||||||
*/
|
|
||||||
public mediafilesObserver: BehaviorSubject<ViewMediafile[]>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subject for agenda items
|
* Subject for agenda items
|
||||||
*/
|
*/
|
||||||
@ -88,7 +81,6 @@ export class TopicDetailComponent extends BaseViewComponent {
|
|||||||
private repo: TopicRepositoryService,
|
private repo: TopicRepositoryService,
|
||||||
private promptService: PromptService,
|
private promptService: PromptService,
|
||||||
private operator: OperatorService,
|
private operator: OperatorService,
|
||||||
private mediafileRepo: MediafileRepositoryService,
|
|
||||||
private itemRepo: ItemRepositoryService,
|
private itemRepo: ItemRepositoryService,
|
||||||
private sanitizer: DomSanitizer
|
private sanitizer: DomSanitizer
|
||||||
) {
|
) {
|
||||||
@ -96,7 +88,6 @@ export class TopicDetailComponent extends BaseViewComponent {
|
|||||||
this.getTopicByUrl();
|
this.getTopicByUrl();
|
||||||
this.createForm();
|
this.createForm();
|
||||||
|
|
||||||
this.mediafilesObserver = this.mediafileRepo.getViewModelListBehaviorSubject();
|
|
||||||
this.itemObserver = this.itemRepo.getViewModelListBehaviorSubject();
|
this.itemObserver = this.itemRepo.getViewModelListBehaviorSubject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user