Browse Source

Task/extend entity logo component by hasPlaceholder attribute (#7553)

* Extend entity logo component by hasPlaceholder attribute

* Update changelog
pull/7559/head
Thomas Kaul 1 day ago
committed by GitHub
parent
commit
0e3e17580a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 3
      apps/client/src/app/components/admin-platform/admin-platform.component.html
  3. 6
      apps/client/src/app/components/admin-settings/admin-settings.component.html
  4. 4
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html
  5. 6
      apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html
  6. 6
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
  7. 10
      libs/ui/src/lib/accounts-table/accounts-table.component.html
  8. 3
      libs/ui/src/lib/activities-table/activities-table.component.html
  9. 7
      libs/ui/src/lib/entity-logo/entity-logo.component.html
  10. 12
      libs/ui/src/lib/entity-logo/entity-logo.component.scss
  11. 16
      libs/ui/src/lib/entity-logo/entity-logo.component.stories.ts
  12. 12
      libs/ui/src/lib/entity-logo/entity-logo.component.ts
  13. 7
      libs/ui/src/lib/mocks/entity-logo-image-source.service.mock.ts
  14. 3
      libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.html

1
CHANGELOG.md

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added a live preview of the date and number format to the user settings - Added a live preview of the date and number format to the user settings
- Added the country flag to the currency selector - Added the country flag to the currency selector
- Added a _Storybook_ story for the currency selector component - Added a _Storybook_ story for the currency selector component
- Extended the entity logo component by a `hasPlaceholder` attribute to reserve the space of a missing logo
### Changed ### Changed

3
apps/client/src/app/components/admin-platform/admin-platform.component.html

@ -22,13 +22,12 @@
<ng-container i18n>Name</ng-container> <ng-container i18n>Name</ng-container>
</th> </th>
<td *matCellDef="let element" class="px-1" mat-cell> <td *matCellDef="let element" class="px-1" mat-cell>
@if (element.url) {
<gf-entity-logo <gf-entity-logo
class="d-inline mr-1" class="d-inline mr-1"
[hasPlaceholder]="true"
[tooltip]="element.name" [tooltip]="element.name"
[url]="element.url" [url]="element.url"
/> />
}
<span>{{ element.name }}</span> <span>{{ element.name }}</span>
</td></ng-container </td></ng-container
> >

6
apps/client/src/app/components/admin-settings/admin-settings.component.html

@ -59,7 +59,11 @@
</th> </th>
<td *matCellDef="let element" class="px-1" mat-cell> <td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<gf-entity-logo class="mr-1" [url]="element.url" /> <gf-entity-logo
class="mr-1"
[hasPlaceholder]="true"
[url]="element.url"
/>
<div> <div>
@if (isGhostfolioDataProvider(element)) { @if (isGhostfolioDataProvider(element)) {
<a <a

4
apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html

@ -46,10 +46,11 @@
<div [class.d-none]="platforms?.length < 1"> <div [class.d-none]="platforms?.length < 1">
<mat-form-field appearance="outline" class="w-100"> <mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Platform</mat-label> <mat-label i18n>Platform</mat-label>
@if (selectedPlatform?.url) { @if (selectedPlatform) {
<gf-entity-logo <gf-entity-logo
class="ml-3" class="ml-3"
matPrefix matPrefix
[hasPlaceholder]="true"
[tooltip]="selectedPlatform?.name" [tooltip]="selectedPlatform?.name"
[url]="selectedPlatform?.url" [url]="selectedPlatform?.url"
/> />
@ -71,6 +72,7 @@
<span class="d-flex"> <span class="d-flex">
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="platformEntry.name" [tooltip]="platformEntry.name"
[url]="platformEntry.url" [url]="platformEntry.url"
/> />

6
apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.html

@ -13,13 +13,12 @@
@for (account of accounts; track account) { @for (account of accounts; track account) {
<mat-option [value]="account.id"> <mat-option [value]="account.id">
<div class="d-flex"> <div class="d-flex">
@if (account.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="account.platform?.name" [tooltip]="account.platform?.name"
[url]="account.platform?.url" [url]="account.platform?.url"
/> />
}
<span>{{ account.name }}</span> <span>{{ account.name }}</span>
</div> </div>
</mat-option> </mat-option>
@ -34,13 +33,12 @@
@for (account of accounts; track account) { @for (account of accounts; track account) {
<mat-option [value]="account.id"> <mat-option [value]="account.id">
<div class="d-flex"> <div class="d-flex">
@if (account.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="account.platform?.name" [tooltip]="account.platform?.name"
[url]="account.platform?.url" [url]="account.platform?.url"
/> />
}
<span>{{ account.name }}</span> <span>{{ account.name }}</span>
</div> </div>
</mat-option> </mat-option>

6
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html

@ -87,9 +87,10 @@
<mat-select formControlName="accountId"> <mat-select formControlName="accountId">
<mat-select-trigger> <mat-select-trigger>
<div class="d-flex"> <div class="d-flex">
@if (selectedAccount?.platform?.url) { @if (selectedAccount) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="selectedAccount?.platform?.name" [tooltip]="selectedAccount?.platform?.name"
[url]="selectedAccount?.platform?.url" [url]="selectedAccount?.platform?.url"
/> />
@ -103,13 +104,12 @@
@for (account of data.accounts; track account) { @for (account of data.accounts; track account) {
<mat-option [value]="account.id"> <mat-option [value]="account.id">
<div class="d-flex"> <div class="d-flex">
@if (account.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="account.platform?.name" [tooltip]="account.platform?.name"
[url]="account.platform?.url" [url]="account.platform?.url"
/> />
}
<span>{{ account.name }}</span> <span>{{ account.name }}</span>
</div> </div>
</mat-option> </mat-option>

10
libs/ui/src/lib/accounts-table/accounts-table.component.html

@ -50,13 +50,12 @@
<ng-container i18n>Name</ng-container> <ng-container i18n>Name</ng-container>
</th> </th>
<td *matCellDef="let element" class="px-1 text-nowrap" mat-cell> <td *matCellDef="let element" class="px-1 text-nowrap" mat-cell>
@if (element.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="d-inline d-sm-none mr-1" class="d-inline d-sm-none mr-1"
[hasPlaceholder]="true"
[tooltip]="element.platform?.name" [tooltip]="element.platform?.name"
[url]="element.platform.url" [url]="element.platform?.url"
/> />
}
<span>{{ element.name }}</span> <span>{{ element.name }}</span>
</td> </td>
<td *matFooterCellDef class="px-1" i18n mat-footer-cell>Total</td> <td *matFooterCellDef class="px-1" i18n mat-footer-cell>Total</td>
@ -98,13 +97,12 @@
mat-cell mat-cell
> >
<div class="d-flex"> <div class="d-flex">
@if (element.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="element.platform?.name" [tooltip]="element.platform?.name"
[url]="element.platform.url" [url]="element.platform?.url"
/> />
}
<span>{{ element.platform?.name }}</span> <span>{{ element.platform?.name }}</span>
</div> </div>
</td> </td>

3
libs/ui/src/lib/activities-table/activities-table.component.html

@ -356,13 +356,12 @@
</th> </th>
<td *matCellDef="let element" class="px-1" mat-cell> <td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex"> <div class="d-flex">
@if (element.account?.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="element.account?.platform?.name" [tooltip]="element.account?.platform?.name"
[url]="element.account?.platform?.url" [url]="element.account?.platform?.url"
/> />
}
<span class="d-none d-lg-block text-nowrap">{{ <span class="d-none d-lg-block text-nowrap">{{
element.account?.name element.account?.name
}}</span> }}</span>

7
libs/ui/src/lib/entity-logo/entity-logo.component.html

@ -1,8 +1,11 @@
@if (src) { @if (src && !hasError) {
<img <img
onerror="this.style.display = 'none'" class="logo"
[class.large]="size === 'large'" [class.large]="size === 'large'"
[src]="src" [src]="src"
[title]="tooltip ? tooltip : ''" [title]="tooltip ? tooltip : ''"
(error)="onError()"
/> />
} @else if (hasPlaceholder) {
<div class="logo placeholder" [class.large]="size === 'large'"></div>
} }

12
libs/ui/src/lib/entity-logo/entity-logo.component.scss

@ -2,7 +2,7 @@
align-items: center; align-items: center;
display: flex; display: flex;
img { .logo {
border-radius: 0.2rem; border-radius: 0.2rem;
height: 0.8rem; height: 0.8rem;
width: 0.8rem; width: 0.8rem;
@ -11,5 +11,15 @@
height: 1.4rem; height: 1.4rem;
width: 1.4rem; width: 1.4rem;
} }
&.placeholder {
border: 1px solid rgba(var(--dark-dividers));
}
}
}
:host-context(.theme-dark) {
.placeholder {
border-color: rgba(var(--light-dividers));
} }
} }

16
libs/ui/src/lib/entity-logo/entity-logo.component.stories.ts

@ -44,3 +44,19 @@ export const LogoByUrl: Story = {
url: 'https://ghostfol.io' url: 'https://ghostfol.io'
} }
}; };
export const Placeholder: Story = {
args: {
hasPlaceholder: true,
size: 'large'
}
};
export const PlaceholderOnError: Story = {
args: {
hasPlaceholder: true,
size: 'large',
tooltip: 'Unknown',
url: 'https://unknown.ghostfol.io'
}
};

12
libs/ui/src/lib/entity-logo/entity-logo.component.ts

@ -18,18 +18,22 @@ import { DataSource } from '@prisma/client';
}) })
export class GfEntityLogoComponent implements OnChanges { export class GfEntityLogoComponent implements OnChanges {
@Input() dataSource: DataSource; @Input() dataSource: DataSource;
@Input() hasPlaceholder = false;
@Input() size: 'large'; @Input() size: 'large';
@Input() symbol: string; @Input() symbol: string;
@Input() tooltip: string; @Input() tooltip: string;
@Input() url: string; @Input() url: string;
public src: string; public hasError = false;
public src?: string;
public constructor( public constructor(
private readonly imageSourceService: EntityLogoImageSourceService private readonly imageSourceService: EntityLogoImageSourceService
) {} ) {}
public ngOnChanges() { public ngOnChanges() {
this.hasError = false;
if (this.dataSource && this.symbol) { if (this.dataSource && this.symbol) {
this.src = this.imageSourceService.getLogoUrlByAssetProfileIdentifier({ this.src = this.imageSourceService.getLogoUrlByAssetProfileIdentifier({
dataSource: this.dataSource, dataSource: this.dataSource,
@ -37,6 +41,12 @@ export class GfEntityLogoComponent implements OnChanges {
}); });
} else if (this.url) { } else if (this.url) {
this.src = this.imageSourceService.getLogoUrlByUrl(this.url); this.src = this.imageSourceService.getLogoUrlByUrl(this.url);
} else {
this.src = undefined;
}
} }
public onError() {
this.hasError = true;
} }
} }

7
libs/ui/src/lib/mocks/entity-logo-image-source.service.mock.ts

@ -2,6 +2,9 @@ import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
import { DataSource } from '@prisma/client'; import { DataSource } from '@prisma/client';
// Resolves like a logo of an unknown entity, but fails to load
const UNAVAILABLE_LOGO_URL = 'data:image/png;base64,unavailable';
export class EntityLogoImageSourceServiceMock { export class EntityLogoImageSourceServiceMock {
public getLogoUrlByAssetProfileIdentifier({ public getLogoUrlByAssetProfileIdentifier({
dataSource, dataSource,
@ -11,7 +14,7 @@ export class EntityLogoImageSourceServiceMock {
return 'data:image/png;base64,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'; return 'data:image/png;base64,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';
} }
return ''; return UNAVAILABLE_LOGO_URL;
} }
public getLogoUrlByUrl(url: string) { public getLogoUrlByUrl(url: string) {
@ -19,6 +22,6 @@ export class EntityLogoImageSourceServiceMock {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEU2z8v////x/Pspzcn0/Px73drR8/KC3tz6/v6e5eOl5+WM4d7n+PhI08/i9/eu6edV1dJk2NVx2teV4+G87evvttLSAAABDElEQVRYhe2V3Y6EIAyFrQXlTwHd93/WpeBsdiKbtF7tJJwbCKFfDlKO0zQ0NPQJwqrn1ZO2zlk9PWPgusClRcsJmHb4pWUTItDDu4zMBJ5w0yog4HGvB0gCgOoBZrYFdL16AMsmmD5AcQ3ofj3AwbOAX38BIhMw02ZjtQ+tLnht66mCAGA2eka1G3eabUZwD/PLbeuHenKMBODVV0Dru/TTQLgKAc1BvQ/9yAEkOnlon66oehEBIHp7dbSyPoIc0NEADMDnAa4wAvVK+CADRGx/VpNSi+iF3jMTUH4rJQ0aISPmVk+JoJiZeJw1QnaqL2OmWKSFkxnrZWsbXK4TzO5tmS+8TYaGhv6xvgEEfAgHGc7HRgAAAABJRU5ErkJggg=='; return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEU2z8v////x/Pspzcn0/Px73drR8/KC3tz6/v6e5eOl5+WM4d7n+PhI08/i9/eu6edV1dJk2NVx2teV4+G87evvttLSAAABDElEQVRYhe2V3Y6EIAyFrQXlTwHd93/WpeBsdiKbtF7tJJwbCKFfDlKO0zQ0NPQJwqrn1ZO2zlk9PWPgusClRcsJmHb4pWUTItDDu4zMBJ5w0yog4HGvB0gCgOoBZrYFdL16AMsmmD5AcQ3ofj3AwbOAX38BIhMw02ZjtQ+tLnht66mCAGA2eka1G3eabUZwD/PLbeuHenKMBODVV0Dru/TTQLgKAc1BvQ/9yAEkOnlon66oehEBIHp7dbSyPoIc0NEADMDnAa4wAvVK+CADRGx/VpNSi+iF3jMTUH4rJQ0aISPmVk+JoJiZeJw1QnaqL2OmWKSFkxnrZWsbXK4TzO5tmS+8TYaGhv6xvgEEfAgHGc7HRgAAAABJRU5ErkJggg==';
} }
return ''; return UNAVAILABLE_LOGO_URL;
} }
} }

3
libs/ui/src/lib/portfolio-filter-form/portfolio-filter-form.component.html

@ -7,13 +7,12 @@
@for (account of accounts(); track account.id) { @for (account of accounts(); track account.id) {
<mat-option [value]="account.id"> <mat-option [value]="account.id">
<div class="d-flex"> <div class="d-flex">
@if (account.platform?.url) {
<gf-entity-logo <gf-entity-logo
class="mr-1" class="mr-1"
[hasPlaceholder]="true"
[tooltip]="account.platform?.name ?? ''" [tooltip]="account.platform?.name ?? ''"
[url]="account.platform?.url ?? ''" [url]="account.platform?.url ?? ''"
/> />
}
<span>{{ account.name }}</span> <span>{{ account.name }}</span>
</div> </div>
</mat-option> </mat-option>

Loading…
Cancel
Save