Feature/move tags from info to user service (#3859)
* Move tags from info to user service * Update changelog
This commit is contained in:
parent
fc5ed887ff
commit
98957d282e
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Moved the tags from the info to the user service
|
||||
- Switched the `prefer-const` rule from `warn` to `error` in the `eslint` configuration
|
||||
|
||||
## 2.113.0 - 2024-10-06
|
||||
|
@ -9,7 +9,6 @@ import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-d
|
||||
import { PropertyModule } from '@ghostfolio/api/services/property/property.module';
|
||||
import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module';
|
||||
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module';
|
||||
import { TagModule } from '@ghostfolio/api/services/tag/tag.module';
|
||||
|
||||
import { Module } from '@nestjs/common';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
@ -33,7 +32,6 @@ import { InfoService } from './info.service';
|
||||
PropertyModule,
|
||||
RedisCacheModule,
|
||||
SymbolProfileModule,
|
||||
TagModule,
|
||||
TransformDataSourceInResponseModule,
|
||||
UserModule
|
||||
],
|
||||
|
@ -5,7 +5,6 @@ import { UserService } from '@ghostfolio/api/app/user/user.service';
|
||||
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
|
||||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
|
||||
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
|
||||
import { TagService } from '@ghostfolio/api/services/tag/tag.service';
|
||||
import {
|
||||
DEFAULT_CURRENCY,
|
||||
PROPERTY_BETTER_UPTIME_MONITOR_ID,
|
||||
@ -47,7 +46,6 @@ export class InfoService {
|
||||
private readonly platformService: PlatformService,
|
||||
private readonly propertyService: PropertyService,
|
||||
private readonly redisCacheService: RedisCacheService,
|
||||
private readonly tagService: TagService,
|
||||
private readonly userService: UserService
|
||||
) {}
|
||||
|
||||
@ -103,8 +101,7 @@ export class InfoService {
|
||||
isUserSignupEnabled,
|
||||
platforms,
|
||||
statistics,
|
||||
subscriptions,
|
||||
tags
|
||||
subscriptions
|
||||
] = await Promise.all([
|
||||
this.benchmarkService.getBenchmarkAssetProfiles(),
|
||||
this.getDemoAuthToken(),
|
||||
@ -113,8 +110,7 @@ export class InfoService {
|
||||
orderBy: { name: 'asc' }
|
||||
}),
|
||||
this.getStatistics(),
|
||||
this.getSubscriptions(),
|
||||
this.tagService.getPublic()
|
||||
this.getSubscriptions()
|
||||
]);
|
||||
|
||||
if (isUserSignupEnabled) {
|
||||
@ -130,7 +126,6 @@ export class InfoService {
|
||||
platforms,
|
||||
statistics,
|
||||
subscriptions,
|
||||
tags,
|
||||
baseCurrency: DEFAULT_CURRENCY,
|
||||
currencies: this.exchangeRateDataService.getCurrencies()
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ export class UserService {
|
||||
{ Account, id, permissions, Settings, subscription }: UserWithSettings,
|
||||
aLocale = locale
|
||||
): Promise<IUser> {
|
||||
const accessesResult = await Promise.all([
|
||||
const userData = await Promise.all([
|
||||
this.prismaService.access.findMany({
|
||||
include: {
|
||||
User: true
|
||||
@ -70,11 +70,11 @@ export class UserService {
|
||||
},
|
||||
where: { userId: id }
|
||||
}),
|
||||
this.tagService.getInUseByUser(id)
|
||||
this.tagService.getTagsForUser(id)
|
||||
]);
|
||||
const access = accessesResult[0];
|
||||
const firstActivity = accessesResult[1];
|
||||
let tags = accessesResult[2];
|
||||
const access = userData[0];
|
||||
const firstActivity = userData[1];
|
||||
let tags = userData[2];
|
||||
|
||||
let systemMessage: SystemMessage;
|
||||
|
||||
|
@ -6,29 +6,39 @@ import { Injectable } from '@nestjs/common';
|
||||
export class TagService {
|
||||
public constructor(private readonly prismaService: PrismaService) {}
|
||||
|
||||
public async getPublic() {
|
||||
return this.prismaService.tag.findMany({
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
},
|
||||
where: {
|
||||
userId: null
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async getInUseByUser(userId: string) {
|
||||
return this.prismaService.tag.findMany({
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
},
|
||||
where: {
|
||||
orders: {
|
||||
some: {
|
||||
userId
|
||||
public async getTagsForUser(userId: string) {
|
||||
const tags = await this.prismaService.tag.findMany({
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
orders: {
|
||||
where: {
|
||||
userId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
},
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
userId
|
||||
},
|
||||
{
|
||||
userId: null
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
return tags.map(({ _count, id, name, userId }) => ({
|
||||
id,
|
||||
name,
|
||||
userId,
|
||||
isUsed: _count.orders > 0
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -147,8 +147,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
||||
) {}
|
||||
|
||||
public ngOnInit() {
|
||||
const { tags } = this.dataService.fetchInfo();
|
||||
|
||||
this.activityForm = this.formBuilder.group({
|
||||
tags: <string[]>[]
|
||||
});
|
||||
@ -158,13 +156,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
||||
{ id: this.data.symbol, type: 'SYMBOL' }
|
||||
];
|
||||
|
||||
this.tagsAvailable = tags.map((tag) => {
|
||||
return {
|
||||
...tag,
|
||||
name: translate(tag.name)
|
||||
};
|
||||
});
|
||||
|
||||
this.activityForm
|
||||
.get('tags')
|
||||
.valueChanges.pipe(takeUntil(this.unsubscribeSubject))
|
||||
@ -434,6 +425,14 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
||||
if (state?.user) {
|
||||
this.user = state.user;
|
||||
|
||||
this.tagsAvailable =
|
||||
this.user?.tags?.map((tag) => {
|
||||
return {
|
||||
...tag,
|
||||
name: translate(tag.name)
|
||||
};
|
||||
}) ?? [];
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
}
|
||||
});
|
||||
|
@ -76,17 +76,19 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
|
||||
this.locale = this.data.user?.settings?.locale;
|
||||
this.dateAdapter.setLocale(this.locale);
|
||||
|
||||
const { currencies, platforms, tags } = this.dataService.fetchInfo();
|
||||
const { currencies, platforms } = this.dataService.fetchInfo();
|
||||
|
||||
this.currencies = currencies;
|
||||
this.defaultDateFormat = getDateFormatString(this.locale);
|
||||
this.platforms = platforms;
|
||||
this.tagsAvailable = tags.map((tag) => {
|
||||
return {
|
||||
...tag,
|
||||
name: translate(tag.name)
|
||||
};
|
||||
});
|
||||
|
||||
this.tagsAvailable =
|
||||
this.data.user?.tags?.map((tag) => {
|
||||
return {
|
||||
...tag,
|
||||
name: translate(tag.name)
|
||||
};
|
||||
}) ?? [];
|
||||
|
||||
Object.keys(Type).forEach((type) => {
|
||||
this.typesTranslationMap[Type[type]] = translate(Type[type]);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SubscriptionOffer } from '@ghostfolio/common/types';
|
||||
|
||||
import { Platform, SymbolProfile, Tag } from '@prisma/client';
|
||||
import { Platform, SymbolProfile } from '@prisma/client';
|
||||
|
||||
import { Statistics } from './statistics.interface';
|
||||
import { Subscription } from './subscription.interface';
|
||||
@ -19,5 +19,4 @@ export interface InfoItem {
|
||||
statistics: Statistics;
|
||||
stripePublicKey?: string;
|
||||
subscriptions: { [offer in SubscriptionOffer]: Subscription };
|
||||
tags: Tag[];
|
||||
}
|
||||
|
@ -23,5 +23,5 @@ export interface User {
|
||||
offer: SubscriptionOffer;
|
||||
type: SubscriptionType;
|
||||
};
|
||||
tags: Tag[];
|
||||
tags: (Tag & { isUsed: boolean })[];
|
||||
}
|
||||
|
@ -156,7 +156,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
|
||||
) {}
|
||||
|
||||
public ngOnInit() {
|
||||
this.accounts = this.user?.accounts;
|
||||
this.assetClasses = Object.keys(AssetClass).map((assetClass) => {
|
||||
return {
|
||||
id: assetClass,
|
||||
@ -164,13 +163,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
|
||||
type: 'ASSET_CLASS'
|
||||
};
|
||||
});
|
||||
this.tags = this.user?.tags.map(({ id, name }) => {
|
||||
return {
|
||||
id,
|
||||
label: translate(name),
|
||||
type: 'TAG'
|
||||
};
|
||||
});
|
||||
|
||||
this.searchFormControl.valueChanges
|
||||
.pipe(
|
||||
@ -212,6 +204,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
public ngOnChanges() {
|
||||
this.accounts = this.user?.accounts ?? [];
|
||||
|
||||
this.dateRangeOptions = [
|
||||
{ label: $localize`Today`, value: '1d' },
|
||||
{
|
||||
@ -279,6 +273,23 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
|
||||
emitEvent: false
|
||||
}
|
||||
);
|
||||
|
||||
this.tags =
|
||||
this.user?.tags
|
||||
?.filter(({ isUsed }) => {
|
||||
return isUsed;
|
||||
})
|
||||
.map(({ id, name }) => {
|
||||
return {
|
||||
id,
|
||||
label: translate(name),
|
||||
type: 'TAG'
|
||||
};
|
||||
}) ?? [];
|
||||
|
||||
if (this.tags.length === 0) {
|
||||
this.filterForm.get('tag').disable({ emitEvent: false });
|
||||
}
|
||||
}
|
||||
|
||||
public hasFilter(aFormValue: { [key: string]: string }) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user