Browse Source

Merge 2181e742c6 into 584d74c3c9

pull/6284/merge
Omkar Gujja 9 hours ago
committed by GitHub
parent
commit
a33d807d99
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      apps/api/src/app/admin/admin.service.ts
  2. 10
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  3. 164
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  4. 13
      libs/common/src/lib/utils/form.util.ts
  5. 4
      libs/common/src/lib/utils/index.ts

8
apps/api/src/app/admin/admin.service.ts

@ -626,22 +626,22 @@ export class AdminService {
assetClass: assetClass as AssetClass,
assetSubClass: assetSubClass as AssetSubClass,
name: name as string,
url: url as string
countries: countries as Prisma.JsonArray,
url: url as string,
sectors: sectors as Prisma.JsonArray
};
const updatedSymbolProfile: Prisma.SymbolProfileUpdateInput = {
comment,
countries,
currency,
dataSource,
holdings,
isActive,
scraperConfiguration,
sectors,
symbol,
symbolMapping,
...(dataSource === 'MANUAL'
? { assetClass, assetSubClass, name, url }
? { assetClass, assetSubClass, name, url, countries, sectors }
: {
SymbolProfileOverrides: {
upsert: {

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

@ -19,7 +19,7 @@ import {
User
} from '@ghostfolio/common/interfaces';
import { DateRange } from '@ghostfolio/common/types';
import { validateObjectForForm } from '@ghostfolio/common/utils';
import { jsonValidator, validateObjectForForm } from '@ghostfolio/common/utils';
import { GfCurrencySelectorComponent } from '@ghostfolio/ui/currency-selector';
import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo';
import { GfHistoricalMarketDataEditorComponent } from '@ghostfolio/ui/historical-market-data-editor';
@ -149,7 +149,7 @@ export class GfAssetProfileDialogComponent implements OnInit {
assetClass: new FormControl<AssetClass>(undefined),
assetSubClass: new FormControl<AssetSubClass>(undefined),
comment: '',
countries: '',
countries: ['', jsonValidator()],
currency: '',
historicalData: this.formBuilder.group({
csvString: ''
@ -158,14 +158,14 @@ export class GfAssetProfileDialogComponent implements OnInit {
name: ['', Validators.required],
scraperConfiguration: this.formBuilder.group({
defaultMarketPrice: null,
headers: JSON.stringify({}),
headers: [JSON.stringify({}), jsonValidator()],
locale: '',
mode: '',
selector: '',
url: ''
}),
sectors: '',
symbolMapping: '',
sectors: ['', jsonValidator()],
symbolMapping: ['', jsonValidator()],
url: ''
});

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

@ -394,29 +394,151 @@
</mat-form-field>
</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>
</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 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
>
</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>
}
<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>

13
libs/common/src/lib/utils/form.util.ts

@ -1,6 +1,17 @@
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
import { FormGroup } from '@angular/forms';
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { isJSON, validate } from 'class-validator';
export function jsonValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!isJSON(control.value)) {
return { invalidJson: true };
}
return null;
};
}
export async function validateObjectForForm<T>({
classDto,

4
libs/common/src/lib/utils/index.ts

@ -1,3 +1,3 @@
import { validateObjectForForm } from './form.util';
import { jsonValidator, validateObjectForForm } from './form.util';
export { validateObjectForForm };
export { jsonValidator, validateObjectForForm };

Loading…
Cancel
Save