diff --git a/client/src/app/site/pages/meetings/modules/projector/components/projector/projector.component.html b/client/src/app/site/pages/meetings/modules/projector/components/projector/projector.component.html index cb4fac75e9..e6a66668fe 100644 --- a/client/src/app/site/pages/meetings/modules/projector/components/projector/projector.component.html +++ b/client/src/app/site/pages/meetings/modules/projector/components/projector/projector.component.html @@ -44,7 +44,7 @@ @if (projector!.show_clock) { } - @for (slide of slides | async; track slide) { + @for (slide of slides | async; track slide.id) {
[]> = new Observable[]>(); + public slides: Observable<(SlideData & { id: Id })[]> = new Observable< + (SlideData & { id: Id })[] + >(); /** * Info about if the user is offline. @@ -160,13 +162,14 @@ export class ProjectorComponent extends BaseUiComponent implements OnDestroy { (projector?.current_projections || []).map( projection => ({ + id: projection.id, collection: projection.content?.collection, data: projection.content, stable: !!projection.stable, type: projection.type || ``, options: projection.options || {}, ...(!!projection.content?.[`error`] && { error: projection.content[`error`] }) - }) as SlideData + }) as SlideData & { id: Id } ) ) ) diff --git a/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts b/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts index 9aa9056fbd..410441fb84 100644 --- a/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts @@ -128,13 +128,13 @@ export const listOfSpeakersSpeakerCountSubscription = { follow: [ { idField: `speaker_ids`, + fieldset: [`begin_time`, `end_time`], follow: [ { idField: `point_of_order_category_id`, fieldset: FULL_FIELDSET } - ], - fieldset: [`begin_time`, `end_time`] + ] } ] }; @@ -151,11 +151,11 @@ export const getListOfSpeakersDetailSubscriptionConfig: SubscriptionConfigGenera follow: [ { idField: `meeting_user_id`, + fieldset: [`number`, `vote_weight`], follow: [ { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, { idField: `structure_level_ids`, fieldset: [`name`] } - ], - fieldset: [`number`, `vote_weight`] + ] }, { idField: `structure_level_list_of_speakers_id`, diff --git a/client/src/app/site/pages/meetings/pages/mediafiles/mediafiles.subscription.ts b/client/src/app/site/pages/meetings/pages/mediafiles/mediafiles.subscription.ts index 20573b4f5d..8d028f95cb 100644 --- a/client/src/app/site/pages/meetings/pages/mediafiles/mediafiles.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/mediafiles/mediafiles.subscription.ts @@ -43,7 +43,7 @@ export const getMediafilesListMinimalSubscriptionConfig: SubscriptionConfigGener modelRequest: { viewModelCtor: ViewMeeting, ids: [id], - follow: [`mediafile_ids`, `meeting_mediafile_ids`] + follow: [{ idField: `mediafile_ids` }, { idField: `meeting_mediafile_ids` }] }, subscriptionName: MEDIAFILES_LIST_MINIMAL_SUBSCRIPTION }); diff --git a/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.html b/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.html index 34cee03cea..19f56cb608 100644 --- a/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.html +++ b/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.html @@ -95,7 +95,14 @@
{{ setting.label | translate }} @if (setting.helpText) { - {{ setting.helpText | translate }} + + {{ setting.helpText | translate }} + + } + @if (getWarning()) { + + {{ setting.warnText | translate }} + } @if (error) {
{{ error }}
diff --git a/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.ts b/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.ts index 79b76f94be..7c3d0b6772 100644 --- a/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.ts +++ b/client/src/app/site/pages/meetings/pages/meeting-settings/pages/meeting-settings-group-detail/components/meeting-settings-group-detail-field/meeting-settings-group-detail-field.component.ts @@ -274,6 +274,18 @@ export class MeetingSettingsGroupDetailFieldComponent extends BaseComponent impl this.cd.detach(); } + /** + * Checks if a warning should be given + * + */ + public getWarning(): boolean { + if (this.setting.warn) { + return this.setting.warn(this.orgaSettings); + } else { + return false; + } + } + public getRestrictedValue(value: T): T { if (this.setting.restrictionFn) { return this.setting.restrictionFn(this.orgaSettings, value); diff --git a/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts b/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts index 2bdbb50b76..d2d08e86bd 100644 --- a/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts @@ -119,12 +119,12 @@ export const getMotionWorkflowDetailSubscriptionConfig: SubscriptionConfigGenera modelRequest: { ids: [id], viewModelCtor: ViewMotionWorkflow, + fieldset: [], follow: [ { idField: `state_ids` } - ], - fieldset: `` + ] }, subscriptionName: MOTION_WORKFLOW_DETAIL_SUBSCRIPTION }); @@ -189,13 +189,13 @@ export const getMotionDetailSubscriptionConfig: SubscriptionConfigGenerator = (. { idField: `comment_ids`, fieldset: FULL_FIELDSET }, { idField: `supporter_meeting_user_ids`, + fieldset: `participantListMinimal`, follow: [ { idField: `user_id`, fieldset: `participantList` } - ], - fieldset: `participantListMinimal` + ] } ], fieldset: [ diff --git a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.html b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.html index 39c4a0bc59..3f2ce3d65a 100644 --- a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.html +++ b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.html @@ -55,7 +55,7 @@
- @if (motion.reason) { + @if (showReason) {

{{ 'Reason' | translate }}

diff --git a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.ts b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.ts index ee17a34d5e..ef7a0d8150 100644 --- a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.ts +++ b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-content/motion-content.component.ts @@ -73,6 +73,10 @@ export class MotionContentComponent extends BaseMotionDetailChildComponent { return this.motion.showPreamble; } + public get showReason(): boolean { + return !!this.motion.reason?.replace(/

/, ``).replace(/<\/p>/, ``).trim(); + } + public get canChangeMetadata(): boolean { return this.perms.isAllowed(`change_metadata`, this.motion); } diff --git a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.html b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.html index ee6d55df7e..68330239c0 100644 --- a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.html +++ b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.html @@ -26,6 +26,7 @@ class="primary-accent-by-theme" mat-icon-button matTooltipPosition="right" + [hidden]="publicAccess" matTooltip="{{ 'Mark as personal favorite' | translate }}" (click)="setFavorite(!isFavorite)" > diff --git a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.ts b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.ts index ab5cbe55cb..d84f844229 100644 --- a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.ts +++ b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-manage-title/motion-manage-title.component.ts @@ -31,6 +31,9 @@ export class MotionManageTitleComponent extends BaseMotionDetailChildComponent { return this._changeRecoMode; } + @Input() + public publicAccess: boolean; + @Output() public updateCrMode = new EventEmitter(); diff --git a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-view/motion-view.component.html b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-view/motion-view.component.html index 17c53385cd..15da866340 100644 --- a/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-view/motion-view.component.html +++ b/client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-view/components/motion-view/motion-view.component.html @@ -140,6 +140,7 @@

diff --git a/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-view/participant-detail-view.component.html b/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-view/participant-detail-view.component.html index 5fba5509bb..0442a70c00 100644 --- a/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-view/participant-detail-view.component.html +++ b/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-view/participant-detail-view.component.html @@ -279,8 +279,7 @@

{{ 'Voting right delegated to (proxy)' | translate }}

@if (showVoteDelegations && user!.vote_delegations_from().length > 0) {

- {{ 'Voting right received from ' | translate }}{{ user!.vote_delegations_from().length - }}{{ ' principals' | translate }} + {{ 'Principals' | translate }}

{{ 'Comment' | translate }} @if (isAllowed('seeSensitiveData')) { - {{ user!.isLockedOutOfMeeting() ? 'visibility_off' : 'check_box_outline_blank' }} + {{ user!.isLockedOutOfMeeting() ? 'visibility_off' : '' }} - {{ (user?.isLockedOutOfMeeting() ? 'Is locked out' : 'Is not locked out') | translate }} + {{ (user?.isLockedOutOfMeeting() ? 'Is locked out' : '') | translate }} }
diff --git a/client/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html b/client/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html index d57e472f28..af39fed402 100644 --- a/client/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html +++ b/client/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html @@ -80,7 +80,7 @@

{{ 'Participants' | translate }}

@if (isInPolldefaultGroup(user)) { {{ 'Vote weight' | translate }}: {{ user.vote_weight() }} @if (user.hasVoteRightFromOthers()) { - + {{ sumOfDelegatedVoteWeight(user) }} {{ ' from delegated votes' | translate }} + + {{ sumOfDelegatedVoteWeight(user) }} {{ 'from delegated votes' | translate }} } }
diff --git a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts index 66709e2d1d..e27715331f 100644 --- a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts @@ -37,8 +37,8 @@ export const getParticipantVoteInfoSubscriptionConfig: SubscriptionConfigGenerat }, { idField: `vote_delegated_to_id`, - follow: [{ idField: `user_id`, fieldset: [`is_present_in_meeting_ids`] }], - fieldset: [`meeting_id`] + fieldset: [`meeting_id`], + follow: [{ idField: `user_id`, fieldset: [`is_present_in_meeting_ids`] }] } ] } diff --git a/client/src/app/site/pages/meetings/pages/projectors/projectors.subscription.ts b/client/src/app/site/pages/meetings/pages/projectors/projectors.subscription.ts index b7a3917aed..7de8451119 100644 --- a/client/src/app/site/pages/meetings/pages/projectors/projectors.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/projectors/projectors.subscription.ts @@ -24,6 +24,7 @@ export const getProjectorListSubscriptionConfig: SubscriptionConfigGenerator = ( modelRequest: { viewModelCtor: ViewMeeting, ids: [id], + additionalFields: [`reference_projector_id`], follow: [ { idField: `projector_ids`, @@ -61,14 +62,13 @@ export const getProjectorListSubscriptionConfig: SubscriptionConfigGenerator = ( } ] }, - `projector_countdown_ids`, - `projector_message_ids`, - ...MEETING_DEFAULT_PROJECTOR_IDS_KEYS, + { idField: `projector_countdown_ids` }, + { idField: `projector_message_ids` }, { idField: `speaker_ids`, additionalFields: [`meeting_user_id`] }, - `list_of_speakers_ids`, - { idField: `agenda_item_ids`, fieldset: [`item_number`, `content_object_id`] } - ], - additionalFields: [`reference_projector_id`] + { idField: `list_of_speakers_ids` }, + { idField: `agenda_item_ids`, fieldset: [`item_number`, `content_object_id`] }, + ...MEETING_DEFAULT_PROJECTOR_IDS_KEYS + ] }, subscriptionName: PROJECTOR_LIST_SUBSCRIPTION }); diff --git a/client/src/app/site/pages/meetings/services/active-meeting.subscription.ts b/client/src/app/site/pages/meetings/services/active-meeting.subscription.ts index f367190409..e9b6321a0b 100644 --- a/client/src/app/site/pages/meetings/services/active-meeting.subscription.ts +++ b/client/src/app/site/pages/meetings/services/active-meeting.subscription.ts @@ -54,14 +54,14 @@ export function getActiveMeetingSubscriptionConfig(id: Id, settingsKeys: string[ }, // TODO: Remove and count unread messages by chat_group_ids/chat_message_ids { idField: `poll_ids`, + fieldset: [`title`, `state`, `entitled_group_ids`], follow: [ { idField: `content_object_id`, fieldset: [`title`], follow: [{ idField: `agenda_item_id`, fieldset: [`item_number`, `content_object_id`] }] } - ], - fieldset: [`title`, `state`, `entitled_group_ids`] + ] }, { idField: `point_of_order_category_ids`, diff --git a/client/src/app/site/pages/meetings/services/meeting-settings-definition.service/meeting-settings-definitions.ts b/client/src/app/site/pages/meetings/services/meeting-settings-definition.service/meeting-settings-definitions.ts index b19ee5ef25..d5fdb3775f 100644 --- a/client/src/app/site/pages/meetings/services/meeting-settings-definition.service/meeting-settings-definitions.ts +++ b/client/src/app/site/pages/meetings/services/meeting-settings-definition.service/meeting-settings-definitions.ts @@ -60,6 +60,7 @@ export interface SettingsInput { // alternative to `choices`; overwrites `choices` if both are given choicesFunc?: ChoicesFunctionDefinition; helpText?: string; // default: "" + warnText?: string; // default: "" indentation?: number; // default: 0. Indents the input field by the given amount to simulate nested settings validators?: ValidatorFn[]; // default: [] automaticChangesSetting?: SettingsItemAutomaticChangeSetting; @@ -88,6 +89,13 @@ export interface SettingsInput { * @returns whether to disable the setting or not */ forbidden?: (meetingView: ViewMeeting) => boolean; + /** + * A function to conditionally give a warning depending on used organization's settings + * + * @param orgaSettings: The `OrganizationSettingsService` has to be passed, because it is not injected in the + * settings definitions + */ + warn?: (orgaSettings: OrganizationSettingsService) => boolean; hide?: boolean; // Hide the setting in the settings view } @@ -207,7 +215,11 @@ export const meetingSettings: SettingsGroup[] = fillInSettingsDefaults([ type: `boolean`, helpText: _( `Enables public access to this meeting without login data. Permissions can be set after activation in the new group 'Public'.` - ) + ), + warnText: _( + `The public access setting is deactivated for the organization. Please contact your admins or hosting providers to activate the setting.` + ), + warn: orgaSettings => !orgaSettings.instant(`enable_anonymous`) } ] }, @@ -1006,14 +1018,16 @@ export const meetingSettings: SettingsGroup[] = fillInSettingsDefaults([ { key: `users_email_subject`, label: _(`Email subject`), - helpText: _(`You can use {event_name} and {username} as placeholder.`) + helpText: _( + `Possible placeholders for email subject and body: {title}, {first_name}, {last_name}, {groups}, {structure_levels}, {event_name}, {url}, {username} and {password}` + ) }, { key: `users_email_body`, label: _(`Email body`), type: `text`, helpText: _( - `Use these placeholders: {name}, {event_name}, {url}, {username}, {password}. The url referrs to the system url.` + `Possible placeholders for email subject and body: {title}, {first_name}, {last_name}, {groups}, {structure_levels}, {event_name}, {url}, {username} and {password}` ) } ] diff --git a/client/src/app/site/pages/organization/organization.subscription.ts b/client/src/app/site/pages/organization/organization.subscription.ts index f4748dca32..2d633a8e89 100644 --- a/client/src/app/site/pages/organization/organization.subscription.ts +++ b/client/src/app/site/pages/organization/organization.subscription.ts @@ -56,11 +56,11 @@ function getMeetingListFollowConfig( ): any { return { idField: idField, + fieldset: `list`, follow: [ { idField: `committee_id`, fieldset: `name` }, { idField: `organization_tag_ids`, fieldset: FULL_FIELDSET } - ], - fieldset: `list` + ] }; } diff --git a/client/src/app/site/pages/organization/pages/accounts/accounts.subscription.ts b/client/src/app/site/pages/organization/pages/accounts/accounts.subscription.ts index 05a6e96736..37d31e8cb4 100644 --- a/client/src/app/site/pages/organization/pages/accounts/accounts.subscription.ts +++ b/client/src/app/site/pages/organization/pages/accounts/accounts.subscription.ts @@ -16,8 +16,8 @@ export const getAccountDetailSubscriptionConfig: SubscriptionConfigGenerator = ( { idField: `committee_ids`, fieldset: [`name`, `manager_ids`] }, { idField: `meeting_ids`, - follow: [{ idField: `group_ids`, fieldset: [`name`], isFullList: false }], - fieldset: [`name`, `committee_id`] + fieldset: [`name`, `committee_id`], + follow: [{ idField: `group_ids`, fieldset: [`name`], isFullList: false }] }, { idField: `gender_id`, fieldset: [`name`] } ] diff --git a/client/src/app/site/pages/organization/pages/organization-tags/organization-tags.subscription.ts b/client/src/app/site/pages/organization/pages/organization-tags/organization-tags.subscription.ts index 17082e45aa..86b233b8e3 100644 --- a/client/src/app/site/pages/organization/pages/organization-tags/organization-tags.subscription.ts +++ b/client/src/app/site/pages/organization/pages/organization-tags/organization-tags.subscription.ts @@ -9,6 +9,6 @@ export const getOrganizationTagListSubscriptionConfig: SubscriptionConfigGenerat modelRequest: { viewModelCtor: ViewOrganization, ids: [ORGANIZATION_ID], - follow: [`organization_tag_ids`] + follow: [{ idField: `organization_tag_ids` }] } }); diff --git a/client/src/app/site/pages/organization/pages/settings/modules/settings-detail/components/organization-settings/organization-settings.component.html b/client/src/app/site/pages/organization/pages/settings/modules/settings-detail/components/organization-settings/organization-settings.component.html index bd7a6f81ba..1e30f05c00 100644 --- a/client/src/app/site/pages/organization/pages/settings/modules/settings-detail/components/organization-settings/organization-settings.component.html +++ b/client/src/app/site/pages/organization/pages/settings/modules/settings-detail/components/organization-settings/organization-settings.component.html @@ -107,7 +107,7 @@

{{ 'Superadmin settings' | translate }}

- {{ 'Meetings can be public' | translate }} + {{ 'Enable public meetings' | translate }}
diff --git a/client/src/app/site/services/auth-check.service.ts b/client/src/app/site/services/auth-check.service.ts index 36c42aab37..8514bd9ff6 100644 --- a/client/src/app/site/services/auth-check.service.ts +++ b/client/src/app/site/services/auth-check.service.ts @@ -97,7 +97,7 @@ export class AuthCheckService { if (typeof info === `string`) { meetingIdString = this.osRouter.getMeetingId(info); } - if (Number.isNaN(Number(meetingIdString))) { + if (Number.isNaN(Number(meetingIdString)) || +meetingIdString <= 0) { return false; } await this.fetchMeetingIfNotExists(+meetingIdString); diff --git a/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts b/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts index 8d00f2e86f..c0ae037ec0 100644 --- a/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts +++ b/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts @@ -36,7 +36,7 @@ import { SUBSCRIPTION_SUFFIX } from '../model-request.service'; }) export class AutoupdateCommunicationService { private autoupdateDataObservable: Observable; - private openResolvers = new Map) => void>(); + private openResolvers = new Map) => void)[]>(); private endpointName: string; private autoupdateEndpointStatus: 'healthy' | 'unhealthy' = `healthy`; private unhealtyTimeout: any; @@ -130,7 +130,11 @@ export class AutoupdateCommunicationService { public open(streamId: Id | null, description: string, request: ModelRequest, params = {}): Promise { return new Promise((resolve, reject) => { const requestHash = djb2hash(JSON.stringify(request)); - this.openResolvers.set(requestHash, resolve); + if (this.openResolvers.has(requestHash)) { + this.openResolvers.get(requestHash).push(resolve); + } else { + this.openResolvers.set(requestHash, [resolve]); + } this.sharedWorker .sendMessage(`autoupdate`, { action: `open`, @@ -298,7 +302,7 @@ export class AutoupdateCommunicationService { return; } - this.openResolvers.get(data.content.requestHash)(data.content?.streamId); + this.openResolvers.get(data.content.requestHash).forEach(r => r(data.content?.streamId)); this.openResolvers.delete(data.content.requestHash); } diff --git a/client/src/app/site/services/autoupdate/autoupdate.service.ts b/client/src/app/site/services/autoupdate/autoupdate.service.ts index d8644f9c7f..58556c129a 100644 --- a/client/src/app/site/services/autoupdate/autoupdate.service.ts +++ b/client/src/app/site/services/autoupdate/autoupdate.service.ts @@ -71,7 +71,7 @@ export class AutoupdateService { private _activeRequestObjects: AutoupdateSubscriptionMap = {}; private _mutex = new Mutex(); private _currentQueryParams: QueryParams | null = null; - private _resolveDataReceived: ((value: ModelData) => void)[] = []; + private _resolveDataReceived: { [key: number]: ((value: ModelData) => void)[] } = []; public constructor( private httpEndpointService: HttpStreamEndpointService, @@ -224,8 +224,13 @@ export class AutoupdateService { ); let rejectReceivedData: any; + let resolveIdx: number; const receivedData = new Promise((resolve, reject) => { - this._resolveDataReceived[id] = resolve; + if (this._resolveDataReceived[id]) { + resolveIdx = this._resolveDataReceived[id].push(resolve) - 1; + } else { + this._resolveDataReceived[id] = [resolve]; + } rejectReceivedData = reject; }); receivedData.catch((e: Error) => { @@ -238,9 +243,9 @@ export class AutoupdateService { close: (): void => { this.communication.close(id); delete this._activeRequestObjects[id]; - if (this._resolveDataReceived[id]) { + if (this._resolveDataReceived[id] && this._resolveDataReceived[id][resolveIdx]) { rejectReceivedData(new Error(`Connection canceled`)); - delete this._resolveDataReceived[id]; + delete this._resolveDataReceived[id][resolveIdx]; } console.debug(`[autoupdate] stream closed:`, description); @@ -323,7 +328,12 @@ export class AutoupdateService { this.communication.cleanupCollections(requestId, deletedModels); if (this._resolveDataReceived[requestId]) { - this._resolveDataReceived[requestId](modelData); + for (let i = 0; i < this._resolveDataReceived[requestId].length; i++) { + if (this._resolveDataReceived[requestId][i]) { + this._resolveDataReceived[requestId][i](modelData); + delete this._resolveDataReceived[requestId][i]; + } + } delete this._resolveDataReceived[requestId]; } } diff --git a/client/src/app/ui/modules/editor/components/editor/editor.component.ts b/client/src/app/ui/modules/editor/components/editor/editor.component.ts index ab64af22e2..65b24776cf 100644 --- a/client/src/app/ui/modules/editor/components/editor/editor.component.ts +++ b/client/src/app/ui/modules/editor/components/editor/editor.component.ts @@ -437,6 +437,10 @@ export class EditorComponent extends BaseFormControlComponent implements unwrapNode(listParagraphs.item(i)); } + if (!this.editor.getText()) { + return ``; + } + return dom.body.innerHTML; } } diff --git a/client/src/assets/i18n/de.po b/client/src/assets/i18n/de.po index c62c261670..eddddf6d77 100644 --- a/client/src/assets/i18n/de.po +++ b/client/src/assets/i18n/de.po @@ -830,10 +830,10 @@ msgid "Ballot reset" msgstr "Wahlgang zurückgesetzt" msgid "Ballot started" -msgstr "Wahlgang gestarted" +msgstr "Wahlgang gestartet" msgid "Ballot stopped" -msgstr "Wahlgeang beendet" +msgstr "Wahlgang beendet" msgid "Ballot stopped/published" msgstr "Wahlgang beendet/veröffentlicht" @@ -2059,6 +2059,9 @@ msgstr "Geschäftsordnungsanträge aktivieren" msgid "Enable point of orders for other participants" msgstr "Stellen eines GO-Antrags für andere Teilnehmende erlauben" +msgid "Enable public meetings" +msgstr "Öffentliche Veranstaltungen aktivieren" + msgid "Enable specifications and ranking for possible motions" msgstr "Vorgaben und Reihung für mögliche GO-Anträge aktivieren" @@ -3951,6 +3954,15 @@ msgstr "GO-Antrag" msgid "Polls" msgstr "Umfragen" +msgid "" +"Possible placeholders for email subject and body: {title}, {first_name}, " +"{last_name}, {groups}, {structure_levels}, {event_name}, {url}, {username} " +"and {password}" +msgstr "" +"Mögliche Platzhalter für E-Mail-Betreff und -Inhalt: {title}, {first_name}, " +"{last_name}, {groups}, {structure_levels}, {event_name}, {url}, {username} " +"und {password}" + msgid "Possible points of order" msgstr "Mögliche GO-Anträge" @@ -5347,13 +5359,6 @@ msgstr "Farbe verwenden" msgid "Use the following custom number" msgstr "Verwende die folgende benutzerdefinierte Anzahl" -msgid "" -"Use these placeholders: {name}, {event_name}, {url}, {username}, {password}." -" The url referrs to the system url." -msgstr "" -"Verwendbare Platzhalter: {name}, {event_name}, {url}, {username}, " -"{password}. Die URL bezieht sich auf die System-URL." - msgid "Used for WLAN QRCode projection." msgstr "Wird für die Projektion des WLAN-QR-Codes verwendet." @@ -5479,6 +5484,9 @@ msgstr "Stimmrecht für" msgid "Voting right received from (principals)" msgstr "Stimmrecht erhalten von (Vollmachtgeber*in)" +msgid "Voting rights" +msgstr "Stimmrechte" + msgid "Voting started" msgstr "Abstimmung gestartet" @@ -5667,9 +5675,6 @@ msgstr "" msgid "You can only anonymize named polls." msgstr "Sie können nur namentliche Stimmabgaben anonymisieren." -msgid "You can use {event_name} and {username} as placeholder." -msgstr "Sie können {event_name} und {username} als Platzhalter verwenden." - msgid "" "You cannot change the recommendation of motions in different workflows!" msgstr "" @@ -5890,6 +5895,9 @@ msgstr "weiblich" msgid "finished (unpublished)" msgstr "abgeschlossen (unveröffentlicht)" +msgid "from delegated votes" +msgstr "aus Stimmrechtsübertragungen" + msgid "fullscreen" msgstr "Vollbild" diff --git a/client/src/assets/i18n/template-en.pot b/client/src/assets/i18n/template-en.pot index 013d25c8ab..08a0bb8eb6 100644 --- a/client/src/assets/i18n/template-en.pot +++ b/client/src/assets/i18n/template-en.pot @@ -1994,6 +1994,10 @@ msgstr "" msgid "Enable point of orders for other participants" msgstr "" +#: /app/src/app/site/pages/organization/pages/settings/modules/settings-detail/components/organization-settings/organization-settings.component.html +msgid "Enable public meetings" +msgstr "" + msgid "Enable specifications and ranking for possible motions" msgstr "" @@ -3941,6 +3945,13 @@ msgstr "" msgid "Polls" msgstr "" +#: /app/src/app/site/pages/meetings/services/meeting-settings-definition.service/meeting-settings-definitions.ts +msgid "" +"Possible placeholders for email subject and body: {title}, {first_name}, " +"{last_name}, {groups}, {structure_levels}, {event_name}, {url}, {username} " +"and {password}" +msgstr "" + msgid "Possible points of order" msgstr "" @@ -5323,11 +5334,6 @@ msgstr "" msgid "Use the following custom number" msgstr "" -msgid "" -"Use these placeholders: {name}, {event_name}, {url}, {username}, " -"{password}. The url referrs to the system url." -msgstr "" - msgid "Used for WLAN QRCode projection." msgstr "" @@ -5450,6 +5456,11 @@ msgstr "" msgid "Voting right received from (principals)" msgstr "" +#: /app/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html +#: /app/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html +msgid "Voting rights" +msgstr "" + msgid "Voting started" msgstr "" @@ -5623,9 +5634,6 @@ msgstr "" msgid "You can only anonymize named polls." msgstr "" -msgid "You can use {event_name} and {username} as placeholder." -msgstr "" - msgid "You cannot change the recommendation of motions in different workflows!" msgstr "" @@ -5832,6 +5840,10 @@ msgstr "" msgid "finished (unpublished)" msgstr "" +#: /app/src/app/site/pages/meetings/pages/participants/pages/participant-list/components/participant-list/participant-list.component.html +msgid "from delegated votes" +msgstr "" + msgid "fullscreen" msgstr ""