Feature/combine name and symbol column in holdings table (#1514)

* Combine name and symbol column

* Update changelog
pull/1516/head^2
Thomas Kaul 1 year ago committed by GitHub
parent 60f52bb209
commit 2b8ab26e7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support to disable user sign up in the admin control panel
- Extended the glossary of the resources page by _Deflation_, _Inflation_ and _Stagflation_
### Changed
- Combined the name and symbol column in the holdings table (former positions table)
## 1.218.0 - 2022-12-12
### Added

@ -3,12 +3,6 @@
:host {
display: block;
::ng-deep {
.mat-form-field-infix {
border-top: 0 solid transparent !important;
}
}
.mat-table {
td {
&.mat-footer-cell {

@ -1,173 +0,0 @@
<table
class="gf-table w-100"
mat-table
matSort
matSortActive="allocationCurrent"
matSortDirection="desc"
[dataSource]="dataSource"
>
<ng-container matColumnDef="icon">
<th *matHeaderCellDef class="px-1" mat-header-cell></th>
<td *matCellDef="let element" class="px-1 text-center" mat-cell>
<gf-symbol-icon
[dataSource]="element.dataSource"
[symbol]="element.symbol"
[tooltip]="element.name"
></gf-symbol-icon>
</td>
</ng-container>
<ng-container matColumnDef="symbol">
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Symbol</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<span [title]="element.name">{{ element.symbol | gfSymbol }}</span>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>Name</ng-container>
</th>
<td *matCellDef="let element" class="d-none d-lg-table-cell px-1" mat-cell>
<ng-container *ngIf="element.name !== element.symbol">{{
element.name
}}</ng-container>
</td>
</ng-container>
<ng-container matColumnDef="dateOfFirstActivity">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>First Activity</ng-container>
</th>
<td *matCellDef="let element" class="d-none d-lg-table-cell px-1" mat-cell>
<div class="d-flex justify-content-end">
<gf-value
[isDate]="element.dateOfFirstActivity ? true : false"
[locale]="locale"
[value]="element.dateOfFirstActivity ?? ''"
></gf-value>
</div>
</td>
</ng-container>
<ng-container matColumnDef="value">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>Value</ng-container>
</th>
<td *matCellDef="let element" class="d-none d-lg-table-cell px-1" mat-cell>
<div class="d-flex justify-content-end">
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.value"
></gf-value>
</div>
</td>
</ng-container>
<ng-container matColumnDef="allocationCurrent">
<th
*matHeaderCellDef
class="justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>Allocation</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex justify-content-end">
<gf-value
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.allocationCurrent"
></gf-value>
</div>
</td>
</ng-container>
<ng-container matColumnDef="performance">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell px-1 text-right"
mat-header-cell
mat-sort-header="netPerformancePercent"
>
<ng-container i18n>Performance</ng-container>
</th>
<td *matCellDef="let element" class="d-none d-lg-table-cell px-1" mat-cell>
<div class="d-flex justify-content-end">
<gf-value
[colorizeSign]="true"
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.netPerformancePercent"
></gf-value>
</div>
</td>
</ng-container>
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
<tr
*matRowDef="let row; columns: displayedColumns"
mat-row
[ngClass]="{
'cursor-pointer':
hasPermissionToShowValues &&
!ignoreAssetSubClasses.includes(row.assetSubClass)
}"
(click)="
hasPermissionToShowValues &&
!ignoreAssetSubClasses.includes(row.assetSubClass) &&
onOpenPositionDialog({ dataSource: row.dataSource, symbol: row.symbol })
"
></tr>
</table>
<ngx-skeleton-loader
*ngIf="isLoading"
animation="pulse"
class="px-4 py-3"
[theme]="{
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
<div
*ngIf="dataSource.data.length > pageSize && !isLoading"
class="my-3 text-center"
>
<button mat-stroked-button (click)="onShowAllPositions()">
<ng-container i18n>Show all</ng-container>
</button>
</div>
<div
*ngIf="
dataSource.data.length === 0 && hasPermissionToCreateActivity && !isLoading
"
class="p-3 text-center"
>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator>
</div>
<mat-paginator class="d-none" [pageSize]="pageSize"></mat-paginator>

@ -1,33 +0,0 @@
@import '~apps/client/src/styles/ghostfolio-style';
:host {
display: block;
::ng-deep {
.mat-form-field-infix {
border-top: 0 solid transparent !important;
}
}
.mat-table {
th {
::ng-deep {
.mat-sort-header-container {
justify-content: inherit;
}
}
}
.mat-row {
&.cursor-pointer {
cursor: pointer;
}
}
}
}
:host-context(.is-dark-theme) {
.mat-form-field {
color: rgba(var(--light-primary-text));
}
}

@ -12,13 +12,13 @@
</div>
<div class="row">
<div class="col-lg">
<gf-positions-table
<gf-holdings-table
[baseCurrency]="user?.settings?.baseCurrency"
[deviceType]="deviceType"
[hasPermissionToCreateActivity]="hasPermissionToCreateOrder"
[locale]="user?.settings?.locale"
[positions]="positionsArray"
></gf-positions-table>
></gf-holdings-table>
<div
*ngIf="hasPermissionToCreateOrder && positionsArray?.length > 0"
class="text-center"

@ -1,7 +1,7 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-table/positions-table.module';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
import { HoldingsPageRoutingModule } from './holdings-page-routing.module';
@ -12,7 +12,7 @@ import { HoldingsPageComponent } from './holdings-page.component';
imports: [
CommonModule,
GfActivitiesFilterModule,
GfPositionsTableModule,
GfHoldingsTableModule,
HoldingsPageRoutingModule,
MatButtonModule
],

@ -115,12 +115,12 @@
</div>
<div class="row">
<div class="col-lg">
<gf-positions-table
<gf-holdings-table
pageSize="7"
[deviceType]="deviceType"
[hasPermissionToShowValues]="false"
[positions]="positionsArray"
></gf-positions-table>
></gf-holdings-table>
</div>
</div>
<div class="row my-5">

@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-table/positions-table.module';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
import { GfValueModule } from '@ghostfolio/ui/value';
@ -14,8 +14,8 @@ import { PublicPageComponent } from './public-page.component';
declarations: [PublicPageComponent],
imports: [
CommonModule,
GfHoldingsTableModule,
GfPortfolioProportionChartModule,
GfPositionsTableModule,
GfValueModule,
GfWorldMapChartModule,
MatButtonModule,

@ -0,0 +1,184 @@
<div class="holdings">
<table
class="gf-table w-100"
mat-table
matSort
matSortActive="allocationCurrent"
matSortDirection="desc"
[dataSource]="dataSource"
>
<ng-container matColumnDef="icon">
<th *matHeaderCellDef class="px-1" mat-header-cell></th>
<td *matCellDef="let element" class="px-1 text-center" mat-cell>
<gf-symbol-icon
[dataSource]="element.dataSource"
[symbol]="element.symbol"
[tooltip]="element.name"
></gf-symbol-icon>
</td>
</ng-container>
<ng-container matColumnDef="nameWithSymbol">
<th
*matHeaderCellDef
class="px-1"
mat-header-cell
mat-sort-header="symbol"
>
<ng-container i18n>Name</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<div *ngIf="element.name !== element.symbol" class="text-truncate">
{{ element.name }}
</div>
<div>
<small class="text-muted">{{ element.symbol }}</small>
</div>
</td>
</ng-container>
<ng-container matColumnDef="dateOfFirstActivity">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>First Activity</ng-container>
</th>
<td
*matCellDef="let element"
class="d-none d-lg-table-cell px-1"
mat-cell
>
<div class="d-flex justify-content-end">
<gf-value
[isDate]="element.dateOfFirstActivity ? true : false"
[locale]="locale"
[value]="element.dateOfFirstActivity ?? ''"
></gf-value>
</div>
</td>
</ng-container>
<ng-container matColumnDef="value">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>Value</ng-container>
</th>
<td
*matCellDef="let element"
class="d-none d-lg-table-cell px-1"
mat-cell
>
<div class="d-flex justify-content-end">
<gf-value
[isCurrency]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.value"
></gf-value>
</div>
</td>
</ng-container>
<ng-container matColumnDef="allocationCurrent">
<th
*matHeaderCellDef
class="justify-content-end px-1"
mat-header-cell
mat-sort-header
>
<ng-container i18n>Allocation</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex justify-content-end">
<gf-value
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.allocationCurrent"
></gf-value>
</div>
</td>
</ng-container>
<ng-container matColumnDef="performance">
<th
*matHeaderCellDef
class="d-none d-lg-table-cell px-1 text-right"
mat-header-cell
mat-sort-header="netPerformancePercent"
>
<ng-container i18n>Performance</ng-container>
</th>
<td
*matCellDef="let element"
class="d-none d-lg-table-cell px-1"
mat-cell
>
<div class="d-flex justify-content-end">
<gf-value
[colorizeSign]="true"
[isPercent]="true"
[locale]="locale"
[value]="isLoading ? undefined : element.netPerformancePercent"
></gf-value>
</div>
</td>
</ng-container>
<tr *matHeaderRowDef="displayedColumns" mat-header-row></tr>
<tr
*matRowDef="let row; columns: displayedColumns"
mat-row
[ngClass]="{
'cursor-pointer':
hasPermissionToShowValues &&
!ignoreAssetSubClasses.includes(row.assetSubClass)
}"
(click)="
hasPermissionToShowValues &&
!ignoreAssetSubClasses.includes(row.assetSubClass) &&
onOpenPositionDialog({
dataSource: row.dataSource,
symbol: row.symbol
})
"
></tr>
</table>
</div>
<mat-paginator class="d-none" [pageSize]="pageSize"></mat-paginator>
<ngx-skeleton-loader
*ngIf="isLoading"
animation="pulse"
class="px-4 py-3"
[theme]="{
height: '1.5rem',
width: '100%'
}"
></ngx-skeleton-loader>
<div
*ngIf="dataSource.data.length > pageSize && !isLoading"
class="my-3 text-center"
>
<button mat-stroked-button (click)="onShowAllPositions()">
<ng-container i18n>Show all</ng-container>
</button>
</div>
<div
*ngIf="
dataSource.data.length === 0 && hasPermissionToCreateActivity && !isLoading
"
class="p-3 text-center"
>
<gf-no-transactions-info-indicator
[hasBorder]="false"
></gf-no-transactions-info-indicator>
</div>

@ -0,0 +1,25 @@
@import '~apps/client/src/styles/ghostfolio-style';
:host {
display: block;
.holdings {
overflow-x: auto;
.mat-table {
th {
::ng-deep {
.mat-sort-header-container {
justify-content: inherit;
}
}
}
.mat-row {
&.cursor-pointer {
cursor: pointer;
}
}
}
}
}

@ -19,12 +19,12 @@ import { AssetClass, Order as OrderModel } from '@prisma/client';
import { Subject, Subscription } from 'rxjs';
@Component({
selector: 'gf-positions-table',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './positions-table.component.html',
styleUrls: ['./positions-table.component.scss']
selector: 'gf-holdings-table',
styleUrls: ['./holdings-table.component.scss'],
templateUrl: './holdings-table.component.html'
})
export class PositionsTableComponent implements OnChanges, OnDestroy, OnInit {
export class HoldingsTableComponent implements OnChanges, OnDestroy, OnInit {
@Input() baseCurrency: string;
@Input() deviceType: string;
@Input() hasPermissionToCreateActivity: boolean;
@ -56,7 +56,7 @@ export class PositionsTableComponent implements OnChanges, OnDestroy, OnInit {
public ngOnInit() {}
public ngOnChanges() {
this.displayedColumns = ['icon', 'symbol', 'name', 'dateOfFirstActivity'];
this.displayedColumns = ['icon', 'nameWithSymbol', 'dateOfFirstActivity'];
if (this.hasPermissionToShowValues) {
this.displayedColumns.push('value');

@ -8,17 +8,17 @@ import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { RouterModule } from '@angular/router';
import { GfPositionDetailDialogModule } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.module';
import { GfSymbolIconModule } from '@ghostfolio/client/components/symbol-icon/symbol-icon.module';
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info';
import { GfValueModule } from '@ghostfolio/ui/value';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfSymbolIconModule } from '../symbol-icon/symbol-icon.module';
import { PositionsTableComponent } from './positions-table.component';
import { HoldingsTableComponent } from './holdings-table.component';
@NgModule({
declarations: [PositionsTableComponent],
exports: [PositionsTableComponent],
declarations: [HoldingsTableComponent],
exports: [HoldingsTableComponent],
imports: [
CommonModule,
GfNoTransactionsInfoModule,
@ -37,4 +37,4 @@ import { PositionsTableComponent } from './positions-table.component';
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class GfPositionsTableModule {}
export class GfHoldingsTableModule {}
Loading…
Cancel
Save