Merge pull request #4592 from MaximilianKrambach/manyStars

bulk set/unset favorite status
This commit is contained in:
Sean 2019-04-15 12:24:46 +02:00 committed by GitHub
commit 1bd9f09dd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 11 deletions

View File

@ -60,6 +60,42 @@ export class PersonalNoteService {
} }
pnObject.notes[model.collectionString][model.id] = content; pnObject.notes[model.collectionString][model.id] = content;
this.savePersonalNoteObject(pnObject);
}
/**
* Sets the 'favorite' status for several models of a type in bulk
*
* @param models The model the content belongs to
* @param star The new 'favorite' status
*/
public async bulkSetStar(models: (BaseModel | BaseViewModel)[], star: boolean): Promise<void> {
if (!models.length) {
return;
}
const pnObject: Partial<PersonalNoteObject> = this.personalNoteObject || {};
if (!pnObject.notes) {
pnObject.notes = {};
}
for (const model of models) {
if (!pnObject.notes[model.collectionString]) {
pnObject.notes[model.collectionString] = {};
}
if (pnObject.notes[model.collectionString][model.id]) {
pnObject.notes[model.collectionString][model.id].star = star;
} else {
pnObject.notes[model.collectionString][model.id] = { star: star, note: '' };
}
}
await this.savePersonalNoteObject(pnObject);
}
/**
* Sends an updated personal note to the server
*
* @param pnObject a partial (if new) or complete personal note object
*/
private async savePersonalNoteObject(pnObject: Partial<PersonalNoteObject>): Promise<void> {
if (!pnObject.id) { if (!pnObject.id) {
await this.http.post('rest/users/personal-note/', pnObject); await this.http.post('rest/users/personal-note/', pnObject);
} else { } else {

View File

@ -6,7 +6,7 @@
<ng-container class="meta-text-block-content"> <ng-container class="meta-text-block-content">
<ng-container *ngIf="!isEditMode"> <ng-container *ngIf="!isEditMode">
<div *ngIf="motion && motion.personalNote" [innerHTML]="sanitizeText(motion.personalNote.note)"></div> <div *ngIf="motion && motion.personalNote" [innerHTML]="sanitizeText(motion.personalNote.note)"></div>
<div class="no-content" *ngIf="!motion || !motion.personalNote" translate> <div class="no-content" *ngIf="!motion || !motion.personalNote || !motion.personalNote.note" translate>
No personal note No personal note
</div> </div>
</ng-container> </ng-container>

View File

@ -221,6 +221,10 @@
</button> </button>
<div *ngIf="perms.isAllowed('change_metadata')"> <div *ngIf="perms.isAllowed('change_metadata')">
<mat-divider></mat-divider> <mat-divider></mat-divider>
<button mat-menu-item (click)="multiselectWrapper(multiselectService.bulkToggleFavorite(selectedRows))">
<mat-icon>star</mat-icon>
<span translate>Set/unset Favorite</span>
</button>
<button mat-menu-item (click)="multiselectWrapper(multiselectService.setStateOfMultiple(selectedRows))"> <button mat-menu-item (click)="multiselectWrapper(multiselectService.setStateOfMultiple(selectedRows))">
<mat-icon>label</mat-icon> <mat-icon>label</mat-icon>
<span translate>Set status</span> <span translate>Set status</span>

View File

@ -2,20 +2,22 @@ import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { ViewMotion } from '../models/view-motion';
import { ChoiceService } from 'app/core/ui-services/choice.service';
import { PromptService } from 'app/core/ui-services/prompt.service';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service';
import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service'; import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service';
import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service'; import { ChoiceDialogOptions } from 'app/shared/components/choice-dialog/choice-dialog.component';
import { HttpService } from 'app/core/core-services/http.service'; import { ChoiceService } from 'app/core/ui-services/choice.service';
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
import { Displayable } from 'app/site/base/displayable'; import { Displayable } from 'app/site/base/displayable';
import { HttpService } from 'app/core/core-services/http.service';
import { Identifiable } from 'app/shared/models/base/identifiable'; import { Identifiable } from 'app/shared/models/base/identifiable';
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service'; import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { PersonalNoteService } from 'app/core/ui-services/personal-note.service';
import { PromptService } from 'app/core/ui-services/prompt.service';
import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service';
import { TreeService } from 'app/core/ui-services/tree.service'; import { TreeService } from 'app/core/ui-services/tree.service';
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
import { ViewMotion } from '../models/view-motion';
import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service';
/** /**
* Contains all multiselect actions for the motion list view. * Contains all multiselect actions for the motion list view.
@ -39,6 +41,7 @@ export class MotionMultiselectService {
* @param motionBlockRepo * @param motionBlockRepo
* @param httpService * @param httpService
* @param treeService * @param treeService
* @param personalNoteService
*/ */
public constructor( public constructor(
private repo: MotionRepositoryService, private repo: MotionRepositoryService,
@ -52,7 +55,8 @@ export class MotionMultiselectService {
private agendaRepo: ItemRepositoryService, private agendaRepo: ItemRepositoryService,
private motionBlockRepo: MotionBlockRepositoryService, private motionBlockRepo: MotionBlockRepositoryService,
private httpService: HttpService, private httpService: HttpService,
private treeService: TreeService private treeService: TreeService,
private personalNoteService: PersonalNoteService
) {} ) {}
/** /**
@ -299,4 +303,22 @@ export class MotionMultiselectService {
} }
} }
} }
/**
* Bulk sets/unsets the favorite status (after a confirmation dialog)
*
* @param motions The motions to set/unset the favorite status for
*/
public async bulkSetFavorite(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will set the favorite status for all selected motions:');
const choices: ChoiceDialogOptions = [
{ id: 1, label: this.translate.instant('Set as favorite') },
{ id: 2, label: this.translate.instant('Set as not favorite') }
];
const selectedChoice = await this.choiceService.open(title, choices);
if (selectedChoice && motions.length) {
const star = (selectedChoice.items as number) === choices[0].id;
await this.personalNoteService.bulkSetStar(motions, star);
}
}
} }