2026-10-13 20:17:52 -05:00
|
|
|
|
<div class="bar">
|
|
|
|
|
|
<span class="count">{{ lines().length }} {{ lines().length === 1 ? 'línea' : 'líneas' }}</span>
|
|
|
|
|
|
@if (!readonly()) {
|
|
|
|
|
|
<span class="sp"></span>
|
|
|
|
|
|
@if (multiAdd(); as m) {
|
|
|
|
|
|
<button type="button" class="btn" (click)="multiOpen.set(true)">{{ m.label }}</button>
|
|
|
|
|
|
}
|
|
|
|
|
|
<button type="button" class="btn main" (click)="add()">+ {{ addLabel() }}</button>
|
|
|
|
|
|
}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="gridwrap">
|
2026-10-16 11:09:47 -05:00
|
|
|
|
<table class="grid" [style.min-width.px]="tableMinWidth()">
|
2026-10-13 20:17:52 -05:00
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th class="rn">#</th>
|
2026-10-16 12:47:51 -05:00
|
|
|
|
@for (c of columns(); track c.key; let j = $index) {
|
2026-10-20 08:59:58 -05:00
|
|
|
|
<th sboColResize [style.width]="c.width" [style.text-align]="alignOf(c)" [class.req]="c.required" [attr.title]="c.key">{{ c.title }}@if (names.show()) {
|
|
|
|
|
|
<span class="db">{{ c.key }}</span>
|
|
|
|
|
|
}</th>
|
2026-10-16 12:47:51 -05:00
|
|
|
|
@if (hasDetails() && j === detailAt()) {
|
|
|
|
|
|
<th class="det">Lotes / Series</th>
|
|
|
|
|
|
}
|
2026-10-16 12:25:01 -05:00
|
|
|
|
}
|
2026-10-13 20:17:52 -05:00
|
|
|
|
@if (!readonly()) {
|
|
|
|
|
|
<th class="del"><span class="sr">Quitar</span></th>
|
|
|
|
|
|
}
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
@for (line of lines(); track $index; let i = $index) {
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td class="rn">{{ i + 1 }}</td>
|
|
|
|
|
|
@for (c of columns(); track c.key; let j = $index) {
|
|
|
|
|
|
<td [class.ro]="isReadonly(line, c)">
|
|
|
|
|
|
@if (c.lookup && !isReadonly(line, c)) {
|
|
|
|
|
|
<div class="pick">
|
|
|
|
|
|
<input
|
|
|
|
|
|
class="cell"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
autocomplete="off"
|
|
|
|
|
|
[class.mono]="c.mono"
|
2026-10-16 11:23:44 -05:00
|
|
|
|
[style.text-align]="alignOf(c)"
|
2026-10-13 20:17:52 -05:00
|
|
|
|
[attr.data-r]="i"
|
|
|
|
|
|
[attr.data-c]="j"
|
|
|
|
|
|
[attr.aria-label]="c.title + ' de la línea ' + (i + 1)"
|
|
|
|
|
|
[value]="cellText(line, c)"
|
|
|
|
|
|
(change)="commit(i, c, $any($event.target))"
|
|
|
|
|
|
(keydown)="onKey($event, i, j)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<button type="button" tabindex="-1" title="Lista de valores (F4)" [attr.aria-label]="'Abrir la lista de ' + c.title" (click)="openLookup(i, c)">…</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
} @else {
|
|
|
|
|
|
<input
|
|
|
|
|
|
class="cell"
|
2026-10-19 14:53:59 -05:00
|
|
|
|
[attr.type]="c.type === 'date' ? 'date' : 'text'"
|
2026-10-13 20:17:52 -05:00
|
|
|
|
autocomplete="off"
|
2026-10-16 11:23:44 -05:00
|
|
|
|
[style.text-align]="alignOf(c)"
|
2026-10-13 20:17:52 -05:00
|
|
|
|
[class.mono]="c.mono"
|
|
|
|
|
|
[readOnly]="isReadonly(line, c)"
|
|
|
|
|
|
[attr.data-r]="i"
|
|
|
|
|
|
[attr.data-c]="j"
|
|
|
|
|
|
[attr.aria-label]="c.title + ' de la línea ' + (i + 1)"
|
|
|
|
|
|
[attr.inputmode]="c.type === 'number' ? 'decimal' : null"
|
|
|
|
|
|
[attr.title]="cellText(line, c) || null"
|
|
|
|
|
|
[value]="cellText(line, c)"
|
|
|
|
|
|
(focus)="c.type === 'number' ? numberFocus($event, line, c) : null"
|
|
|
|
|
|
(change)="commit(i, c, $any($event.target))"
|
|
|
|
|
|
(blur)="c.type === 'number' ? commit(i, c, $any($event.target)) : null"
|
|
|
|
|
|
(keydown)="onKey($event, i, j)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
}
|
|
|
|
|
|
</td>
|
2026-10-16 12:47:51 -05:00
|
|
|
|
@if (hasDetails() && j === detailAt()) {
|
|
|
|
|
|
<td class="det">
|
|
|
|
|
|
@for (d of detailsOf(line); track d.key) {
|
|
|
|
|
|
<button type="button" class="detbtn" [attr.aria-label]="d.title + ' de la línea ' + (i + 1)" (click)="openDetail(i, d)">{{ d.summary(line) }}</button>
|
|
|
|
|
|
}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
}
|
2026-10-16 12:25:01 -05:00
|
|
|
|
}
|
2026-10-13 20:17:52 -05:00
|
|
|
|
@if (!readonly()) {
|
|
|
|
|
|
<td class="del">
|
|
|
|
|
|
<button type="button" [attr.aria-label]="'Quitar la línea ' + (i + 1)" title="Quitar línea" (click)="remove(i)">×</button>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
}
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
} @empty {
|
|
|
|
|
|
<tr class="none">
|
2026-10-16 12:25:01 -05:00
|
|
|
|
<td [attr.colspan]="columns().length + (readonly() ? 1 : 2) + (hasDetails() ? 1 : 0)">
|
2026-10-13 20:17:52 -05:00
|
|
|
|
{{ readonly() ? 'El documento no tiene líneas.' : 'No hay líneas. Pulse «Añadir línea» para comenzar.' }}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
}
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-16 12:25:01 -05:00
|
|
|
|
@if (detailTarget(); as t) {
|
|
|
|
|
|
<sbo-line-detail-dialog
|
|
|
|
|
|
[title]="t.detail.title"
|
|
|
|
|
|
[subtitle]="'Línea ' + (t.row + 1)"
|
|
|
|
|
|
[columns]="t.detail.columns"
|
|
|
|
|
|
[initial]="detailInitial()"
|
|
|
|
|
|
[readonly]="readonly()"
|
|
|
|
|
|
[hintFor]="detailHintFn()"
|
|
|
|
|
|
(saved)="detailSaved($event)"
|
|
|
|
|
|
(closed)="detailTarget.set(null)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-13 20:17:52 -05:00
|
|
|
|
@if (lookup(); as cfg) {
|
|
|
|
|
|
<sbo-value-help
|
|
|
|
|
|
[open]="true"
|
|
|
|
|
|
[title]="cfg.title"
|
|
|
|
|
|
[resource]="cfg.resource"
|
|
|
|
|
|
[columns]="cfg.columns"
|
|
|
|
|
|
[baseFilter]="cfg.baseFilter"
|
|
|
|
|
|
[orderby]="cfg.orderby"
|
|
|
|
|
|
[rowKey]="cfg.valueKey"
|
2026-10-14 14:37:01 -05:00
|
|
|
|
[extraFields]="cfg.extraFields ?? []"
|
2026-10-14 14:27:36 -05:00
|
|
|
|
[selection]="lookupMultiple() ? 'multiple' : 'single'"
|
2026-10-13 20:17:52 -05:00
|
|
|
|
(selected)="lookupPicked($event)"
|
|
|
|
|
|
(closed)="lookupClosed()"
|
|
|
|
|
|
/>
|
|
|
|
|
|
}
|
|
|
|
|
|
@if (multiOpen(); as _) {
|
|
|
|
|
|
@if (multiAdd(); as m) {
|
|
|
|
|
|
<sbo-value-help
|
|
|
|
|
|
[open]="true"
|
|
|
|
|
|
[title]="m.lookup.title"
|
|
|
|
|
|
[resource]="m.lookup.resource"
|
|
|
|
|
|
[columns]="m.lookup.columns"
|
|
|
|
|
|
[baseFilter]="m.lookup.baseFilter"
|
|
|
|
|
|
[orderby]="m.lookup.orderby"
|
2026-10-14 14:37:01 -05:00
|
|
|
|
[extraFields]="m.lookup.extraFields ?? []"
|
2026-10-13 20:17:52 -05:00
|
|
|
|
selection="multiple"
|
|
|
|
|
|
(selected)="multiPicked($event)"
|
|
|
|
|
|
(closed)="multiOpen.set(false)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|