You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
14 KiB
411 lines
14 KiB
<form
|
|
class="d-flex flex-column h-100"
|
|
[formGroup]="activityForm"
|
|
(keyup.enter)="activityForm.valid && onSubmit()"
|
|
(ngSubmit)="onSubmit()"
|
|
>
|
|
<h1 *ngIf="data.activity.id" i18n mat-dialog-title>Update activity</h1>
|
|
<h1 *ngIf="!data.activity.id" i18n mat-dialog-title>Add activity</h1>
|
|
<div class="flex-grow-1 py-3" mat-dialog-content>
|
|
<div class="mb-3">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Type</mat-label>
|
|
<mat-select formControlName="type">
|
|
<mat-select-trigger>{{
|
|
typesTranslationMap[activityForm.get('type').value]
|
|
}}</mat-select-trigger>
|
|
<mat-option value="BUY">
|
|
<span
|
|
><b>{{ typesTranslationMap['BUY'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>Stocks, ETFs, bonds, cryptocurrencies, commodities</small
|
|
>
|
|
</mat-option>
|
|
<mat-option value="FEE">
|
|
<span
|
|
><b>{{ typesTranslationMap['FEE'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>One-time fee, annual account fees</small
|
|
>
|
|
</mat-option>
|
|
<mat-option value="DIVIDEND">
|
|
<span
|
|
><b>{{ typesTranslationMap['DIVIDEND'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>Distribution of corporate earnings</small
|
|
>
|
|
</mat-option>
|
|
<mat-option value="INTEREST">
|
|
<span
|
|
><b>{{ typesTranslationMap['INTEREST'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>Revenue for lending out money</small
|
|
>
|
|
</mat-option>
|
|
<mat-option value="LIABILITY">
|
|
<span
|
|
><b>{{ typesTranslationMap['LIABILITY'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>Mortgages, personal loans, credit cards</small
|
|
>
|
|
</mat-option>
|
|
<mat-option value="SELL">
|
|
<span
|
|
><b>{{ typesTranslationMap['SELL'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>Stocks, ETFs, bonds, cryptocurrencies, commodities</small
|
|
>
|
|
</mat-option>
|
|
<mat-option value="ITEM">
|
|
<span
|
|
><b>{{ typesTranslationMap['ITEM'] }}</b></span
|
|
>
|
|
<small class="d-block line-height-1 text-muted text-nowrap" i18n
|
|
>Luxury items, real estate, private companies</small
|
|
>
|
|
</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
<div [ngClass]="{ 'mb-3': data.activity.id }">
|
|
<mat-form-field
|
|
appearance="outline"
|
|
class="w-100"
|
|
[ngClass]="{ 'mb-1 without-hint': !data.activity.id }"
|
|
>
|
|
<mat-label i18n>Account</mat-label>
|
|
<mat-select formControlName="accountId">
|
|
<mat-option
|
|
*ngIf="
|
|
!activityForm.get('accountId').hasValidator(Validators.required)
|
|
"
|
|
[value]="null"
|
|
/>
|
|
<mat-option
|
|
*ngFor="let account of data.accounts"
|
|
[value]="account.id"
|
|
>
|
|
<div class="d-flex">
|
|
<gf-asset-profile-icon
|
|
*ngIf="account.Platform?.url"
|
|
class="mr-1"
|
|
[tooltip]="account.Platform?.name"
|
|
[url]="account.Platform?.url"
|
|
/><span>{{ account.name }}</span>
|
|
</div>
|
|
</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="mb-3" [ngClass]="{ 'd-none': data.activity.id }">
|
|
<mat-checkbox color="primary" formControlName="updateAccountBalance" i18n
|
|
>Update Cash Balance</mat-checkbox
|
|
>
|
|
</div>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{
|
|
'd-none': !activityForm
|
|
.get('searchSymbol')
|
|
.hasValidator(Validators.required)
|
|
}"
|
|
>
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Name, symbol or ISIN</mat-label>
|
|
<gf-symbol-autocomplete
|
|
formControlName="searchSymbol"
|
|
[isLoading]="isLoading"
|
|
/>
|
|
</mat-form-field>
|
|
</div>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{
|
|
'd-none': !activityForm.get('name').hasValidator(Validators.required)
|
|
}"
|
|
>
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Name</mat-label>
|
|
<input formControlName="name" matInput />
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="d-none">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Currency</mat-label>
|
|
<mat-select formControlName="currency">
|
|
<mat-option *ngFor="let currency of currencies" [value]="currency">{{
|
|
currency
|
|
}}</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="d-none">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Data Source</mat-label>
|
|
<input formControlName="dataSource" matInput />
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="mb-3">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Date</mat-label>
|
|
<input formControlName="date" matInput [matDatepicker]="date" />
|
|
<mat-datepicker-toggle class="mr-2" matSuffix [for]="date">
|
|
<ion-icon
|
|
class="text-muted"
|
|
matDatepickerToggleIcon
|
|
name="calendar-clear-outline"
|
|
/>
|
|
</mat-datepicker-toggle>
|
|
<mat-datepicker #date disabled="false" />
|
|
</mat-form-field>
|
|
</div>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{
|
|
'd-none':
|
|
activityForm.get('type')?.value === 'FEE' ||
|
|
activityForm.get('type')?.value === 'INTEREST' ||
|
|
activityForm.get('type')?.value === 'ITEM' ||
|
|
activityForm.get('type')?.value === 'LIABILITY'
|
|
}"
|
|
>
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Quantity</mat-label>
|
|
<input formControlName="quantity" matInput type="number" />
|
|
</mat-form-field>
|
|
</div>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{ 'd-none': activityForm.get('type')?.value === 'FEE' }"
|
|
>
|
|
<div class="align-items-start d-flex">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label
|
|
><ng-container [ngSwitch]="activityForm.get('type')?.value">
|
|
<ng-container *ngSwitchCase="'DIVIDEND'" i18n
|
|
>Dividend</ng-container
|
|
>
|
|
<ng-container *ngSwitchCase="'INTEREST'" i18n>Value</ng-container>
|
|
<ng-container *ngSwitchCase="'ITEM'" i18n>Value</ng-container>
|
|
<ng-container *ngSwitchCase="'LIABILITY'" i18n
|
|
>Value</ng-container
|
|
>
|
|
<ng-container *ngSwitchDefault i18n>Unit Price</ng-container>
|
|
</ng-container>
|
|
</mat-label>
|
|
<input
|
|
formControlName="unitPriceInCustomCurrency"
|
|
matInput
|
|
type="number"
|
|
/>
|
|
<div
|
|
class="ml-2"
|
|
matTextSuffix
|
|
[ngClass]="{ 'd-none': !activityForm.get('currency')?.value }"
|
|
>
|
|
<mat-select formControlName="currencyOfUnitPrice">
|
|
<mat-option
|
|
*ngFor="let currency of currencies"
|
|
[value]="currency"
|
|
>
|
|
{{ currency }}
|
|
</mat-option>
|
|
</mat-select>
|
|
</div>
|
|
<mat-error
|
|
*ngIf="
|
|
activityForm.get('unitPriceInCustomCurrency').hasError('invalid')
|
|
"
|
|
><ng-container i18n
|
|
>Oops! Could not get the historical exchange rate
|
|
from</ng-container
|
|
>
|
|
{{
|
|
activityForm.get('date')?.value | date: defaultDateFormat
|
|
}}</mat-error
|
|
>
|
|
</mat-form-field>
|
|
<button
|
|
*ngIf="
|
|
currentMarketPrice &&
|
|
(data.activity.type === 'BUY' || data.activity.type === 'SELL') &&
|
|
isToday(activityForm.get('date')?.value)
|
|
"
|
|
class="ml-2 mt-1 no-min-width"
|
|
mat-button
|
|
title="Apply current market price"
|
|
type="button"
|
|
(click)="applyCurrentMarketPrice()"
|
|
>
|
|
<ion-icon class="text-muted" name="refresh-outline" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="d-none">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label
|
|
><ng-container [ngSwitch]="activityForm.get('type')?.value">
|
|
<ng-container *ngSwitchCase="'DIVIDEND'" i18n
|
|
>Dividend</ng-container
|
|
>
|
|
<ng-container *ngSwitchCase="'FEE'" i18n>Value</ng-container>
|
|
<ng-container *ngSwitchCase="'INTEREST'" i18n>Value</ng-container>
|
|
<ng-container *ngSwitchCase="'ITEM'" i18n>Value</ng-container>
|
|
<ng-container *ngSwitchCase="'LIABILITY'" i18n>Value</ng-container>
|
|
<ng-container *ngSwitchDefault i18n>Unit Price</ng-container>
|
|
</ng-container>
|
|
</mat-label>
|
|
<input formControlName="unitPrice" matInput type="number" />
|
|
<span class="ml-2" matTextSuffix>{{
|
|
activityForm.get('currency').value
|
|
}}</span>
|
|
</mat-form-field>
|
|
</div>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{
|
|
'd-none':
|
|
activityForm.get('type')?.value === 'INTEREST' ||
|
|
activityForm.get('type')?.value === 'ITEM' ||
|
|
activityForm.get('type')?.value === 'LIABILITY'
|
|
}"
|
|
>
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Fee</mat-label>
|
|
<input formControlName="feeInCustomCurrency" matInput type="number" />
|
|
<div
|
|
class="ml-2"
|
|
matTextSuffix
|
|
[ngClass]="{ 'd-none': !activityForm.get('currency')?.value }"
|
|
>
|
|
{{ activityForm.get('currencyOfUnitPrice').value }}
|
|
</div>
|
|
<mat-error
|
|
*ngIf="activityForm.get('feeInCustomCurrency').hasError('invalid')"
|
|
><ng-container i18n
|
|
>Oops! Could not get the historical exchange rate from</ng-container
|
|
>
|
|
{{
|
|
activityForm.get('date')?.value | date: defaultDateFormat
|
|
}}</mat-error
|
|
>
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="d-none">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Fee</mat-label>
|
|
<input formControlName="fee" matInput type="number" />
|
|
<span class="ml-2" matTextSuffix>{{
|
|
activityForm.get('currency').value
|
|
}}</span>
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="mb-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>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{ 'd-none': activityForm.get('type')?.value !== 'ITEM' }"
|
|
>
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Asset Class</mat-label>
|
|
<mat-select formControlName="assetClass">
|
|
<mat-option [value]="null" />
|
|
<mat-option
|
|
*ngFor="let assetClass of assetClasses"
|
|
[value]="assetClass.id"
|
|
>{{ assetClass.label }}</mat-option
|
|
>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
<div
|
|
class="mb-3"
|
|
[ngClass]="{ 'd-none': activityForm.get('type')?.value !== 'ITEM' }"
|
|
>
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Asset Sub Class</mat-label>
|
|
<mat-select formControlName="assetSubClass">
|
|
<mat-option [value]="null" />
|
|
<mat-option
|
|
*ngFor="let assetSubClass of assetSubClasses"
|
|
[value]="assetSubClass.id"
|
|
>{{ assetSubClass.label }}</mat-option
|
|
>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
</div>
|
|
<div class="mb-3" [ngClass]="{ 'd-none': tags?.length < 1 }">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label i18n>Tags</mat-label>
|
|
<mat-chip-grid #tagsChipList>
|
|
<mat-chip-row
|
|
*ngFor="let tag of activityForm.get('tags')?.value"
|
|
matChipRemove
|
|
[removable]="true"
|
|
(removed)="onRemoveTag(tag)"
|
|
>
|
|
{{ tag.name }}
|
|
<ion-icon class="ml-2" matPrefix name="close-outline" />
|
|
</mat-chip-row>
|
|
<input
|
|
#tagInput
|
|
name="close-outline"
|
|
[matAutocomplete]="autocompleteTags"
|
|
[matChipInputFor]="tagsChipList"
|
|
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
|
/>
|
|
</mat-chip-grid>
|
|
<mat-autocomplete
|
|
#autocompleteTags="matAutocomplete"
|
|
(optionSelected)="onAddTag($event)"
|
|
>
|
|
<mat-option
|
|
*ngFor="let tag of filteredTagsObservable | async"
|
|
[value]="tag.id"
|
|
>
|
|
{{ tag.name }}
|
|
</mat-option>
|
|
</mat-autocomplete>
|
|
</mat-form-field>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex" mat-dialog-actions>
|
|
<gf-value
|
|
class="flex-grow-1"
|
|
[isCurrency]="true"
|
|
[locale]="data.user?.settings?.locale"
|
|
[unit]="
|
|
activityForm.get('currency')?.value ?? data.user?.settings?.baseCurrency
|
|
"
|
|
[value]="total"
|
|
/>
|
|
<div>
|
|
<button i18n mat-button type="button" (click)="onCancel()">Cancel</button>
|
|
<button
|
|
color="primary"
|
|
mat-flat-button
|
|
type="submit"
|
|
[disabled]="!activityForm.valid"
|
|
>
|
|
<ng-container i18n>Save</ng-container>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|