Merge pull request #4452 from FinnStutzenstein/reworkPersonalNotes
rework personal notes
This commit is contained in:
commit
0290449b8b
@ -40,15 +40,15 @@ export class AppComponent {
|
||||
*/
|
||||
public constructor(
|
||||
translate: TranslateService,
|
||||
appRef: ApplicationRef,
|
||||
servertimeService: ServertimeService,
|
||||
operator: OperatorService,
|
||||
loginDataService: LoginDataService,
|
||||
constantsService: ConstantsService, // Needs to be started, so it can register itself to the WebsocketService
|
||||
servertimeService: ServertimeService,
|
||||
themeService: ThemeService,
|
||||
countUsersService: CountUsersService, // Needed to register itself.
|
||||
configService: ConfigService,
|
||||
loadFontService: LoadFontService,
|
||||
appRef: ApplicationRef
|
||||
loadFontService: LoadFontService
|
||||
) {
|
||||
// manually add the supported languages
|
||||
translate.addLangs(['en', 'de', 'cs']);
|
||||
@ -66,9 +66,7 @@ export class AppComponent {
|
||||
filter(s => s),
|
||||
take(1)
|
||||
)
|
||||
.subscribe(() => {
|
||||
servertimeService.startScheduler();
|
||||
});
|
||||
.subscribe(() => servertimeService.startScheduler());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,6 +104,9 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the observation of dependency subjects.
|
||||
*/
|
||||
protected setupDependencyObservation(): void {
|
||||
if (this.depsModelCtors) {
|
||||
this.DS.secondaryModelChangeSubject.subscribe(model => {
|
||||
@ -112,17 +115,26 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
||||
});
|
||||
if (dependencyChanged) {
|
||||
const viewModel = this.viewModelStoreService.get(model.collectionString, model.id);
|
||||
|
||||
// if an domain object we need was added or changed, update viewModelStore
|
||||
this.getViewModelList().forEach(ownViewModel => {
|
||||
ownViewModel.updateDependencies(viewModel);
|
||||
});
|
||||
this.updateAllObservables(model.id);
|
||||
this.updateDependency(viewModel);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all models with the provided `update` which is a dependency.
|
||||
*
|
||||
* @param update The dependency to update.
|
||||
*/
|
||||
protected updateDependency(update: BaseViewModel): void {
|
||||
// if an domain object we need was added or changed, update viewModelStore
|
||||
this.getViewModelList().forEach(ownViewModel => {
|
||||
ownViewModel.updateDependencies(update);
|
||||
this.updateViewModelObservable(ownViewModel.id);
|
||||
});
|
||||
this.updateViewModelListObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the update to an existing model. So called "update"-function
|
||||
* @param update the update that should be created
|
||||
|
@ -21,7 +21,6 @@ import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||
import { MotionChangeRecommendation } from 'app/shared/models/motions/motion-change-reco';
|
||||
import { MotionPoll } from 'app/shared/models/motions/motion-poll';
|
||||
import { OSTreeSortEvent } from 'app/shared/components/sorting-tree/sorting-tree.component';
|
||||
import { PersonalNoteService } from '../../ui-services/personal-note.service';
|
||||
import { TreeService } from 'app/core/ui-services/tree.service';
|
||||
import { User } from 'app/shared/models/users/user';
|
||||
import { ViewMotionChangeRecommendation } from 'app/site/motions/models/view-change-recommendation';
|
||||
@ -40,6 +39,10 @@ import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block';
|
||||
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
||||
import { ViewTag } from 'app/site/tags/models/view-tag';
|
||||
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||
import { PersonalNote, PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
||||
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||
|
||||
/**
|
||||
* Repository Services for motions (and potentially categories)
|
||||
@ -67,7 +70,6 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
* @param httpService OpenSlides own Http service
|
||||
* @param lineNumbering Line numbering for motion text
|
||||
* @param diff Display changes in motion text as diff.
|
||||
* @param personalNoteService service fo personal notes
|
||||
*/
|
||||
public constructor(
|
||||
DS: DataStoreService,
|
||||
@ -78,8 +80,8 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
private readonly lineNumbering: LinenumberingService,
|
||||
private readonly diff: DiffService,
|
||||
private treeService: TreeService,
|
||||
private personalNoteService: PersonalNoteService,
|
||||
private translate: TranslateService
|
||||
private translate: TranslateService,
|
||||
private operator: OperatorService
|
||||
) {
|
||||
super(DS, mapperService, viewModelStoreService, Motion, [
|
||||
Category,
|
||||
@ -89,7 +91,8 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
MotionBlock,
|
||||
Mediafile,
|
||||
Tag,
|
||||
MotionChangeRecommendation
|
||||
MotionChangeRecommendation,
|
||||
PersonalNote
|
||||
]);
|
||||
}
|
||||
|
||||
@ -157,6 +160,7 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
if (workflow) {
|
||||
state = workflow.getStateById(motion.state_id);
|
||||
}
|
||||
const personalNote = this.getPersonalNoteForMotion(motion.id);
|
||||
const viewMotion = new ViewMotion(
|
||||
motion,
|
||||
category,
|
||||
@ -169,7 +173,8 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
attachments,
|
||||
tags,
|
||||
parent,
|
||||
changeRecommendations
|
||||
changeRecommendations,
|
||||
personalNote
|
||||
);
|
||||
viewMotion.getIdentifierOrTitle = () => this.getIdentifierOrTitle(viewMotion);
|
||||
viewMotion.getTitle = () => this.getTitle(viewMotion);
|
||||
@ -180,6 +185,60 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
return viewMotion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the personal note content for one motion by their id
|
||||
*
|
||||
* @param motionId the id of the motion
|
||||
* @returns the personal note content for this motion or null
|
||||
*/
|
||||
private getPersonalNoteForMotion(motionId: number): PersonalNoteContent | null {
|
||||
if (this.operator.isAnonymous) {
|
||||
return;
|
||||
}
|
||||
|
||||
const personalNote = this.viewModelStoreService.find(ViewPersonalNote, pn => {
|
||||
return pn.userId === this.operator.user.id;
|
||||
});
|
||||
|
||||
if (!personalNote) {
|
||||
return;
|
||||
}
|
||||
|
||||
const notes = personalNote.notes;
|
||||
const collection = Motion.COLLECTIONSTRING;
|
||||
if (notes && notes[collection] && notes[collection][motionId]) {
|
||||
return notes[collection][motionId];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param update
|
||||
*
|
||||
* @overwrite
|
||||
*/
|
||||
protected updateDependency(update: BaseViewModel): void {
|
||||
if (update instanceof ViewPersonalNote) {
|
||||
if (this.operator.isAnonymous || update.userId !== this.operator.user.id) {
|
||||
return;
|
||||
}
|
||||
const notes = update.notes;
|
||||
const collection = Motion.COLLECTIONSTRING;
|
||||
|
||||
this.getViewModelList().forEach(ownViewModel => {
|
||||
if (notes && notes[collection] && notes[collection][ownViewModel.id]) {
|
||||
ownViewModel.personalNote = notes[collection][ownViewModel.id];
|
||||
} else {
|
||||
ownViewModel.personalNote = null;
|
||||
}
|
||||
this.updateViewModelObservable(ownViewModel.id);
|
||||
});
|
||||
this.updateViewModelListObservable();
|
||||
} else {
|
||||
super.updateDependency(update);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom hook into the observables. The motions get a virtual weight (a sequential number) for the
|
||||
* call list order. One can just sort for this number instead of dealing with the sort parent id and weight.
|
||||
@ -194,10 +253,6 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
||||
let virtualWeightCounter = 0;
|
||||
while (!(m = iterator.next()).done) {
|
||||
m.value.callListWeight = virtualWeightCounter++;
|
||||
const motion = m.value;
|
||||
this.personalNoteService
|
||||
.getPersonalNoteObserver(motion.motion)
|
||||
.subscribe(note => (motion.personalNote = note));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -33,20 +33,20 @@ export class PersonalNoteRepositoryService extends BaseRepository<ViewPersonalNo
|
||||
};
|
||||
|
||||
protected createViewModel(personalNote: PersonalNote): ViewPersonalNote {
|
||||
const viewPersonalNote = new ViewPersonalNote();
|
||||
const viewPersonalNote = new ViewPersonalNote(personalNote);
|
||||
viewPersonalNote.getVerboseName = this.getVerboseName;
|
||||
return viewPersonalNote;
|
||||
}
|
||||
|
||||
public async create(personalNote: PersonalNote): Promise<Identifiable> {
|
||||
throw new Error('TODO');
|
||||
throw new Error('Not supported');
|
||||
}
|
||||
|
||||
public async update(personalNote: Partial<PersonalNote>, viewPersonalNote: ViewPersonalNote): Promise<void> {
|
||||
throw new Error('TODO');
|
||||
throw new Error('Not supported');
|
||||
}
|
||||
|
||||
public async delete(viewPersonalNote: ViewPersonalNote): Promise<void> {
|
||||
throw new Error('TODO');
|
||||
throw new Error('Not supported');
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,16 @@ import { BaseRepository } from '../repositories/base-repository';
|
||||
export interface OsFilter {
|
||||
property: string;
|
||||
label?: string;
|
||||
options: (OsFilterOption | string)[];
|
||||
options: OsFilterOptions;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of all filter options. This is an array of options. One option
|
||||
* can be OsFilterOption or a string.
|
||||
*/
|
||||
export type OsFilterOptions = (OsFilterOption | string)[];
|
||||
|
||||
/**
|
||||
* Describes a list of available options for a drop down menu of a filter.
|
||||
* A filter condition of null will be interpreted as a negative filter
|
||||
|
@ -1,27 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
|
||||
import { DataStoreService } from '../core-services/data-store.service';
|
||||
import { OperatorService } from '../core-services/operator.service';
|
||||
import { PersonalNote, PersonalNoteObject, PersonalNoteContent } from '../../shared/models/users/personal-note';
|
||||
import { BaseModel } from '../../shared/models/base/base-model';
|
||||
import { HttpService } from '../core-services/http.service';
|
||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||
|
||||
/**
|
||||
* All subjects are organized by the collection string and id of the model.
|
||||
*/
|
||||
interface PersonalNoteSubjects {
|
||||
[collectionString: string]: {
|
||||
[id: number]: BehaviorSubject<PersonalNoteContent>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles personal notes.
|
||||
*
|
||||
* Get updated by subscribing to `getPersonalNoteObserver`. Save personal notes by calling
|
||||
* `savePersonalNote`.
|
||||
* Handles saving personal notes.
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -33,12 +20,7 @@ export class PersonalNoteService {
|
||||
private personalNoteObject: PersonalNoteObject;
|
||||
|
||||
/**
|
||||
* All subjects for all observers.
|
||||
*/
|
||||
private subjects: PersonalNoteSubjects = {};
|
||||
|
||||
/**
|
||||
* Watches for changes in the personal note model.
|
||||
* Watches for changes in the personal note model and the operator.
|
||||
*/
|
||||
public constructor(private operator: OperatorService, private DS: DataStoreService, private http: HttpService) {
|
||||
operator.getUserObservable().subscribe(() => this.updatePersonalNoteObject());
|
||||
@ -61,51 +43,6 @@ export class PersonalNoteService {
|
||||
const operatorId = this.operator.user.id;
|
||||
const objects = this.DS.filter(PersonalNote, pn => pn.user_id === operatorId);
|
||||
this.personalNoteObject = objects.length === 0 ? null : objects[0];
|
||||
|
||||
this.updateSubscribers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all subscribers.
|
||||
*/
|
||||
private updateSubscribers(): void {
|
||||
Object.keys(this.subjects).forEach(collectionString => {
|
||||
Object.keys(this.subjects[collectionString]).forEach(id => {
|
||||
this.subjects[collectionString][id].next(this.getPersonalNoteContent(collectionString, +id));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content from a note by the collection string and id.
|
||||
*/
|
||||
private getPersonalNoteContent(collectionString: string, id: number): PersonalNoteContent {
|
||||
if (
|
||||
!this.personalNoteObject ||
|
||||
!this.personalNoteObject.notes ||
|
||||
!this.personalNoteObject.notes[collectionString] ||
|
||||
!this.personalNoteObject.notes[collectionString][id]
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return this.personalNoteObject.notes[collectionString][id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an observalbe for a given BaseModel.
|
||||
* @param model The model to observe the personal note from.
|
||||
*/
|
||||
public getPersonalNoteObserver(model: BaseModel): Observable<PersonalNoteContent> {
|
||||
if (!this.subjects[model.collectionString]) {
|
||||
this.subjects[model.collectionString] = {};
|
||||
}
|
||||
if (!this.subjects[model.collectionString][model.id]) {
|
||||
const subject = new BehaviorSubject<PersonalNoteContent>(
|
||||
this.getPersonalNoteContent(model.collectionString, model.id)
|
||||
);
|
||||
this.subjects[model.collectionString][model.id] = subject;
|
||||
}
|
||||
return this.subjects[model.collectionString][model.id].asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +50,7 @@ export class PersonalNoteService {
|
||||
* @param model The model the content belongs to
|
||||
* @param content The new content.
|
||||
*/
|
||||
public async savePersonalNote(model: BaseModel, content: PersonalNoteContent): Promise<void> {
|
||||
public async savePersonalNote(model: BaseModel | BaseViewModel, content: PersonalNoteContent): Promise<void> {
|
||||
const pnObject: Partial<PersonalNoteObject> = this.personalNoteObject || {};
|
||||
if (!pnObject.notes) {
|
||||
pnObject.notes = {};
|
||||
@ -129,19 +66,4 @@ export class PersonalNoteService {
|
||||
await this.http.put(`rest/users/personal-note/${pnObject.id}/`, pnObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the 'favorite' status of a personal note, without changing other information
|
||||
*
|
||||
* @param model
|
||||
* @param star The new status to set
|
||||
*/
|
||||
public async setPersonalNoteStar(model: BaseModel, star: boolean): Promise<void> {
|
||||
let content: PersonalNoteContent = this.getPersonalNoteContent(model.collectionString, model.id);
|
||||
if (!content) {
|
||||
content = { note: null, star: star };
|
||||
}
|
||||
content.star = star;
|
||||
return this.savePersonalNote(model, content);
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ export class ViewMotion extends BaseAgendaViewModel implements Searchable {
|
||||
protected _tags: ViewTag[];
|
||||
protected _parent: ViewMotion;
|
||||
protected _changeRecommendations: ViewMotionChangeRecommendation[];
|
||||
public personalNote: PersonalNoteContent;
|
||||
public personalNote?: PersonalNoteContent;
|
||||
|
||||
/**
|
||||
* Is set by the repository; this is the order of the flat call list given by
|
||||
@ -314,7 +314,7 @@ export class ViewMotion extends BaseAgendaViewModel implements Searchable {
|
||||
* @returns the current state
|
||||
*/
|
||||
public get star(): boolean {
|
||||
return this.personalNote && this.personalNote.star ? true : false;
|
||||
return !!this.personalNote && !!this.personalNote.star;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,7 +323,7 @@ export class ViewMotion extends BaseAgendaViewModel implements Searchable {
|
||||
* @returns true if personalContent is present and has notes
|
||||
*/
|
||||
public get hasNotes(): boolean {
|
||||
return this.personalNote && this.personalNote.note ? true : false;
|
||||
return !!this.personalNote && !!this.personalNote.note;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -372,7 +372,8 @@ export class ViewMotion extends BaseAgendaViewModel implements Searchable {
|
||||
attachments?: ViewMediafile[],
|
||||
tags?: ViewTag[],
|
||||
parent?: ViewMotion,
|
||||
changeRecommendations?: ViewMotionChangeRecommendation[]
|
||||
changeRecommendations?: ViewMotionChangeRecommendation[],
|
||||
personalNote?: PersonalNoteContent
|
||||
) {
|
||||
super(Motion.COLLECTIONSTRING);
|
||||
this._motion = motion;
|
||||
@ -387,6 +388,7 @@ export class ViewMotion extends BaseAgendaViewModel implements Searchable {
|
||||
this._tags = tags;
|
||||
this._parent = parent;
|
||||
this._changeRecommendations = changeRecommendations;
|
||||
this.personalNote = personalNote;
|
||||
}
|
||||
|
||||
public getAgendaItem(): ViewItem {
|
||||
|
@ -145,7 +145,7 @@
|
||||
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
|
||||
|
||||
<!-- Personal note -->
|
||||
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
||||
<os-personal-note *ngIf="!editMotion && !operator.isAnonymous" [motion]="motion"></os-personal-note>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #desktopView>
|
||||
@ -157,7 +157,7 @@
|
||||
</div>
|
||||
|
||||
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
|
||||
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
||||
<os-personal-note *ngIf="!editMotion && !operator.isAnonymous" [motion]="motion"></os-personal-note>
|
||||
</div>
|
||||
<div class="desktop-right">
|
||||
<!-- Content -->
|
||||
|
@ -29,7 +29,6 @@ import { MotionPdfExportService } from 'app/site/motions/services/motion-pdf-exp
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { NotifyService } from 'app/core/core-services/notify.service';
|
||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||
import { PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
||||
import { PersonalNoteService } from 'app/core/ui-services/personal-note.service';
|
||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||
import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions/statute-paragraph-repository.service';
|
||||
@ -316,11 +315,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
*/
|
||||
public highlightedLineTyping: number;
|
||||
|
||||
/**
|
||||
* The personal notes' content for this motion
|
||||
*/
|
||||
public personalNoteContent: PersonalNoteContent;
|
||||
|
||||
/**
|
||||
* new state extension label to be submitted, if state extensions can be set
|
||||
*/
|
||||
@ -379,7 +373,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
translate: TranslateService,
|
||||
matSnackBar: MatSnackBar,
|
||||
public vp: ViewportService,
|
||||
private operator: OperatorService,
|
||||
public operator: OperatorService,
|
||||
public perms: LocalPermissionsService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
@ -562,9 +556,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
if (newViewMotion) {
|
||||
this.motion = newViewMotion;
|
||||
this.newStateExtension = this.motion.stateExtension;
|
||||
this.personalNoteService.getPersonalNoteObserver(this.motion.motion).subscribe(pn => {
|
||||
this.personalNoteContent = pn;
|
||||
});
|
||||
this.patchForm(this.motion);
|
||||
}
|
||||
});
|
||||
@ -1400,8 +1391,16 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
/**
|
||||
* Toggles the favorite status
|
||||
*/
|
||||
public async toggleFavorite(): Promise<void> {
|
||||
this.personalNoteService.setPersonalNoteStar(this.motion.motion, !this.motion.star);
|
||||
public toggleFavorite(): void {
|
||||
if (!this.motion.personalNote) {
|
||||
this.motion.personalNote = {
|
||||
note: '',
|
||||
star: true
|
||||
};
|
||||
} else {
|
||||
this.motion.personalNote.star = !this.motion.personalNote.star;
|
||||
}
|
||||
this.personalNoteService.savePersonalNote(this.motion, this.motion.personalNote).then(null, this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
<ng-container class="meta-text-block-content">
|
||||
<ng-container *ngIf="!isEditMode">
|
||||
<div *ngIf="personalNote" [innerHTML]="personalNote.note"></div>
|
||||
<div class="no-content" *ngIf="!personalNote" translate>
|
||||
<div *ngIf="motion && motion.personalNote" [innerHTML]="motion.personalNote.note"></div>
|
||||
<div class="no-content" *ngIf="!motion || !motion.personalNote" translate>
|
||||
No personal note
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -25,7 +25,7 @@
|
||||
matTooltip="{{ 'Edit' | translate }}">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button *ngIf="!isEditMode && personalNote" (click)="printPersonalNote()"
|
||||
<button mat-icon-button *ngIf="!isEditMode && motion && motion.personalNote" (click)="printPersonalNote()"
|
||||
matTooltip="{{ 'Export personal note only' | translate }}">
|
||||
<mat-icon>picture_as_pdf</mat-icon>
|
||||
</button>
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { Component, Input, OnDestroy } from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { BaseComponent } from 'app/base.component';
|
||||
import { MotionPdfExportService } from 'app/site/motions/services/motion-pdf-export.service';
|
||||
import { PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
||||
@ -17,34 +15,12 @@ import { ViewMotion } from 'app/site/motions/models/view-motion';
|
||||
templateUrl: './personal-note.component.html',
|
||||
styleUrls: ['./personal-note.component.scss']
|
||||
})
|
||||
export class PersonalNoteComponent extends BaseComponent implements OnDestroy {
|
||||
export class PersonalNoteComponent extends BaseComponent {
|
||||
/**
|
||||
* The motion, which the personal note belong to.
|
||||
*/
|
||||
private _motion: ViewMotion;
|
||||
|
||||
/**
|
||||
* Sets the motion. If the motion updates (changes, and so on), the subscription
|
||||
* for the personal note will be established.
|
||||
*/
|
||||
@Input()
|
||||
public set motion(motion: ViewMotion) {
|
||||
this._motion = motion;
|
||||
if (this.personalNoteSubscription) {
|
||||
this.personalNoteSubscription.unsubscribe();
|
||||
}
|
||||
if (motion && motion.motion) {
|
||||
this.personalNoteSubscription = this.personalNoteService
|
||||
.getPersonalNoteObserver(motion.motion)
|
||||
.subscribe(pn => {
|
||||
this.personalNote = pn;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get motion(): ViewMotion {
|
||||
return this._motion;
|
||||
}
|
||||
public motion: ViewMotion;
|
||||
|
||||
/**
|
||||
* The edit form for the note
|
||||
@ -56,16 +32,6 @@ export class PersonalNoteComponent extends BaseComponent implements OnDestroy {
|
||||
*/
|
||||
public isEditMode = false;
|
||||
|
||||
/**
|
||||
* The personal note.
|
||||
*/
|
||||
public personalNote: PersonalNoteContent;
|
||||
|
||||
/**
|
||||
* The subscription for the personal note.
|
||||
*/
|
||||
private personalNoteSubscription: Subscription;
|
||||
|
||||
/**
|
||||
* Constructor. Creates form
|
||||
*
|
||||
@ -90,7 +56,7 @@ export class PersonalNoteComponent extends BaseComponent implements OnDestroy {
|
||||
public editPersonalNote(): void {
|
||||
this.personalNoteForm.reset();
|
||||
this.personalNoteForm.patchValue({
|
||||
note: this.personalNote ? this.personalNote.note : ''
|
||||
note: this.motion.personalNote ? this.motion.personalNote.note : ''
|
||||
});
|
||||
this.isEditMode = true;
|
||||
}
|
||||
@ -100,8 +66,8 @@ export class PersonalNoteComponent extends BaseComponent implements OnDestroy {
|
||||
*/
|
||||
public async savePersonalNote(): Promise<void> {
|
||||
let content: PersonalNoteContent;
|
||||
if (this.personalNote) {
|
||||
content = Object.assign({}, this.personalNote);
|
||||
if (this.motion.personalNote) {
|
||||
content = Object.assign({}, this.motion.personalNote);
|
||||
content.note = this.personalNoteForm.get('note').value;
|
||||
} else {
|
||||
content = {
|
||||
@ -117,19 +83,10 @@ export class PersonalNoteComponent extends BaseComponent implements OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the subscription if this component isn't needed anymore.
|
||||
*/
|
||||
public ngOnDestroy(): void {
|
||||
if (this.personalNoteSubscription) {
|
||||
this.personalNoteSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a pdf export of the personal note
|
||||
*/
|
||||
public printPersonalNote(): void {
|
||||
this.pdfService.exportPersonalNote(this.personalNote, this.motion);
|
||||
this.pdfService.exportPersonalNote(this.motion.personalNote, this.motion);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { BaseFilterListService, OsFilter, OsFilterOption } from 'app/core/ui-services/base-filter-list.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { BaseFilterListService, OsFilter, OsFilterOptions } from 'app/core/ui-services/base-filter-list.service';
|
||||
import { Motion } from 'app/shared/models/motions/motion';
|
||||
import { ViewMotion } from '../models/view-motion';
|
||||
import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service';
|
||||
@ -9,7 +11,6 @@ import { StorageService } from 'app/core/core-services/storage.service';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
|
||||
import { MotionCommentSectionRepositoryService } from 'app/core/repositories/motions/motion-comment-section-repository.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { ViewWorkflow } from '../models/view-workflow';
|
||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||
@ -25,13 +26,18 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
||||
* generated dynamically, as the options change with the datastore
|
||||
*/
|
||||
public get filterOptions(): OsFilter[] {
|
||||
return [
|
||||
let filterOptions = [
|
||||
this.flowFilterOptions,
|
||||
this.categoryFilterOptions,
|
||||
this.motionBlockFilterOptions,
|
||||
this.recommendationFilterOptions,
|
||||
this.motionCommentFilterOptions
|
||||
].concat(this.staticFilterOptions);
|
||||
];
|
||||
|
||||
if (!this.operator.isAnonymous) {
|
||||
filterOptions = filterOptions.concat(this.personalNoteFilterOptions);
|
||||
}
|
||||
return filterOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,7 +87,7 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
||||
options: []
|
||||
};
|
||||
|
||||
public staticFilterOptions = [
|
||||
public personalNoteFilterOptions = [
|
||||
{
|
||||
property: 'star',
|
||||
label: this.translate.instant('Favorites'),
|
||||
@ -143,32 +149,22 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
||||
this.subscribeCategories();
|
||||
this.subscribeMotionBlocks();
|
||||
this.subscribeComments();
|
||||
}
|
||||
|
||||
// TODO: Notes/Favorite
|
||||
// does not work, some cloning error. I want to:
|
||||
// 'check all items in filterService against this function, in the
|
||||
// scope of motion-filter.service'
|
||||
// public getNoteFilterFn(): Function {
|
||||
// const notesRepo = this.notesRepo;
|
||||
// return (m: ViewMotion) => {
|
||||
// return notesRepo.hasPersonalNote('Motion', m.id)
|
||||
// }
|
||||
// };
|
||||
this.operator.getUserObservable().subscribe(() => {
|
||||
this.updateFilterDefinitions(this.filterOptions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscibes to changing MotionBlocks, and updates the filter accordingly
|
||||
*/
|
||||
private subscribeMotionBlocks(): void {
|
||||
this.motionBlockRepo.getViewModelListObservable().subscribe(motionBlocks => {
|
||||
const motionBlockOptions = [];
|
||||
motionBlocks.forEach(mb => {
|
||||
motionBlockOptions.push({
|
||||
condition: mb.id,
|
||||
label: mb.title,
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
const motionBlockOptions: OsFilterOptions = motionBlocks.map(mb => ({
|
||||
condition: mb.id,
|
||||
label: mb.title,
|
||||
isActive: false
|
||||
}));
|
||||
if (motionBlocks.length) {
|
||||
motionBlockOptions.push('-');
|
||||
motionBlockOptions.push({
|
||||
@ -187,14 +183,11 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
||||
*/
|
||||
private subscribeCategories(): void {
|
||||
this.categoryRepo.getSortedViewModelListObservable().subscribe(categories => {
|
||||
const categoryOptions: (OsFilterOption | string)[] = [];
|
||||
categories.forEach(cat => {
|
||||
categoryOptions.push({
|
||||
condition: cat.id,
|
||||
label: cat.prefixedName,
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
const categoryOptions: OsFilterOptions = categories.map(cat => ({
|
||||
condition: cat.id,
|
||||
label: cat.prefixedName,
|
||||
isActive: false
|
||||
}));
|
||||
if (categories.length) {
|
||||
categoryOptions.push('-');
|
||||
categoryOptions.push({
|
||||
@ -235,10 +228,10 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
||||
* set config options
|
||||
*/
|
||||
private updateWorkflows(): void {
|
||||
const workflowOptions: (OsFilterOption | string)[] = [];
|
||||
const workflowOptions: OsFilterOptions = [];
|
||||
const finalStates: number[] = [];
|
||||
const nonFinalStates: number[] = [];
|
||||
const recommendationOptions: (OsFilterOption | string)[] = [];
|
||||
const recommendationOptions: OsFilterOptions = [];
|
||||
if (!this.currentWorkflows) {
|
||||
return;
|
||||
}
|
||||
@ -304,14 +297,11 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
||||
*/
|
||||
private subscribeComments(): void {
|
||||
this.commentRepo.getViewModelListObservable().subscribe(comments => {
|
||||
const commentOptions: (OsFilterOption | string)[] = [];
|
||||
comments.forEach(comm => {
|
||||
commentOptions.push({
|
||||
condition: comm.id,
|
||||
label: comm.name,
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
const commentOptions: OsFilterOptions = comments.map(comment => ({
|
||||
condition: comment.id,
|
||||
label: comment.name,
|
||||
isActive: false
|
||||
}));
|
||||
if (comments.length) {
|
||||
commentOptions.push('-');
|
||||
commentOptions.push({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||
import { PersonalNote } from 'app/shared/models/users/personal-note';
|
||||
import { PersonalNote, PersonalNotesFormat } from 'app/shared/models/users/personal-note';
|
||||
|
||||
export class ViewPersonalNote extends BaseViewModel {
|
||||
public static COLLECTIONSTRING = PersonalNote.COLLECTIONSTRING;
|
||||
@ -7,11 +7,19 @@ export class ViewPersonalNote extends BaseViewModel {
|
||||
private _personalNote: PersonalNote;
|
||||
|
||||
public get personalNote(): PersonalNote {
|
||||
return this._personalNote ? this._personalNote : null;
|
||||
return this._personalNote;
|
||||
}
|
||||
|
||||
public get id(): number {
|
||||
return this.personalNote ? this.personalNote.id : null;
|
||||
return this.personalNote.id;
|
||||
}
|
||||
|
||||
public get userId(): number {
|
||||
return this.personalNote.user_id;
|
||||
}
|
||||
|
||||
public get notes(): PersonalNotesFormat {
|
||||
return this.personalNote.notes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -19,7 +27,7 @@ export class ViewPersonalNote extends BaseViewModel {
|
||||
*/
|
||||
public getVerboseName;
|
||||
|
||||
public constructor(personalNote?: PersonalNote) {
|
||||
public constructor(personalNote: PersonalNote) {
|
||||
super(PersonalNote.COLLECTIONSTRING);
|
||||
this._personalNote = personalNote;
|
||||
}
|
||||
@ -28,7 +36,5 @@ export class ViewPersonalNote extends BaseViewModel {
|
||||
return this.personalNote ? this.personalNote.toString() : null;
|
||||
};
|
||||
|
||||
public updateDependencies(update: BaseViewModel): void {
|
||||
throw new Error('Todo');
|
||||
}
|
||||
public updateDependencies(update: BaseViewModel): void {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user