73 lines
3.4 KiB
TypeScript
73 lines
3.4 KiB
TypeScript
import { ChangeDetectionStrategy, Component, computed, input, model, resource } from '@angular/core';
|
|
import { UserFieldsApi, type UserFieldInfo } from '../../core/sl/user-fields';
|
|
import type { VhLookup } from '../value-help/value-help.types';
|
|
import { inject } from '@angular/core';
|
|
import { SelectField, TextField } from './fields';
|
|
import { FieldBase } from './field-base';
|
|
import { LookupField } from './lookup-field';
|
|
|
|
/**
|
|
* Campo de usuario de SAP (`U_*`) que se pide según como lo definió SAP: lista desplegable si tiene valores válidos,
|
|
* ventana de selección si está enlazado a una tabla de usuario, texto en otro caso (o mientras carga, o si la base de datos
|
|
* no está configurada). El tipo numérico se guarda como número.
|
|
*/
|
|
@Component({
|
|
selector: 'sbo-udf-field',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
imports: [LookupField, SelectField, TextField],
|
|
template: `
|
|
@if (kind() === 'select') {
|
|
<sbo-select-field [label]="label()" [dbName]="dbName()" [required]="required()" [readonly]="readOnly()" [error]="error()" [options]="options()" placeholder="" [value]="str() || null" (valueChange)="emit($event)" />
|
|
} @else if (kind() === 'lookup') {
|
|
<sbo-lookup-field [label]="label()" [dbName]="dbName()" [required]="required()" [readonly]="readOnly()" [error]="error()" [lookup]="lookup()" [value]="str()" (valueChange)="emit($event)" resolveOnLeave />
|
|
} @else {
|
|
<sbo-text-field [label]="label()" [dbName]="dbName()" [required]="required()" [readonly]="readOnly()" [error]="error()" [value]="str()" (valueChange)="emit($event)" />
|
|
}
|
|
`,
|
|
styles: ':host { display: block; }',
|
|
})
|
|
export class UdfField extends FieldBase {
|
|
private readonly api = inject(UserFieldsApi);
|
|
|
|
/** Tabla del campo (`OBTN`, `OWTQ`, `@MI_TABLA`) y alias sin el `U_` (`SIS_ESTLOT`). */
|
|
readonly table = input.required<string>();
|
|
readonly alias = input.required<string>();
|
|
readonly value = model<unknown>('');
|
|
|
|
protected readonly info = resource({
|
|
params: () => ({ table: this.table(), alias: this.alias() }),
|
|
loader: ({ params }) => this.api.get(params.table, params.alias),
|
|
});
|
|
private readonly def = computed<UserFieldInfo | null>(() => (this.info.hasValue() ? this.info.value() : null));
|
|
|
|
protected readonly kind = computed<'select' | 'lookup' | 'text'>(() => {
|
|
const d = this.def();
|
|
return d?.validValues.length ? 'select' : d?.linkedRows.length ? 'lookup' : 'text';
|
|
});
|
|
protected readonly str = computed(() => {
|
|
const v = this.value();
|
|
return v === null || v === undefined ? '' : String(v);
|
|
});
|
|
protected readonly options = computed(() => (this.def()?.validValues ?? []).map((v) => ({ value: v.value, label: v.description ? `${v.value} · ${v.description}` : v.value })));
|
|
protected readonly lookup = computed<VhLookup>(() => {
|
|
const d = this.def()!;
|
|
return {
|
|
title: d.description || d.linkedTable || 'Valores',
|
|
resource: d.linkedTable ?? 'UserTable',
|
|
columns: [
|
|
{ key: 'code', title: 'Código', width: '140px', mono: true, searchable: true },
|
|
{ key: 'name', title: 'Nombre', searchable: true },
|
|
],
|
|
rows: d.linkedRows.map((r) => ({ code: r.code, name: r.name })),
|
|
valueKey: 'code',
|
|
nameKey: 'name',
|
|
codeWidth: '140px',
|
|
};
|
|
});
|
|
|
|
protected emit(v: string | number | null): void {
|
|
const s = v === null ? '' : String(v);
|
|
this.value.set(this.def()?.type === 'N' && s.trim() !== '' && Number.isFinite(Number(s)) ? Number(s) : s);
|
|
}
|
|
}
|