From 47cf638b58d90e20233dce493e85ea5502645f9b Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Thu, 23 May 2024 11:02:59 +0200 Subject: [PATCH 1/3] Fix osPerm directive not updating permissions on group change (#3690) --- client/src/app/site/services/operator.service.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/src/app/site/services/operator.service.ts b/client/src/app/site/services/operator.service.ts index eaa517ffa0..ee9ddf7732 100644 --- a/client/src/app/site/services/operator.service.ts +++ b/client/src/app/site/services/operator.service.ts @@ -299,8 +299,15 @@ export class OperatorService { this._operatorUpdatedSubject.next(); } }); - this.meetingUserRepo.getGeneralViewModelObservable().subscribe(user => { - if (user !== undefined && this.operatorId === user.user_id) { + this.meetingUserRepo.getGeneralViewModelObservable().subscribe(mUser => { + if (mUser !== undefined && this.operatorId === mUser.user_id) { + const user = mUser.user; + if (user) { + this._shortName = this.userRepo.getShortName(user); + this.updateUser(user); + this._operatorShortNameSubject.next(this._shortName); + this._userSubject.next(user); + } this._operatorUpdatedSubject.next(); } }); From 0c6459bb67d4564a8d6cbc23d9de72d075838be2 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Thu, 23 May 2024 11:09:12 +0200 Subject: [PATCH 2/3] Remove history mode (#3676) --- .../services/voting-banner.service.ts | 6 +- .../history-banner.component.html | 7 -- .../history-banner.component.scss | 19 ---- .../history-banner.component.spec.ts | 24 ----- .../history-banner.component.ts | 20 ---- .../history-list/history-list.component.html | 6 +- .../history-list/history-list.component.scss | 4 +- .../history-list/history-list.component.ts | 24 ----- .../pages/history/definitions/index.ts | 1 - .../pages/history/definitions/position.ts | 12 --- .../meetings/pages/history/history.module.ts | 3 +- .../history/services/history.service.spec.ts | 16 ---- .../pages/history/services/history.service.ts | 93 ------------------- .../meeting-active-filters.service.ts | 13 +-- .../services/autoupdate/autoupdate.service.ts | 4 - .../meeting/motion/history.spec.ts | 72 ++++---------- 16 files changed, 27 insertions(+), 297 deletions(-) delete mode 100644 client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.html delete mode 100644 client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.scss delete mode 100644 client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.spec.ts delete mode 100644 client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.ts delete mode 100644 client/src/app/site/pages/meetings/pages/history/definitions/index.ts delete mode 100644 client/src/app/site/pages/meetings/pages/history/definitions/position.ts delete mode 100644 client/src/app/site/pages/meetings/pages/history/services/history.service.spec.ts delete mode 100644 client/src/app/site/pages/meetings/pages/history/services/history.service.ts diff --git a/client/src/app/site/modules/site-wrapper/services/voting-banner.service.ts b/client/src/app/site/modules/site-wrapper/services/voting-banner.service.ts index 6615cff1d6..8e47ba0096 100644 --- a/client/src/app/site/modules/site-wrapper/services/voting-banner.service.ts +++ b/client/src/app/site/modules/site-wrapper/services/voting-banner.service.ts @@ -6,7 +6,6 @@ import { Id } from 'src/app/domain/definitions/key-types'; import { Permission } from 'src/app/domain/definitions/permission'; import { VoteControllerService } from 'src/app/site/pages/meetings/modules/poll/services/vote-controller.service'; import { VotingService } from 'src/app/site/pages/meetings/modules/poll/services/voting.service'; -import { HistoryService } from 'src/app/site/pages/meetings/pages/history/services/history.service'; import { ViewPoll } from 'src/app/site/pages/meetings/pages/polls'; import { ActiveMeetingService } from 'src/app/site/pages/meetings/services/active-meeting.service'; import { ActivePollsService } from 'src/app/site/pages/meetings/services/active-polls.service'; @@ -34,7 +33,6 @@ export class VotingBannerService { public constructor( private banner: BannerService, private translate: TranslateService, - private historyService: HistoryService, private votingService: VotingService, private activeMeeting: ActiveMeetingService, private sendVotesService: VoteControllerService, @@ -72,8 +70,8 @@ export class VotingBannerService { this.pollsToVote = []; } - // display no banner if in history mode or there are no polls to vote - if ((this.historyService.isInHistoryMode() && this.currentBanner) || !this.pollsToVote.length) { + // display no banner if no polls to vote + if (!this.pollsToVote.length) { this.sliceBanner(); return; } diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.html b/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.html deleted file mode 100644 index cb7f0098b0..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.html +++ /dev/null @@ -1,7 +0,0 @@ -
- - {{ 'You are using the history mode of OpenSlides. Changes will not be saved.' | translate }} - - {{ historyPositionTimestamp | localizedDate }} - {{ 'Exit' | translate }} -
diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.scss b/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.scss deleted file mode 100644 index 38c4c1e14f..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.scss +++ /dev/null @@ -1,19 +0,0 @@ -:host { - width: 100%; -} - -.history-banner { - background: repeating-linear-gradient(45deg, #fe0, #fe0 10px, #070600 0, #000 20px); - - span, - a { - padding: 2px; - color: #000000 !important; - background: #ffee00; - } - - a { - cursor: pointer; - font-weight: bold; - } -} diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.spec.ts b/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.spec.ts deleted file mode 100644 index 4d2c16f532..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { HistoryBannerComponent } from './history-banner.component'; - -xdescribe(`HistoryBannerComponent`, () => { - let component: HistoryBannerComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [HistoryBannerComponent] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(HistoryBannerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it(`should create`, () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.ts b/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.ts deleted file mode 100644 index 184613cdf6..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/components/history-banner/history-banner.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component } from '@angular/core'; - -import { HistoryService } from '../../services/history.service'; - -@Component({ - selector: `os-history-banner`, - templateUrl: `./history-banner.component.html`, - styleUrls: [`./history-banner.component.scss`] -}) -export class HistoryBannerComponent { - public constructor(private historyService: HistoryService) {} - - public get historyPositionTimestamp(): number | null { - return this.historyService.currentHistoryPosition?.timestamp; - } - - public leaveHistoryMode(): void { - this.historyService.leaveHistoryMode(); - } -} diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.html b/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.html index d2f7a4f088..b3a79dae5e 100644 --- a/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.html +++ b/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.html @@ -81,11 +81,7 @@ - + diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.scss b/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.scss index 9435dd81c3..b3006ddc41 100644 --- a/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.scss +++ b/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.scss @@ -14,8 +14,8 @@ padding-right: 5px; } - .links-disabled { - pointer-events: none; + mat-row:hover { + cursor: auto; } } diff --git a/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.ts b/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.ts index 863d9c0a21..e8e027ee78 100644 --- a/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.ts +++ b/client/src/app/site/pages/meetings/pages/history/components/history-list/history-list.component.ts @@ -7,7 +7,6 @@ import { Observable, Subject } from 'rxjs'; import { Collection, Fqid, Id } from 'src/app/domain/definitions/key-types'; import { OML } from 'src/app/domain/definitions/organization-permission'; import { Selectable } from 'src/app/domain/interfaces'; -import { isDetailNavigable } from 'src/app/domain/interfaces/detail-navigable'; import { BaseModel } from 'src/app/domain/models/base/base-model'; import { HistoryPosition, HistoryPresenterService } from 'src/app/gateways/presenter/history-presenter.service'; import { SearchDeletedModelsPresenterService } from 'src/app/gateways/presenter/search-deleted-models-presenter.service'; @@ -28,8 +27,6 @@ import { ViewModelStoreService } from 'src/app/site/services/view-model-store.se import { ViewMotionState } from '../../../motions'; import { ParticipantControllerService } from '../../../participants/services/common/participant-controller.service'; -import { Position } from '../../definitions'; -import { HistoryService } from '../../services/history.service'; const HISTORY_SUBSCRIPTION_PREFIX = `history`; @@ -109,7 +106,6 @@ export class HistoryListComponent extends BaseMeetingComponent implements OnInit private historyPresenter: HistoryPresenterService, private searchDeletedModelsPresenter: SearchDeletedModelsPresenterService, private operator: OperatorService, - private historyService: HistoryService, private motionRepo: MotionRepositoryService, private assignmentRepo: AssignmentRepositoryService, private userRepo: ParticipantControllerService, @@ -247,26 +243,6 @@ export class HistoryListComponent extends BaseMeetingComponent implements OnInit return [`time`, `info`, `user`]; } - /** - * Click handler for rows in the history table. - * Serves as an entry point for the time travel routine - */ - public async onClickRow(position: Position): Promise { - if (!this.operator.hasOrganizationPermissions(OML.superadmin)) { - return; - } - - await this.historyService.enterHistoryMode(this.currentFqid, position); - const [collection, id] = collectionIdFromFqid(this.currentFqid); - const element = this.viewModelStore.get(collection, id); - if (element && isDetailNavigable(element)) { - this.router.navigate([element.getDetailStateUrl()]); - } else { - const message = this.translate.instant(`Cannot navigate to the selected history element.`); - this.raiseError(message); - } - } - public refresh(): void { if (this.currentFqid) { this.queryByFqid(this.currentFqid); diff --git a/client/src/app/site/pages/meetings/pages/history/definitions/index.ts b/client/src/app/site/pages/meetings/pages/history/definitions/index.ts deleted file mode 100644 index aa2a31e774..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/definitions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './position'; diff --git a/client/src/app/site/pages/meetings/pages/history/definitions/position.ts b/client/src/app/site/pages/meetings/pages/history/definitions/position.ts deleted file mode 100644 index ca7464cf76..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/definitions/position.ts +++ /dev/null @@ -1,12 +0,0 @@ -export class Position { - public position: number; - public timestamp: number; - public information: string[]; - public user: string; - - public constructor(input: Position) { - if (input) { - Object.assign(this, input); - } - } -} diff --git a/client/src/app/site/pages/meetings/pages/history/history.module.ts b/client/src/app/site/pages/meetings/pages/history/history.module.ts index 95f329e427..987205d399 100644 --- a/client/src/app/site/pages/meetings/pages/history/history.module.ts +++ b/client/src/app/site/pages/meetings/pages/history/history.module.ts @@ -14,7 +14,6 @@ import { SearchSelectorModule } from 'src/app/ui/modules/search-selector'; import { PipesModule } from 'src/app/ui/pipes'; import { ParticipantCommonServiceModule } from '../participants/services/common/participant-common-service.module'; -import { HistoryBannerComponent } from './components/history-banner/history-banner.component'; import { HistoryListComponent } from './components/history-list/history-list.component'; import { HistoryMainComponent } from './components/history-main/history-main.component'; import { HistoryRoutingModule } from './history-routing.module'; @@ -41,6 +40,6 @@ import { HistoryRoutingModule } from './history-routing.module'; ParticipantCommonServiceModule, PipesModule ], - declarations: [HistoryListComponent, HistoryMainComponent, HistoryBannerComponent] + declarations: [HistoryListComponent, HistoryMainComponent] }) export class HistoryModule {} diff --git a/client/src/app/site/pages/meetings/pages/history/services/history.service.spec.ts b/client/src/app/site/pages/meetings/pages/history/services/history.service.spec.ts deleted file mode 100644 index 6a4397a31a..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/services/history.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { HistoryService } from './history.service'; - -xdescribe(`HistoryService`, () => { - let service: HistoryService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(HistoryService); - }); - - it(`should be created`, () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/client/src/app/site/pages/meetings/pages/history/services/history.service.ts b/client/src/app/site/pages/meetings/pages/history/services/history.service.ts deleted file mode 100644 index 7c9e3dbf72..0000000000 --- a/client/src/app/site/pages/meetings/pages/history/services/history.service.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Injectable } from '@angular/core'; -import { MatSnackBar } from '@angular/material/snack-bar'; -import { combineLatest } from 'rxjs'; -import { Fqid } from 'src/app/domain/definitions/key-types'; -import { ActionService } from 'src/app/gateways/actions'; -import { NotifyService } from 'src/app/gateways/notify.service'; -import { BannerService } from 'src/app/site/modules/site-wrapper/services/banner.service'; -import { ActiveMeetingIdService } from 'src/app/site/pages/meetings/services/active-meeting-id.service'; -import { AutoupdateService } from 'src/app/site/services/autoupdate'; -import { DataStoreService } from 'src/app/site/services/data-store.service'; -import { OpenSlidesRouterService } from 'src/app/site/services/openslides-router.service'; - -import { HistoryBannerComponent } from '../components/history-banner/history-banner.component'; -import { Position } from '../definitions'; - -@Injectable({ - providedIn: `root` -}) -export class HistoryService { - private _isInHistoryMode = false; - private _actionFnIndex: number | null = null; - private _currentHistoryPosition: Position | null = null; - - public get currentHistoryPosition(): Position | null { - return this._currentHistoryPosition; - } - - public constructor( - _openslidesRouter: OpenSlidesRouterService, - private autoupdateService: AutoupdateService, - private bannerService: BannerService, - private notify: NotifyService, - private activeMeetingIdService: ActiveMeetingIdService, - private actions: ActionService, - private snackBar: MatSnackBar, - private datastore: DataStoreService - ) { - combineLatest([ - _openslidesRouter.beforeLeaveMeetingObservable, - _openslidesRouter.beforeSignoutObservable - ]).subscribe(() => { - this.leaveHistoryMode(); - }); - } - - public async enterHistoryMode(fqid: Fqid, historyPosition: Position): Promise { - if (!this._isInHistoryMode) { - this._isInHistoryMode = true; // Prevent going multiple times into the history mode - this.bannerService.addBanner({ component: HistoryBannerComponent }); - this.notify.disconnect(); - this.setHistoryMode(); - } - this._currentHistoryPosition = historyPosition; - await this.loadHistoryPosition(fqid, historyPosition); - } - - public leaveHistoryMode(): void { - if (this._isInHistoryMode) { - this._isInHistoryMode = false; - this._currentHistoryPosition = null; - this.removeActionFn(); - this.bannerService.removeBanner({ component: HistoryBannerComponent }); - this.datastore.clear(); - this.autoupdateService.reconnect(); - this.notify.connect(this.activeMeetingIdService.meetingId!); - } - } - - public isInHistoryMode(): boolean { - return this._isInHistoryMode; - } - - private setHistoryMode(): void { - this._actionFnIndex = this.actions.addBeforeActionFn(() => { - if (this._isInHistoryMode) { - this.snackBar.open(`You cannot make changes while in history mode`, `Ok`); - } - return this._isInHistoryMode; - }); - } - - private removeActionFn(): void { - if (this._actionFnIndex) { - this.actions.removeBeforeActionFn(this._actionFnIndex); - this._actionFnIndex = null; - } - } - - private async loadHistoryPosition(fqid: Fqid, historyPosition: Position): Promise { - this.datastore.clear(); - this.autoupdateService.reconnect({ position: historyPosition.position }); - } -} diff --git a/client/src/app/site/pages/meetings/services/meeting-active-filters.service.ts b/client/src/app/site/pages/meetings/services/meeting-active-filters.service.ts index fdbb70391f..b44483b1eb 100644 --- a/client/src/app/site/pages/meetings/services/meeting-active-filters.service.ts +++ b/client/src/app/site/pages/meetings/services/meeting-active-filters.service.ts @@ -3,24 +3,17 @@ import { OsFilter } from 'src/app/site/base/base-filter.service'; import { ActiveFiltersService } from 'src/app/site/services/active-filters.service'; import { ActiveFiltersStoreService } from 'src/app/ui/modules/list/definitions'; -import { HistoryService } from '../pages/history/services/history.service'; - @Injectable({ providedIn: `root` }) export class MeetingActiveFiltersService implements ActiveFiltersStoreService { - public constructor(private historyService: HistoryService, private activeFiltersService: ActiveFiltersService) {} + public constructor(private activeFiltersService: ActiveFiltersService) {} public async save(storageKey: string, filterDefinitions: OsFilter[]): Promise { - if (!this.historyService.isInHistoryMode()) { - return await this.activeFiltersService.save(storageKey, filterDefinitions); - } + return await this.activeFiltersService.save(storageKey, filterDefinitions); } public load(storageKey: string): Promise[] | null> { - if (!this.historyService.isInHistoryMode()) { - return this.activeFiltersService.load(storageKey); - } - return null; + return this.activeFiltersService.load(storageKey); } } diff --git a/client/src/app/site/services/autoupdate/autoupdate.service.ts b/client/src/app/site/services/autoupdate/autoupdate.service.ts index fe5699d6a5..6117f437df 100644 --- a/client/src/app/site/services/autoupdate/autoupdate.service.ts +++ b/client/src/app/site/services/autoupdate/autoupdate.service.ts @@ -26,10 +26,6 @@ export interface ModelSubscription { export const AUTOUPDATE_DEFAULT_ENDPOINT = `autoupdate`; interface AutoupdateConnectConfig { - /** - * Selects one position for a model. This implies `single: 1`. - */ - position?: number; /** * Selects the last n updates to the requested fields. `true` is equivalent to `n = 1`. */ diff --git a/client/tests/integration/meeting/motion/history.spec.ts b/client/tests/integration/meeting/motion/history.spec.ts index 41dd6c062f..95ce5064e1 100644 --- a/client/tests/integration/meeting/motion/history.spec.ts +++ b/client/tests/integration/meeting/motion/history.spec.ts @@ -1,8 +1,9 @@ -import { test, expect } from '@playwright/test'; +import { expect, test } from '@playwright/test'; + import { login, logout } from '../../helpers/auth'; import { createMeeting, deleteCommittees, deleteMeetings, os4request } from '../../helpers/request'; -test.describe('motion history mode test', () => { +test.describe(`motion history mode test`, () => { const ADMIN_ID = 1; let meeting: { id: number; committeeId: number; name: string }; let motion: { id: number; sequential_number: number }; @@ -11,24 +12,24 @@ test.describe('motion history mode test', () => { const context = await browser.newContext(); await login(context); meeting = await createMeeting(context, `MeetingMotionHistoryTestMeeting${Date.now().toString()}`, [ADMIN_ID]); - motion = await os4request(context, 'motion.create', { + motion = await os4request(context, `motion.create`, { meeting_id: meeting.id, - title: 'MotionHistoryTestTitle', - text: '

MotionHistoryTestText

', + title: `MotionHistoryTestTitle`, + text: `

MotionHistoryTestText

`, submitter_ids: [], category_id: null, attachment_ids: [], - reason: '', + reason: ``, supporter_meeting_user_ids: [], agenda_create: false, - agenda_type: 'internal' + agenda_type: `internal` }); - await os4request(context, 'poll.create', { + await os4request(context, `poll.create`, { meeting_id: meeting.id, - title: 'Vote', - onehundred_percent_base: 'YNA', - pollmethod: 'YNA', - type: 'pseudoanonymous', + title: `Vote`, + onehundred_percent_base: `YNA`, + pollmethod: `YNA`, + type: `pseudoanonymous`, global_abstain: false, global_no: false, global_yes: false, @@ -41,12 +42,12 @@ test.describe('motion history mode test', () => { } ], content_object_id: `motion/${motion.id}`, - backend: 'fast' + backend: `fast` }); - await os4request(context, 'motion.update', { + await os4request(context, `motion.update`, { id: motion.id, - title: 'MotionHistoryTestChangedTitle', - text: '

MotionHistoryTestChangedText

' + title: `MotionHistoryTestChangedTitle`, + text: `

MotionHistoryTestChangedText

` }); await logout(context); }); @@ -59,47 +60,10 @@ test.describe('motion history mode test', () => { await logout(context); }); - test('history entry exists', async ({ context, page }) => { + test(`history entry exists`, async ({ context, page }) => { await login(context); await page.goto(`/${meeting.id}/history?fqid=motion%2F${motion.id}`); await expect(page.locator(`body`)).toContainText(`Motion created`); await logout(context); }); - - test('history mode banner appears', async ({ context, page }) => { - await login(context); - await page.goto(`/${meeting.id}/history?fqid=motion%2F${motion.id}`); - await new Promise(resolve => setTimeout(resolve, 5000)); - await expect(page.locator(`body`)).toContainText(`Motion created`); - await page.getByText(`Motion created`).first().click(); - await page.waitForURL(`/${meeting.id}/motions/${motion.sequential_number}`); - await expect(page.locator(`body`)).toContainText(`You are using the history mode of OpenSlides.`); - await logout(context); - }); - - test('history mode changes get reverted', async ({ context, page }) => { - await login(context); - await page.goto(`/${meeting.id}/history?fqid=motion%2F${motion.id}`); - await new Promise(resolve => setTimeout(resolve, 5000)); - await page.getByText(`Motion created`).first().click(); - await page.waitForURL(`/${meeting.id}/motions/${motion.sequential_number}`); - await expect(page.locator(`body`)).toContainText(`MotionHistoryTestTitle`); - await expect(page.locator(`body`)).toContainText(`MotionHistoryTestText`); - await expect(page.locator(`os-motion-poll`)).not.toBeVisible(); - await logout(context); - }); - - test('history mode leave', async ({ context, page }) => { - await login(context); - await page.goto(`/${meeting.id}/history?fqid=motion%2F${motion.id}`); - await new Promise(resolve => setTimeout(resolve, 5000)); - await page.getByText(`Motion created`).first().click(); - await page.waitForURL(`/${meeting.id}/motions/${motion.sequential_number}`); - await expect(page.locator(`body`)).toContainText(`MotionHistoryTestTitle`); - await page.locator('a', { hasText: `Exit` }).first().click(); - await expect(page.locator(`body`)).toContainText(`MotionHistoryTestChangedTitle`); - await expect(page.locator(`body`)).toContainText(`MotionHistoryTestChangedText`); - await expect(page.locator(`os-motion-poll`)).toBeVisible(); - await logout(context); - }); }); From 92c61e10e6b8720bc0e749f709c447eef8b6e010 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Thu, 23 May 2024 11:15:56 +0200 Subject: [PATCH 3/3] Add spokesperson to motion xlsx export (#3592) --- .../motion-export-dialog.component.html | 7 +++++++ .../motion-export-dialog.component.ts | 19 +++++++++++++++++++ .../motion-xlsx-export.service.ts | 6 ++++++ 3 files changed, 32 insertions(+) diff --git a/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.html b/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.html index 1635d1b3f6..43f117baa1 100644 --- a/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.html +++ b/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.html @@ -64,6 +64,13 @@

{{ 'Export motions' | translate }}

{{ 'Speakers' | translate }} + + {{ 'Spokesperson' | translate }} + {{ 'Voting result' | translate }} diff --git a/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.ts b/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.ts index cc04017755..a19861eed9 100644 --- a/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.ts +++ b/client/src/app/site/pages/meetings/pages/motions/components/motion-export-dialog/components/motion-export-dialog/motion-export-dialog.component.ts @@ -53,6 +53,8 @@ export class MotionExportDialogComponent extends BaseUiComponent implements OnIn */ public exportForm!: UntypedFormGroup; + public workingGroupSpeakerActive: boolean; + /** * Store the subject to the ViewMotionCommentSection */ @@ -109,6 +111,12 @@ export class MotionExportDialogComponent extends BaseUiComponent implements OnIn @ViewChild(`speakersButton`) public speakersButton!: MatButtonToggle; + /** + * To deactivate the working group button. + */ + @ViewChild(`workingGroupSpeakerButton`) + public workingGroupSpeakerButton!: MatButtonToggle; + /** * To deactivate the toc button. */ @@ -137,6 +145,7 @@ export class MotionExportDialogComponent extends BaseUiComponent implements OnIn super(); this.defaults.lnMode = this.meetingSettingsService.instant(`motions_default_line_numbering`)!; this.defaults.crMode = this.meetingSettingsService.instant(`motions_recommendation_text_mode`)!; + this.workingGroupSpeakerActive = this.meetingSettingsService.instant(`motions_enable_working_group_speaker`)!; this.commentsSubject = this.commentRepo.getViewModelListObservable(); if (this.meetingSettingsService.instant(`motions_show_sequential_number`)) { this.defaults.metaInfo!.push(`id`); @@ -173,9 +182,15 @@ export class MotionExportDialogComponent extends BaseUiComponent implements OnIn if (format === ExportFileFormat.XLSX) { this.disableControl(`content`); this.changeStateOfButton(this.speakersButton, false); + if (this.workingGroupSpeakerButton) { + this.changeStateOfButton(this.workingGroupSpeakerButton, false); + } } else { this.enableControl(`content`); this.changeStateOfButton(this.speakersButton, true); + if (this.workingGroupSpeakerButton) { + this.changeStateOfButton(this.workingGroupSpeakerButton, true); + } } if (format === ExportFileFormat.CSV || format === ExportFileFormat.XLSX) { @@ -287,6 +302,10 @@ export class MotionExportDialogComponent extends BaseUiComponent implements OnIn // restore selection or set default this.store.get(`motion_export_selection`).then(restored => { if (restored) { + if (!this.workingGroupSpeakerActive && restored.metaInfo?.includes(`working_group_speakers`)) { + restored.metaInfo.splice(restored.metaInfo.indexOf(`working_group_speakers`)); + } + this.exportForm.patchValue(restored); } else { this.exportForm.patchValue(this.defaults); diff --git a/client/src/app/site/pages/meetings/pages/motions/services/export/motion-xlsx-export.service/motion-xlsx-export.service.ts b/client/src/app/site/pages/meetings/pages/motions/services/export/motion-xlsx-export.service/motion-xlsx-export.service.ts index dcd88ef25e..3113b5fa32 100644 --- a/client/src/app/site/pages/meetings/pages/motions/services/export/motion-xlsx-export.service/motion-xlsx-export.service.ts +++ b/client/src/app/site/pages/meetings/pages/motions/services/export/motion-xlsx-export.service/motion-xlsx-export.service.ts @@ -83,6 +83,9 @@ export class MotionXlsxExportService { const properties: string[] = infoToExport.includes(`speakers`) ? sortMotionPropertyList([`number`, `title`].concat(infoToExport)).concat(`speakers`) : sortMotionPropertyList([`number`, `title`].concat(infoToExport)); + if (infoToExport.includes(`working_group_speakers`)) { + properties.push(`working_group_speakers`); + } const worksheet = workbook.addWorksheet(this.translate.instant(`Motions`), { pageSetup: { @@ -114,6 +117,9 @@ export class MotionXlsxExportService { case `speakers`: propertyHeader = _(`Open requests to speak`); break; + case `working_group_speakers`: + propertyHeader = _(`Spokesperson`); + break; default: propertyHeader = property.charAt(0).toUpperCase() + property.slice(1).replace(`_`, ` `); }