Browse Source

Feature/introduce tabs in asset profile dialog (#5693)

* Introduce tabs in asset profile dialog

* Update changelog
pull/5704/head
Bence Hornyák 1 week ago
committed by GitHub
parent
commit
0e43bb048a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 11
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  3. 884
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

1
CHANGELOG.md

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added support to edit a granted access (experimental)
- Introduced tabs to the asset profile details dialog in the admin control panel
- Added support for a date range query parameter in the data gathering endpoint
- Added a _Storybook_ story for the activities table component

11
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -65,6 +65,7 @@ import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTabsModule } from '@angular/material/tabs';
import { IonIcon } from '@ionic/angular/standalone';
import {
AssetClass,
@ -77,7 +78,12 @@ import { isUUID } from 'class-validator';
import { format } from 'date-fns';
import { StatusCodes } from 'http-status-codes';
import { addIcons } from 'ionicons';
import { createOutline, ellipsisVertical } from 'ionicons/icons';
import {
createOutline,
ellipsisVertical,
readerOutline,
serverOutline
} from 'ionicons/icons';
import ms from 'ms';
import { EMPTY, Subject } from 'rxjs';
import { catchError, takeUntil } from 'rxjs/operators';
@ -106,6 +112,7 @@ import { AssetProfileDialogParams } from './interfaces/interfaces';
MatMenuModule,
MatSelectModule,
MatSnackBarModule,
MatTabsModule,
ReactiveFormsModule,
TextFieldModule
],
@ -223,7 +230,7 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit {
private snackBar: MatSnackBar,
private userService: UserService
) {
addIcons({ createOutline, ellipsisVertical });
addIcons({ createOutline, ellipsisVertical, readerOutline, serverOutline });
}
public get canEditAssetProfileIdentifier() {

884
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -79,463 +79,485 @@
[showXAxis]="true"
[showYAxis]="true"
/>
<div class="mb-3">
<mat-accordion class="my-3">
<mat-expansion-panel class="shadow-none">
<mat-expansion-panel-header class="p-0 pr-3">
<mat-panel-title class="font-weight-bold" i18n
>Historical Market Data</mat-panel-title
>
</mat-expansion-panel-header>
<gf-historical-market-data-editor
class="mb-3"
[currency]="assetProfile?.currency"
[dataSource]="data.dataSource"
[dateOfFirstActivity]="assetProfile?.dateOfFirstActivity"
[locale]="data.locale"
[marketData]="marketDataItems"
[symbol]="data.symbol"
[user]="user"
(marketDataChanged)="onMarketDataChanged($event)"
/>
</mat-expansion-panel>
</mat-accordion>
</div>
<div class="row">
@if (isEditAssetProfileIdentifierMode) {
<div class="col-12 mb-4">
<form
class="align-items-center d-flex"
[formGroup]="assetProfileIdentifierForm"
(keyup.enter)="
assetProfileIdentifierForm.valid &&
onSubmitAssetProfileIdentifierForm()
"
(ngSubmit)="onSubmitAssetProfileIdentifierForm()"
>
<mat-form-field appearance="outline" class="gf-spacer without-hint">
<mat-label i18n>Name, symbol or ISIN</mat-label>
<gf-symbol-autocomplete
formControlName="assetProfileIdentifier"
[includeIndices]="true"
/>
</mat-form-field>
<button
class="ml-2 no-min-width px-2"
color="primary"
mat-flat-button
type="submit"
[disabled]="
assetProfileIdentifierForm.hasError(
'invalidData',
'assetProfileIdentifier'
) ||
assetProfileIdentifierForm.hasError(
'equalsPreviousProfileIdentifier'
)
"
>
<ng-container i18n>Apply</ng-container>
</button>
<button
class="ml-2 no-min-width px-2"
mat-button
type="button"
(click)="onCancelEditAssetProfileIdentifierMode()"
>
<ng-container i18n>Cancel</ng-container>
</button>
</form>
</div>
} @else {
<div class="col-6 mb-3">
<gf-value i18n size="medium" [value]="assetProfile?.symbol"
>Symbol</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[value]="
assetProfile?.dataProviderInfo?.name ?? assetProfile?.dataSource
"
>Data Source</gf-value
>
<div
class="edit-asset-profile-identifier-container position-absolute"
>
<button
class="h-100 no-min-width px-2"
mat-button
type="button"
[disabled]="!canSaveAssetProfileIdentifier"
[ngClass]="{
'd-none': !canEditAssetProfileIdentifier
}"
(click)="onSetEditAssetProfileIdentifierMode()"
>
<ion-icon name="create-outline" />
</button>
</div>
</div>
}
<div class="col-6 mb-3">
<gf-value i18n size="medium" [value]="assetProfile?.currency"
>Currency</gf-value
>
</div>
<div class="col-6 mb-3"></div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[isDate]="assetProfile?.dateOfFirstActivity ? true : false"
[locale]="data.locale"
[value]="assetProfile?.dateOfFirstActivity ?? '-'"
>First Activity</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[locale]="data.locale"
[value]="assetProfile?.activitiesCount"
>Activities</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[hidden]="!assetClassLabel"
[value]="assetClassLabel"
>Asset Class</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[hidden]="!assetSubClassLabel"
[value]="assetSubClassLabel"
>Asset Sub Class</gf-value
>
</div>
@if (
assetProfile?.countries?.length > 0 || assetProfile?.sectors?.length > 0
) {
@if (
assetProfile?.countries?.length === 1 &&
assetProfile?.sectors?.length === 1
) {
@if (assetProfile?.sectors?.length === 1) {
<mat-tab-group
animationDuration="0ms"
[dynamicHeight]="true"
[mat-stretch-tabs]="false"
>
<mat-tab>
<ng-template mat-tab-label>
<ion-icon name="reader-outline" />
<div class="d-none d-sm-block ml-2" i18n>Overview</div>
</ng-template>
<div class="container mt-3 p-0">
<div class="row w-100">
@if (isEditAssetProfileIdentifierMode) {
<div class="col-12 mb-4">
<form
class="align-items-center d-flex"
[formGroup]="assetProfileIdentifierForm"
(keyup.enter)="
assetProfileIdentifierForm.valid &&
onSubmitAssetProfileIdentifierForm()
"
(ngSubmit)="onSubmitAssetProfileIdentifierForm()"
>
<mat-form-field
appearance="outline"
class="gf-spacer without-hint"
>
<mat-label i18n>Name, symbol or ISIN</mat-label>
<gf-symbol-autocomplete
formControlName="assetProfileIdentifier"
[includeIndices]="true"
/>
</mat-form-field>
<button
class="ml-2 no-min-width px-2"
color="primary"
mat-flat-button
type="submit"
[disabled]="
assetProfileIdentifierForm.hasError(
'invalidData',
'assetProfileIdentifier'
) ||
assetProfileIdentifierForm.hasError(
'equalsPreviousProfileIdentifier'
)
"
>
<ng-container i18n>Apply</ng-container>
</button>
<button
class="ml-2 no-min-width px-2"
mat-button
type="button"
(click)="onCancelEditAssetProfileIdentifierMode()"
>
<ng-container i18n>Cancel</ng-container>
</button>
</form>
</div>
} @else {
<div class="col-6 mb-3">
<gf-value i18n size="medium" [value]="assetProfile?.symbol"
>Symbol</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[value]="
assetProfile?.dataProviderInfo?.name ??
assetProfile?.dataSource
"
>Data Source</gf-value
>
<div
class="edit-asset-profile-identifier-container position-absolute"
>
<button
class="h-100 no-min-width px-2"
mat-button
type="button"
[disabled]="!canSaveAssetProfileIdentifier"
[ngClass]="{
'd-none': !canEditAssetProfileIdentifier
}"
(click)="onSetEditAssetProfileIdentifierMode()"
>
<ion-icon name="create-outline" />
</button>
</div>
</div>
}
<div class="col-6 mb-3">
<gf-value i18n size="medium" [value]="assetProfile?.currency"
>Currency</gf-value
>
</div>
<div class="col-6 mb-3"></div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[isDate]="assetProfile?.dateOfFirstActivity ? true : false"
[locale]="data.locale"
[value]="assetProfile?.sectors[0].name"
>Sector</gf-value
[value]="assetProfile?.dateOfFirstActivity ?? '-'"
>First Activity</gf-value
>
</div>
}
@if (assetProfile?.countries?.length === 1) {
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[locale]="data.locale"
[value]="assetProfile?.countries[0].name"
>Country</gf-value
[value]="assetProfile?.activitiesCount"
>Activities</gf-value
>
</div>
}
} @else {
<div class="col-md-6 mb-3">
<div class="h5" i18n>Sectors</div>
<gf-portfolio-proportion-chart
[colorScheme]="data.colorScheme"
[data]="sectors"
[isInPercent]="true"
[keys]="['name']"
[maxItems]="10"
/>
</div>
<div class="col-md-6 mb-3">
<div class="h5" i18n>Countries</div>
<gf-portfolio-proportion-chart
[colorScheme]="data.colorScheme"
[data]="countries"
[isInPercent]="true"
[keys]="['name']"
[maxItems]="10"
/>
</div>
}
}
</div>
<form
#assetProfileFormElement
[formGroup]="assetProfileForm"
(keyup.enter)="assetProfileForm.valid && onSubmitAssetProfileForm()"
(ngSubmit)="onSubmitAssetProfileForm()"
>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Name</mat-label>
<input formControlName="name" matInput type="text" />
</mat-form-field>
</div>
@if (assetProfile?.dataSource === 'MANUAL') {
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Currency</mat-label>
<gf-currency-selector
formControlName="currency"
[currencies]="currencies"
/>
</mat-form-field>
</div>
}
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Asset Class</mat-label>
<mat-select formControlName="assetClass">
<mat-option [value]="null" />
@for (
assetClassOption of assetClassOptions;
track assetClassOption.id
) {
<mat-option [value]="assetClassOption.id">{{
assetClassOption.label
}}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Asset Sub Class</mat-label>
<mat-select formControlName="assetSubClass">
<mat-option [value]="null" />
@for (
assetSubClassOption of assetSubClassOptions;
track assetSubClassOption.id
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[hidden]="!assetClassLabel"
[value]="assetClassLabel"
>Asset Class</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[hidden]="!assetSubClassLabel"
[value]="assetSubClassLabel"
>Asset Sub Class</gf-value
>
</div>
@if (
assetProfile?.countries?.length > 0 ||
assetProfile?.sectors?.length > 0
) {
<mat-option [value]="assetSubClassOption.id">{{
assetSubClassOption.label
}}</mat-option>
@if (
assetProfile?.countries?.length === 1 &&
assetProfile?.sectors?.length === 1
) {
@if (assetProfile?.sectors?.length === 1) {
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[locale]="data.locale"
[value]="assetProfile?.sectors[0].name"
>Sector</gf-value
>
</div>
}
@if (assetProfile?.countries?.length === 1) {
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[locale]="data.locale"
[value]="assetProfile?.countries[0].name"
>Country</gf-value
>
</div>
}
} @else {
<div class="col-md-6 mb-3">
<div class="h5" i18n>Sectors</div>
<gf-portfolio-proportion-chart
[colorScheme]="data.colorScheme"
[data]="sectors"
[isInPercent]="true"
[keys]="['name']"
[maxItems]="10"
/>
</div>
<div class="col-md-6 mb-3">
<div class="h5" i18n>Countries</div>
<gf-portfolio-proportion-chart
[colorScheme]="data.colorScheme"
[data]="countries"
[isInPercent]="true"
[keys]="['name']"
[maxItems]="10"
/>
</div>
}
}
</mat-select>
</mat-form-field>
</div>
<div class="d-flex my-3">
<div class="w-50">
<mat-checkbox
color="primary"
i18n
[checked]="isBenchmark"
[disabled]="isEditAssetProfileIdentifierMode"
(change)="
isBenchmark
? onUnsetBenchmark({
dataSource: data.dataSource,
symbol: data.symbol
})
: onSetBenchmark({
dataSource: data.dataSource,
symbol: data.symbol
})
"
>Benchmark</mat-checkbox
</div>
<form
#assetProfileFormElement
[formGroup]="assetProfileForm"
(keyup.enter)="assetProfileForm.valid && onSubmitAssetProfileForm()"
(ngSubmit)="onSubmitAssetProfileForm()"
>
</div>
</div>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Symbol Mapping</mat-label>
<textarea
cdkTextareaAutosize
formControlName="symbolMapping"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
@if (assetProfile?.dataSource === 'MANUAL') {
<div class="mb-3">
<mat-accordion class="my-3">
<mat-expansion-panel
class="shadow-none"
[expanded]="
assetProfileForm.controls.scraperConfiguration.controls.selector
.value !== '' &&
assetProfileForm.controls.scraperConfiguration.controls.url
.value !== ''
"
(closed)="scraperConfiguationIsExpanded.set(false)"
(opened)="scraperConfiguationIsExpanded.set(true)"
>
<mat-expansion-panel-header class="p-0 pr-3">
<mat-panel-title class="font-weight-bold" i18n
>Scraper Configuration</mat-panel-title
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Name</mat-label>
<input formControlName="name" matInput type="text" />
</mat-form-field>
</div>
@if (assetProfile?.dataSource === 'MANUAL') {
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Currency</mat-label>
<gf-currency-selector
formControlName="currency"
[currencies]="currencies"
/>
</mat-form-field>
</div>
}
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Asset Class</mat-label>
<mat-select formControlName="assetClass">
<mat-option [value]="null" />
@for (
assetClassOption of assetClassOptions;
track assetClassOption.id
) {
<mat-option [value]="assetClassOption.id">{{
assetClassOption.label
}}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Asset Sub Class</mat-label>
<mat-select formControlName="assetSubClass">
<mat-option [value]="null" />
@for (
assetSubClassOption of assetSubClassOptions;
track assetSubClassOption.id
) {
<mat-option [value]="assetSubClassOption.id">{{
assetSubClassOption.label
}}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<div class="d-flex my-3">
<div class="w-50">
<mat-checkbox
color="primary"
i18n
[checked]="isBenchmark"
[disabled]="isEditAssetProfileIdentifierMode"
(change)="
isBenchmark
? onUnsetBenchmark({
dataSource: data.dataSource,
symbol: data.symbol
})
: onSetBenchmark({
dataSource: data.dataSource,
symbol: data.symbol
})
"
>Benchmark</mat-checkbox
>
</mat-expansion-panel-header>
<div formGroupName="scraperConfiguration">
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>Default Market Price</mat-label>
<input
formControlName="defaultMarketPrice"
matInput
type="number"
/>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>HTTP Request Headers</mat-label>
<textarea
cdkTextareaAutosize
formControlName="headers"
matInput
type="text"
[matAutocomplete]="auto"
></textarea>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>Locale</mat-label>
<input formControlName="locale" matInput type="text" />
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>Mode</mat-label>
<mat-select formControlName="mode">
@for (modeValue of modeValues; track modeValue) {
<mat-option [value]="modeValue.value">{{
modeValue.viewValue
}}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label>
<ng-container i18n>Selector</ng-container>*
</mat-label>
<textarea
cdkTextareaAutosize
formControlName="selector"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label>
<ng-container i18n>Url</ng-container>*
</mat-label>
<input formControlName="url" matInput type="text" />
</mat-form-field>
</div>
<div class="my-3 text-right">
<button
color="accent"
mat-flat-button
type="button"
[disabled]="
</div>
</div>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Symbol Mapping</mat-label>
<textarea
cdkTextareaAutosize
formControlName="symbolMapping"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
@if (assetProfile?.dataSource === 'MANUAL') {
<div class="mb-3">
<mat-accordion class="my-3">
<mat-expansion-panel
class="shadow-none"
[expanded]="
assetProfileForm.controls.scraperConfiguration.controls
.selector.value === '' ||
.selector.value !== '' &&
assetProfileForm.controls.scraperConfiguration.controls
.url.value === ''
.url.value !== ''
"
(click)="onTestMarketData()"
(closed)="scraperConfiguationIsExpanded.set(false)"
(opened)="scraperConfiguationIsExpanded.set(true)"
>
<ng-container i18n>Test</ng-container>
</button>
</div>
<mat-expansion-panel-header class="p-0 pr-3">
<mat-panel-title class="font-weight-bold" i18n
>Scraper Configuration</mat-panel-title
>
</mat-expansion-panel-header>
<div formGroupName="scraperConfiguration">
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>Default Market Price</mat-label>
<input
formControlName="defaultMarketPrice"
matInput
type="number"
/>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>HTTP Request Headers</mat-label>
<textarea
cdkTextareaAutosize
formControlName="headers"
matInput
type="text"
[matAutocomplete]="auto"
></textarea>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>Locale</mat-label>
<input
formControlName="locale"
matInput
type="text"
/>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label i18n>Mode</mat-label>
<mat-select formControlName="mode">
@for (modeValue of modeValues; track modeValue) {
<mat-option [value]="modeValue.value">{{
modeValue.viewValue
}}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label>
<ng-container i18n>Selector</ng-container>*
</mat-label>
<textarea
cdkTextareaAutosize
formControlName="selector"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field
appearance="outline"
class="w-100 without-hint"
>
<mat-label>
<ng-container i18n>Url</ng-container>*
</mat-label>
<input formControlName="url" matInput type="text" />
</mat-form-field>
</div>
<div class="my-3 text-right">
<button
color="accent"
mat-flat-button
type="button"
[disabled]="
assetProfileForm.controls.scraperConfiguration
.controls.selector.value === '' ||
assetProfileForm.controls.scraperConfiguration
.controls.url.value === ''
"
(click)="onTestMarketData()"
>
<ng-container i18n>Test</ng-container>
</button>
</div>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
}
@if (assetProfile?.dataSource === 'MANUAL') {
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Sectors</mat-label>
<textarea
cdkTextareaAutosize
formControlName="sectors"
matInput
type="text"
></textarea>
</mat-form-field>
}
@if (assetProfile?.dataSource === 'MANUAL') {
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Sectors</mat-label>
<textarea
cdkTextareaAutosize
formControlName="sectors"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Countries</mat-label>
<textarea
cdkTextareaAutosize
formControlName="countries"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
}
<div>
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Url</mat-label>
<input formControlName="url" matInput type="text" />
@if (assetProfileForm.get('url').value) {
<gf-entity-logo
class="mr-3"
matSuffix
[url]="assetProfileForm.get('url').value"
/>
}
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Note</mat-label>
<textarea
cdkAutosizeMinRows="2"
cdkTextareaAutosize
formControlName="comment"
matInput
(keyup.enter)="$event.stopPropagation()"
></textarea>
</mat-form-field>
</div>
</form>
</div>
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Countries</mat-label>
<textarea
cdkTextareaAutosize
formControlName="countries"
matInput
type="text"
></textarea>
</mat-form-field>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<ion-icon name="server-outline" />
<div class="d-none d-sm-block ml-2" i18n>Historical Market Data</div>
</ng-template>
<div class="container mt-3 p-0">
<div class="no-gutters row w-100">
<div class="col-12">
<gf-historical-market-data-editor
[currency]="assetProfile?.currency"
[dataSource]="data.dataSource"
[dateOfFirstActivity]="assetProfile?.dateOfFirstActivity"
[locale]="data.locale"
[marketData]="marketDataItems"
[symbol]="data.symbol"
[user]="user"
(marketDataChanged)="onMarketDataChanged($event)"
/>
</div>
</div>
</div>
}
<div>
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Url</mat-label>
<input formControlName="url" matInput type="text" />
@if (assetProfileForm.get('url').value) {
<gf-entity-logo
class="mr-3"
matSuffix
[url]="assetProfileForm.get('url').value"
/>
}
</mat-form-field>
</div>
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Note</mat-label>
<textarea
cdkAutosizeMinRows="2"
cdkTextareaAutosize
formControlName="comment"
matInput
(keyup.enter)="$event.stopPropagation()"
></textarea>
</mat-form-field>
</div>
</form>
</mat-tab>
</mat-tab-group>
</div>
<div class="d-flex" mat-dialog-actions>

Loading…
Cancel
Save