Skip to content

Commit

Permalink
Merge pull request #322 from swisstopo/feature/assets-19-favoriten
Browse files Browse the repository at this point in the history
Feature 19: Favoriten | Erstellung & Verwaltung
  • Loading branch information
daniel-va authored Nov 7, 2024
2 parents 517eab7 + b2df577 commit 5a396b4
Show file tree
Hide file tree
Showing 79 changed files with 716 additions and 268 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,23 @@
asset-sg-menu-bar-item
icon="assets"
[link]="isActive ? null : [translateService.currentLang]"
[isActive]="isActive && ((isFiltersOpen$ | async) ?? false)"
[isActive]="isActive"
(click)="isActive ? toggleAssetDrawer() : null"
>
menuBar.filters
</li>
<li *ngIf="userExists$ | async" asset-sg-menu-bar-item icon="favourite" disabled>menuBar.favourites</li>
@if (userExists$ | async) {
<li
*rxLet="activeItem === 'favorites'; let isActive"
asset-sg-menu-bar-item
icon="favorite"
[link]="isActive ? null : [translateService.currentLang, 'favorites']"
[isActive]="isActive"
(click)="isActive ? toggleAssetDrawer() : null"
>
menuBar.favourites
</li>
}
<li
*canCreate="AssetEditPolicy"
asset-sg-menu-bar-item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ export class MenuBarComponent {

readonly activeItem$: Observable<MenuItem | null> = this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
startWith(() => undefined),
map((): MenuItem | null => {
const segments = this.router.parseUrl(this.router.url).root.children['primary'].segments;
if (segments.length === 1) {
const segments = (this.router.getCurrentNavigation() ?? this.router.lastSuccessfulNavigation)?.finalUrl?.root
.children['primary'].segments;
if (segments == null || segments.length === 1) {
return 'home';
}
const path = segments.slice(1).join('/');
Expand All @@ -43,6 +45,9 @@ export class MenuBarComponent {
if (isPath('asset-admin/new')) {
return 'create-asset';
}
if (isPath('favorites')) {
return 'favorites';
}
if (path == 'asset-admin' || isPath('admin')) {
return 'options';
}
Expand All @@ -58,4 +63,4 @@ export class MenuBarComponent {
protected readonly AssetEditPolicy = AssetEditPolicy;
}

type MenuItem = 'home' | 'create-asset' | 'options';
type MenuItem = 'home' | 'favorites' | 'create-asset' | 'options';
3 changes: 3 additions & 0 deletions apps/client-asset-sg/src/app/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export const deAppTranslations = {
nameTaken: "Der Name '{{name}}' wird bereits von einer anderen Arbeitsgruppe verwendet.",
},
},
favorites: {
title: 'Favoriten',
},
menuBar: {
filters: 'Filter',
admin: 'Verwaltung',
Expand Down
3 changes: 3 additions & 0 deletions apps/client-asset-sg/src/app/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export const enAppTranslations: AppTranslations = {
nameTaken: "The name '{{name}}' is already taken by another workgroup.",
},
},
favorites: {
title: 'Favorites',
},
menuBar: {
filters: 'Filters',
admin: 'Administration',
Expand Down
3 changes: 3 additions & 0 deletions apps/client-asset-sg/src/app/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export const frAppTranslations: AppTranslations = {
nameTaken: "Le nom '{{name}}' est déjà utilisé par un autre groupe de travail.",
},
},
favorites: {
title: 'Favorites',
},
menuBar: {
filters: 'Filtres',
admin: 'Administration',
Expand Down
3 changes: 3 additions & 0 deletions apps/client-asset-sg/src/app/i18n/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export const itAppTranslations: AppTranslations = {
nameTaken: "IT Der Name '{{name}}' wird bereits von einer anderen Arbeitsgruppe verwendet.",
},
},
favorites: {
title: 'IT Favoriten',
},
menuBar: {
filters: 'IT Filter',
admin: 'IT Verwaltung',
Expand Down
3 changes: 3 additions & 0 deletions apps/client-asset-sg/src/app/i18n/rm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export const rmAppTranslations: AppTranslations = {
nameTaken: "RM Name '{{name}}' wird bereits von einer anderen Arbeitsgruppe verwendet.",
},
},
favorites: {
title: 'RM Favoriten',
},
menuBar: {
filters: 'RM Filter',
admin: 'RM Verwaltung',
Expand Down
24 changes: 20 additions & 4 deletions apps/server-asset-sg/src/app.logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,30 @@ export class AppLogger implements LoggerService {
if (!(message instanceof Error)) {
output += level.color(`${message}`);
}
const suffix = [];
if (params.length !== 0 && !(params.length === 1 && params[0] === undefined)) {
output += ' ' + stringify(params, level);
let i = 0;
while (typeof params[i] === 'string') {
const line = params[i] as string;
suffix.push(line);
i += 1;
if (i >= params.length || line.endsWith('\n')) {
break;
}
}
params = params.slice(i);
if (params.length !== 0) {
output += ' ' + stringify(params, level);
}
}
const args: unknown[] = [`${prefix} ${output}`];
if (message instanceof Error) {
console.log(`${prefix} ${output}`, message);
} else {
console.log(`${prefix} ${output}`);
args.push(message);
}
if (suffix.length !== 0) {
args.push(level.color(`\n${suffix.join('\n')}`));
}
console.log(...args);
}
}

Expand Down
2 changes: 1 addition & 1 deletion apps/server-asset-sg/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ import { WorkgroupsController } from '@/features/workgroups/workgroups.controlle
@Module({
controllers: [
AppController,
FavoritesController,
AssetEditController,
AssetSearchController,
AssetSyncController,
AssetsController,
ContactsController,
FavoritesController,
FilesController,
StudiesController,
UsersController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { fakeAssetFormatItemCode } from '../../../../../test/data/asset-format-i
// eslint-disable-next-line @nx/enforce-module-boundaries
import { fakeAssetKindItemCode } from '../../../../../test/data/asset-kind-item';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { fakeContactKindItem } from '../../../../../test/data/contact-kind-item';
import { fakeContactKindItemCode } from '../../../../../test/data/contact-kind-item';

import { define } from '@/utils/define';

Expand All @@ -35,7 +35,7 @@ export const fakeUser = () => {

export const fakeContact = () =>
define<Omit<Contact, 'id'>>({
contactKindItemCode: fakeContactKindItem(),
contactKindItemCode: fakeContactKindItemCode(),
name: faker.company.name(),
street: faker.location.street(),
houseNumber: faker.location.buildingNumber(),
Expand Down
18 changes: 17 additions & 1 deletion apps/server-asset-sg/src/features/assets/asset-info.repo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { AssetId, AssetInfo } from '@asset-sg/shared/v2';
import { AssetId, AssetInfo, UserId } from '@asset-sg/shared/v2';
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@/core/prisma.service';
import { ReadRepo, RepoListOptions } from '@/core/repo';
import { assetInfoSelection, parseAssetInfoFromPrisma } from '@/features/assets/prisma-asset';

@Injectable()
export class AssetInfoRepo implements ReadRepo<AssetInfo, AssetId> {
constructor(private readonly prisma: PrismaService) {}

Expand All @@ -28,4 +30,18 @@ export class AssetInfoRepo implements ReadRepo<AssetInfo, AssetId> {
});
return entries.map(parseAssetInfoFromPrisma);
}

async listFavorites(userId: UserId): Promise<AssetInfo[]> {
const entries = await this.prisma.asset.findMany({
where: {
favorites: {
some: {
userId: userId,
},
},
},
select: assetInfoSelection,
});
return entries.map(parseAssetInfoFromPrisma);
}
}
4 changes: 2 additions & 2 deletions apps/server-asset-sg/src/features/assets/asset.repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { handlePrismaMutationError } from '@/utils/prisma';
export class AssetRepo implements FindRepo<Asset, AssetId>, MutateRepo<Asset, AssetId, FullAssetData> {
constructor(private readonly prisma: PrismaService) {}

async count() {
return await this.prisma.asset.count();
async count(): Promise<number> {
return this.prisma.asset.count();
}

async find(id: AssetId): Promise<Asset | null> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class AssetSearchController {
limit = limit == null ? limit : Number(limit);
offset = offset == null ? offset : Number(offset);
restrictQueryForUser(query, user);
const result = await this.assetSearchService.search(query, { limit, offset, decode: false });
const result = await this.assetSearchService.search(query, user, { limit, offset, decode: false });
return plainToInstance(AssetSearchResultDTO, result);
}

Expand All @@ -48,7 +48,7 @@ export class AssetSearchController {
@CurrentUser() user: User
): Promise<AssetSearchStats> {
restrictQueryForUser(query, user);
const stats = await this.assetSearchService.aggregate(query);
const stats = await this.assetSearchService.aggregate(query, user);
return plainToInstance(AssetSearchStatsDTO, stats);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ describe(AssetSearchService, () => {
await create({ patch: fakeAssetPatch(), user });

// When
const result = await service.search({ text: `${text}` });
const result = await service.search({ text: `${text}` }, user);

// Then
assertSingleResult(result, asset);
Expand Down Expand Up @@ -194,11 +194,14 @@ describe(AssetSearchService, () => {
});

// When
const result = await service.search({
createDate: {
min: new Date(dateFromDateId(asset.createDate).getTime() - millisPerDay),
const result = await service.search(
{
createDate: {
min: new Date(dateFromDateId(asset.createDate).getTime() - millisPerDay),
},
},
});
user
);

// Then
assertSingleResult(result, asset);
Expand All @@ -217,11 +220,14 @@ describe(AssetSearchService, () => {
});

// When
const result = await service.search({
createDate: {
max: new Date(dateFromDateId(asset.createDate).getTime() + millisPerDay),
const result = await service.search(
{
createDate: {
max: new Date(dateFromDateId(asset.createDate).getTime() + millisPerDay),
},
},
});
user
);

// Then
assertSingleResult(result, asset);
Expand All @@ -244,14 +250,18 @@ describe(AssetSearchService, () => {
},
user: fakeUser(),
});
const user = fakeUser();

// When
const result = await service.search({
createDate: {
min: new Date(dateFromDateId(asset.createDate).getTime() - millisPerDay),
max: new Date(dateFromDateId(asset.createDate).getTime() + millisPerDay),
const result = await service.search(
{
createDate: {
min: new Date(dateFromDateId(asset.createDate).getTime() - millisPerDay),
max: new Date(dateFromDateId(asset.createDate).getTime() + millisPerDay),
},
},
});
user
);

// Then
assertSingleResult(result, asset);
Expand All @@ -274,9 +284,10 @@ describe(AssetSearchService, () => {
patch: { ...fakeAssetPatch(), assetLanguages: [{ languageItemCode: code3 }] },
user: fakeUser(),
});
const user = fakeUser();

// When
const result = await service.search({ languageItemCodes: [code1] });
const result = await service.search({ languageItemCodes: [code1] }, user);

// Then
assertSingleResult(result, asset);
Expand All @@ -293,7 +304,7 @@ describe(AssetSearchService, () => {
await create({ patch: { ...fakeAssetPatch(), assetKindItemCode: code3 }, user });

// When
const result = await service.search({ assetKindItemCodes: [code1] });
const result = await service.search({ assetKindItemCodes: [code1] }, user);

// Then
assertSingleResult(result, asset);
Expand All @@ -310,7 +321,7 @@ describe(AssetSearchService, () => {
await create({ patch: { ...fakeAssetPatch(), manCatLabelRefs: [code3] }, user });

// When
const result = await service.search({ manCatLabelItemCodes: [code1] });
const result = await service.search({ manCatLabelItemCodes: [code1] }, user);

// Then
assertSingleResult(result, asset);
Expand Down Expand Up @@ -346,7 +357,7 @@ describe(AssetSearchService, () => {
});

// When
const result = await service.search({ usageCodes: [usageCode] });
const result = await service.search({ usageCodes: [usageCode] }, user);

// Then
assertSingleResult(result, asset);
Expand All @@ -371,7 +382,7 @@ describe(AssetSearchService, () => {
});

// When
const result = await service.search({ authorId: contact1.contactId });
const result = await service.search({ authorId: contact1.contactId }, user);

// Then
assertSingleResult(result, asset);
Expand Down Expand Up @@ -417,8 +428,11 @@ describe(AssetSearchService, () => {
};

it('returns empty stats when no assets are present', async () => {
// Given
const user = fakeUser();

// When
const result = await service.aggregate({});
const result = await service.aggregate({}, user);

// Then
expect(result.total).toEqual(0);
Expand All @@ -436,7 +450,7 @@ describe(AssetSearchService, () => {
const asset = await create({ patch: fakeAssetPatch(), user });

// When
const result = await service.aggregate({});
const result = await service.aggregate({}, user);

// Then
assertSingleStats(result, asset);
Expand Down
Loading

0 comments on commit 5a396b4

Please sign in to comment.