Skip to content

Commit

Permalink
Merge branch 'main' into 2755-angular-16
Browse files Browse the repository at this point in the history
  • Loading branch information
bastianjoel committed Oct 20, 2023
2 parents c2a4dd9 + 05e9143 commit ec8723c
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ export class MeetingRepositoryService extends BaseRepository<ViewMeeting, Meetin
update.start_time = this.anyDateToUnix(update.start_time);
update.end_time = this.anyDateToUnix(update.end_time);
}
if (meeting && meeting.start_time === undefined && update.start_time === null) {
delete update.start_time;
}
if (meeting && meeting.end_time === undefined && update.end_time === null) {
delete update.end_time;
}

if (update.organization_tag_ids === null) {
update.organization_tag_ids = [];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@
></os-participant-search-selector>
</div>

<div class="centered-text" *osPerms="permission.listOfSpeakersCanBeSpeaker">
<span *ngIf="!canAddDueToPresence" translate>You have to be present to add yourself.</span>
</div>

<div class="add-self-buttons" *osPerms="permission.listOfSpeakersCanBeSpeaker">
<!-- Add me and remove me if OP has correct permission -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@
padding: 15px 25px 0 25px;
width: auto;
}

.centered-text {
text-align: center;
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
#countdown {
white-space: nowrap;
font-family: $font-monospace;
font-weight: bold;
font-weight: 800;
text-align: center;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class HistoryListComponent extends BaseMeetingComponent implements OnInit
private filterHistoryData(positions: HistoryPosition[], fqid: Fqid): HistoryPosition[] {
return positions.filter(position => {
const newInformation = [];
if (!Array.isArray(position.information)) {
if (position.information && !Array.isArray(position.information)) {
position.information = position.information[fqid];
}
if (!position.information) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ const routes: Routes = [
},
{
path: `tags`,
loadChildren: () => import(`./pages/tags/tags.module`).then(m => m.TagsModule)
loadChildren: () => import(`./pages/tags/tags.module`).then(m => m.TagsModule),
data: { meetingPermissions: [Permission.tagCanManage] }
},
{
path: `polls`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ export class AmendmentCreateWizardComponent extends BaseMeetingComponent impleme
};

const { sequential_number } = await this.repo.createParagraphBased(motionCreate);
this.router.navigate([this.activeMeetingId, `motions`, sequential_number]);
this.router.navigate([this.activeMeetingId, `motions`, sequential_number], {
replaceUrl: true,
state: { canGoBack: true }
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,10 @@ export class MotionPdfService {
}

// referring motions
if (!infoToExport || infoToExport.includes(`referring_motions`)) {
if (
infoToExport?.includes(`referring_motions`) ||
(!infoToExport && this.meetingSettingsService.instant(`motions_show_referring_motions`))
) {
if (motion.referenced_in_motion_recommendation_extensions.length) {
const referringMotions = motion.referenced_in_motion_recommendation_extensions
.naturalSort(this.translate.currentLang, [`number`, `title`])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,12 @@ export class MeetingEditComponent extends BaseComponent implements OnInit {
public committee!: ViewCommittee;

public get meetingUsers(): ViewUser[] {
return this.editMeeting?.calculated_users || [];
const users = this.editMeeting?.calculated_users;
if (users && !users.some(u => u.id === this.operator.operatorId)) {
users.push(this.operator.user);
}

return users || [];
}

private meetingId: Id | null = null;
Expand Down
14 changes: 10 additions & 4 deletions client/src/app/site/services/autoupdate/autoupdate.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { marker as _ } from '@colsen1991/ngx-translate-extract-marker';
import { firstValueFrom } from 'rxjs';
import { ModelRequest } from 'src/app/domain/interfaces/model-request';

import { Collection, Id, Ids } from '../../../domain/definitions/key-types';
Expand All @@ -8,6 +9,7 @@ import { EndpointConfiguration } from '../../../gateways/http-stream/endpoint-co
import { HttpMethod, QueryParams } from '../../../infrastructure/definitions/http';
import { Mutex } from '../../../infrastructure/utils/promises';
import { BannerDefinition, BannerService } from '../../modules/site-wrapper/services/banner.service';
import { LifecycleService } from '../lifecycle.service';
import { ModelRequestObject } from '../model-request-builder';
import { ViewModelStoreUpdateService } from '../view-model-store-update.service';
import { WindowVisibilityService } from '../window-visibility.service';
Expand Down Expand Up @@ -82,7 +84,8 @@ export class AutoupdateService {
private viewmodelStoreUpdate: ViewModelStoreUpdateService,
private communication: AutoupdateCommunicationService,
private bannerService: BannerService,
private visibilityService: WindowVisibilityService
private visibilityService: WindowVisibilityService,
private lifecycle: LifecycleService
) {
this.setAutoupdateConfig(null);
this.httpEndpointService.registerEndpoint(
Expand All @@ -97,9 +100,12 @@ export class AutoupdateService {
this.communication.listenShouldReconnect().subscribe(() => {
this.pauseUntilVisible();
});
this.visibilityService.hiddenFor(PAUSE_ON_INACTIVITY_TIMEOUT).subscribe(() => {
this.pauseUntilVisible();
});

firstValueFrom(this.lifecycle.appLoaded).then(() =>
this.visibilityService.hiddenFor(PAUSE_ON_INACTIVITY_TIMEOUT).subscribe(() => {
this.pauseUntilVisible();
})
);

window.addEventListener(`beforeunload`, () => {
for (const id of Object.keys(this._activeRequestObjects)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { filter, pairwise, startWith } from 'rxjs';
providedIn: `root`
})
export class RoutingStateService {
private skipUnsafeRouteCheck = false;
/**
* Hold the previous URL
*/
Expand All @@ -32,7 +33,7 @@ export class RoutingStateService {
* If this fails, the open nav button should be shown
*/
public get isSafePrevUrl(): boolean {
if (this._previousUrl) {
if (this._previousUrl && !this.skipUnsafeRouteCheck) {
return !this.unsafeUrls.some(unsafeUrl => this._previousUrl?.includes(unsafeUrl));
} else {
return true;
Expand Down Expand Up @@ -62,6 +63,9 @@ export class RoutingStateService {
pairwise()
)
.subscribe((event: any[]) => {
this.skipUnsafeRouteCheck =
router.getCurrentNavigation()?.extras?.state &&
router.getCurrentNavigation()?.extras?.state[`canGoBack`];
this._previousUrl = event[0]?.urlAfterRedirects ?? this._currentUrl;
const currentNavigationExtras = router.getCurrentNavigation()?.extras;
if (currentNavigationExtras && currentNavigationExtras.state && currentNavigationExtras.state[`back`]) {
Expand Down
195 changes: 187 additions & 8 deletions client/src/app/ui/modules/list/services/list-search.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,195 @@
import { TestBed } from '@angular/core/testing';
import { BehaviorSubject, filter, firstValueFrom, map, skip } from 'rxjs';

import { ListSearchService } from './list-search.service';

xdescribe(`ListSearchService`, () => {
let service: ListSearchService<any>;
class MockIdentifiable {
public constructor(
public id: number,
public en: string,
public ti: boolean,
private _fi: (originItem: MockIdentifiable) => string,
public ab: { data: string },
public le?: number[]
) {}

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ListSearchService);
public fi(): string {
return this._fi(this);
}
}

describe(`ListSearchService`, () => {
let service: ListSearchService<MockIdentifiable>;

const data = {
strings: [`an`, `apple`, `a`, `day`, `keeps`, `the`, `doctor`, `away`],
numbers: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89],
booleans: [true, false, false, true, true, true, false, true, false],
functions: [
(originItem: MockIdentifiable) => originItem.en,
() => `banana`,
(originItem: MockIdentifiable) => originItem.ab.data
],
generate: [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 92]
};

function getSourceData(length = 25): MockIdentifiable[] {
return Array.from({ length }, (value, index) => index).map(
id =>
new MockIdentifiable(
id,
data.strings[id % data.strings.length],
data.booleans[id % data.booleans.length],
data.functions[id % data.functions.length],
{
data: data.strings[(id + 3) % data.strings.length].split(``).reverse().join(``)
},
data.generate.slice(
data.generate[id % data.generate.length] % data.generate.length,
Math.max(
id % data.generate.length,
data.generate[id % data.generate.length] % data.generate.length
) + 1
)
)
);
}

function generateService(filterProps: string[], alsoFilterByProperties: string[] = []): void {
service = new ListSearchService(filterProps, alsoFilterByProperties);
}

function getWaitUntilPromiseForService(
condition: (data: MockIdentifiable[]) => boolean,
skipOver = 0
): Promise<number[]> {
return firstValueFrom(
service.outputObservable.pipe(
filter(condition),
skip(skipOver),
map(arr => arr.map(item => item.id))
)
);
}

afterEach(() => {
service.exitSearchService();
});

it(`test search without properties`, async () => {
generateService([]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`apple`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25, 1)).toBePending();
});

it(`test search without data`, async () => {
generateService([`en`]);
service.initSearchService(new BehaviorSubject([]));
expect(() => service.search(`apple`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 0, 1)).toBePending();
});

it(`test search with data and properites`, async () => {
generateService([`ti`]);
service.initSearchService(new BehaviorSubject(getSourceData(10)));
expect(() => service.search(`true`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([0, 3, 4, 5, 7, 9]);
});

it(`test search with alsoFilterByProperties`, async () => {
generateService([`ti`], [`en`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`doctor`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([6, 14, 22]);
});

it(`test search trim`, async () => {
generateService([`ti`], [`en`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`doctor `)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([6, 14, 22]);
});

it(`test search function`, async () => {
generateService([`fi`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`doctor`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([6]);
service.exitSearchService();
generateService([`fi`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`banana`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([
1, 4, 7, 10, 13, 16, 19, 22
]);
});

it(`test search number`, async () => {
generateService([`id`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`5`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([5, 15]);
});

it(`test search array`, async () => {
generateService([`le`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`5`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([
4, 5, 6, 8, 9, 10, 11, 12, 17, 18, 19, 21, 22, 23, 24
]);
});

it(`test if search doesn't include other property values`, async () => {
generateService([`ti`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`doctor`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([]);
});

it(`test search with multiple properties`, async () => {
generateService([`le`, `id`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`5`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([
4, 5, 6, 8, 9, 10, 11, 12, 15, 17, 18, 19, 21, 22, 23, 24
]);
});

it(`test search with multiple properties of different types`, async () => {
generateService([`en`, `id`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`5`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([5, 15]);
});

it(`test if really only the first additional property is searched`, async () => {
generateService([`ti`], [`en`, `id`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`5`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([]);
});

it(`test if the second additional property is used, if the first isn't filled`, async () => {
generateService([`ti`], [`le`, `en`]);
service.initSearchService(
new BehaviorSubject(
getSourceData(25).map((val, index) =>
index % 2 ? val : new MockIdentifiable(val.id, val.en, val.ti, val.fi, val.ab)
)
)
);
expect(() => service.search(`a`)).not.toThrow();
// does not contain uneven ids, even though `en` for 1 should be `apple`
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([
0, 2, 8, 10, 16, 18, 24
]);
});

it(`should be created`, () => {
expect(service).toBeTruthy();
it(`test search with nested properties`, async () => {
generateService([`ab.data`]);
service.initSearchService(new BehaviorSubject(getSourceData(25)));
expect(() => service.search(`elppa`)).not.toThrow();
await expectAsync(getWaitUntilPromiseForService(data => data.length !== 25)).toBeResolvedTo([6, 14, 22]);
});
});
Loading

0 comments on commit ec8723c

Please sign in to comment.