diff --git a/client/src/app/core/repositories/motions/motion-repository.service.ts b/client/src/app/core/repositories/motions/motion-repository.service.ts index 5ebad6010..a7b752ee2 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -31,6 +31,7 @@ import { ViewUnifiedChange } from '../../../site/motions/models/view-unified-cha import { ViewStatuteParagraph } from '../../../site/motions/models/view-statute-paragraph'; import { Workflow } from '../../../shared/models/motions/workflow'; import { WorkflowState } from '../../../shared/models/motions/workflow-state'; +import { Tag } from 'app/shared/models/core/tag'; /** * Repository Services for motions (and potentially categories) @@ -71,7 +72,7 @@ export class MotionRepositoryService extends BaseRepository private personalNoteService: PersonalNoteService, private translate: TranslateService ) { - super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock, Mediafile]); + super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock, Mediafile, Tag]); } /** @@ -90,11 +91,23 @@ export class MotionRepositoryService extends BaseRepository const item = this.DS.get(Item, motion.agenda_item_id); const block = this.DS.get(MotionBlock, motion.motion_block_id); const attachments = this.DS.getMany(Mediafile, motion.attachments_id); + const tags = this.DS.getMany(Tag, motion.tags_id); let state: WorkflowState = null; if (workflow) { state = workflow.getStateById(motion.state_id); } - return new ViewMotion(motion, category, submitters, supporters, workflow, state, item, block, attachments); + return new ViewMotion( + motion, + category, + submitters, + supporters, + workflow, + state, + item, + block, + attachments, + tags + ); } /** @@ -219,6 +232,26 @@ export class MotionRepositoryService extends BaseRepository await this.update(motion, viewMotion); } + /** + * Adds new or removes existing tags from motions + * + * @param viewMotion the motion to tag + * @param tagId the tags id to add or remove + */ + public async setTag(viewMotion: ViewMotion, tagId: number): Promise { + const motion = viewMotion.motion; + const tagIndex = motion.tags_id.findIndex(tag => tag === tagId); + + if (tagIndex === -1) { + // add tag to motion + motion.tags_id.push(tagId); + } else { + // remove tag from motion + motion.tags_id.splice(tagIndex, 1); + } + await this.update(motion, viewMotion); + } + /** * Sets the submitters by sending a request to the server, * diff --git a/client/src/app/site/motions/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/components/motion-detail/motion-detail.component.html index 407e1f231..2c4507daf 100644 --- a/client/src/app/site/motions/components/motion-detail/motion-detail.component.html +++ b/client/src/app/site/motions/components/motion-detail/motion-detail.component.html @@ -303,6 +303,47 @@ + + +
+

Tags

+ + +
+ + + + + + +
+ + + {{ '–' }} + + + + + + {{ tag }} + + +
+
+ + +
+ + + {{ tag }} + + +
+
+

Motion block

@@ -494,8 +535,13 @@ -
+
This field is required.
@@ -506,15 +552,30 @@
-

+

Reason *

-
+
This field is required.
diff --git a/client/src/app/site/motions/components/motion-detail/motion-detail.component.scss b/client/src/app/site/motions/components/motion-detail/motion-detail.component.scss index eb0e650d9..553f82aaf 100644 --- a/client/src/app/site/motions/components/motion-detail/motion-detail.component.scss +++ b/client/src/app/site/motions/components/motion-detail/motion-detail.component.scss @@ -275,3 +275,9 @@ span { padding: 0px; } } + +.mat-chip-list-stacked { + .mat-chip { + margin: 4px 4px 4px 8px; + } +} diff --git a/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts index 5c46e2800..125bb3b62 100644 --- a/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts @@ -40,6 +40,7 @@ import { ViewUnifiedChange } from '../../models/view-unified-change'; import { ViewStatuteParagraph } from '../../models/view-statute-paragraph'; import { Workflow } from 'app/shared/models/motions/workflow'; import { LinenumberingService } from 'app/core/ui-services/linenumbering.service'; +import { Tag } from 'app/shared/models/core/tag'; /** * Component for the motion detail view @@ -221,6 +222,11 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { */ public agendaItemObserver: BehaviorSubject; + /** + * Subject for tags + */ + public tagObserver: BehaviorSubject; + /** * Determine if the name of supporters are visible */ @@ -356,6 +362,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { this.blockObserver = new BehaviorSubject(DS.getAll(MotionBlock)); this.mediafilesObserver = new BehaviorSubject(DS.getAll(Mediafile)); this.agendaItemObserver = new BehaviorSubject(DS.getAll(Item)); + this.tagObserver = new BehaviorSubject(DS.getAll(Tag)); // Make sure the subjects are updated, when a new Model for the type arrives this.DS.changeObservable.subscribe(newModel => { @@ -372,6 +379,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { this.mediafilesObserver.next(DS.getAll(Mediafile)); } else if (newModel instanceof Item) { this.agendaItemObserver.next(DS.getAll(Item)); + } else if (newModel instanceof Tag) { + this.tagObserver.next(DS.getAll(Tag)); } }); @@ -1013,6 +1022,17 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { } } + /** + * Adds or removes a tag to the current motion + * + * @param id Motion tag id + */ + public setTag(event: MouseEvent, id: number): void { + console.log('event: ', event); + event.stopPropagation(); + this.repo.setTag(this.motion, id); + } + /** * Add the current motion to a motion block * diff --git a/client/src/app/site/motions/models/view-motion.ts b/client/src/app/site/motions/models/view-motion.ts index 61a93918a..3d36cddd4 100644 --- a/client/src/app/site/motions/models/view-motion.ts +++ b/client/src/app/site/motions/models/view-motion.ts @@ -12,6 +12,7 @@ import { ViewMotionCommentSection } from './view-motion-comment-section'; import { Workflow } from '../../../shared/models/motions/workflow'; import { WorkflowState } from '../../../shared/models/motions/workflow-state'; import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable'; +import { Tag } from 'app/shared/models/core/tag'; /** * The line numbering mode for the motion detail view. @@ -51,6 +52,7 @@ export class ViewMotion extends BaseProjectableModel { protected _item: Item; protected _block: MotionBlock; protected _attachments: Mediafile[]; + protected _tags: Tag[]; public personalNote: PersonalNoteContent; /** @@ -232,6 +234,10 @@ export class ViewMotion extends BaseProjectableModel { return this._attachments ? this._attachments : null; } + public get tags(): Tag[] { + return this._tags ? this._tags : null; + } + /** * @returns the creation date as Date object */ @@ -313,7 +319,8 @@ export class ViewMotion extends BaseProjectableModel { state?: WorkflowState, item?: Item, block?: MotionBlock, - attachments?: Mediafile[] + attachments?: Mediafile[], + tags?: Tag[] ) { super(); this._motion = motion; @@ -325,6 +332,7 @@ export class ViewMotion extends BaseProjectableModel { this._item = item; this._block = block; this._attachments = attachments; + this._tags = tags; } public getTitle(): string { @@ -364,6 +372,8 @@ export class ViewMotion extends BaseProjectableModel { this.updateUser(update as User); } else if (update instanceof Mediafile) { this.updateAttachments(update as Mediafile); + } else if (update instanceof Tag) { + this.updateTags(update as Tag); } } @@ -381,7 +391,7 @@ export class ViewMotion extends BaseProjectableModel { /** * Update routine for the workflow * - * @param workflow potentially the changed workflow (state). Needs manual verification + * @param workflow potentially the (changed workflow (state). Needs manual verification */ public updateWorkflow(workflow: Workflow): void { if (this.motion && workflow.id === this.motion.workflow_id) { @@ -443,6 +453,15 @@ export class ViewMotion extends BaseProjectableModel { } } + public updateTags(update: Tag): void { + if (this.motion) { + if (this.tags_id && this.tags_id.includes(update.id)) { + const tagIndex = this.tags.findIndex(tag => tag.id === update.id); + this.tags[tagIndex] = update as Tag; + } + } + } + public hasSupporters(): boolean { return !!(this.supporters && this.supporters.length > 0); } @@ -451,6 +470,10 @@ export class ViewMotion extends BaseProjectableModel { return !!(this.attachments && this.attachments.length > 0); } + public hasTags(): boolean { + return !!(this.tags && this.tags.length > 0); + } + public isStatuteAmendment(): boolean { return !!this.statute_paragraph_id; } @@ -508,7 +531,8 @@ export class ViewMotion extends BaseProjectableModel { this._state, this._item, this._block, - this._attachments + this._attachments, + this._tags ); } }