@bexis2/bexis2-core-ui 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/components/File/FileUploader.svelte +7 -0
- package/dist/components/Table/Table.svelte +5 -379
- package/dist/components/Table/Table.svelte.d.ts +1 -12
- package/dist/components/Table/TableContent.svelte +382 -0
- package/dist/components/Table/TableContent.svelte.d.ts +19 -0
- package/dist/components/form/InputContainer.svelte +1 -1
- package/dist/components/page/Docs.svelte +1 -1
- package/package.json +1 -1
- package/src/lib/components/Table/Table.svelte +6 -437
- package/src/lib/components/Table/TableContent.svelte +442 -0
- package/src/lib/components/file/FileUploader.svelte +9 -0
- package/src/lib/components/form/InputContainer.svelte +1 -1
- package/src/lib/components/page/Docs.svelte +1 -1
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
import { createTable, Subscribe, Render, createRender } from 'svelte-headless-table';
|
|
4
|
+
import {
|
|
5
|
+
addSortBy,
|
|
6
|
+
addPagination,
|
|
7
|
+
addExpandedRows,
|
|
8
|
+
addColumnFilters,
|
|
9
|
+
addTableFilter,
|
|
10
|
+
addDataExport
|
|
11
|
+
} from 'svelte-headless-table/plugins';
|
|
12
|
+
import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
|
|
13
|
+
import { SlideToggle, storePopup } from '@skeletonlabs/skeleton';
|
|
14
|
+
|
|
15
|
+
storePopup.set({ computePosition, autoUpdate, offset, shift, flip, arrow });
|
|
16
|
+
|
|
17
|
+
import TableFilter from './TableFilter.svelte';
|
|
18
|
+
import TablePagination from './TablePagination.svelte';
|
|
19
|
+
import { columnFilter, searchFilter } from './filter';
|
|
20
|
+
import type { TableConfig } from '$lib/models/Models';
|
|
21
|
+
|
|
22
|
+
export let config: TableConfig<any>;
|
|
23
|
+
|
|
24
|
+
// Destructuring the config object and setting default values
|
|
25
|
+
let {
|
|
26
|
+
id: tableId, // Unique table ID
|
|
27
|
+
data, // Data store
|
|
28
|
+
columns, // Column configuration
|
|
29
|
+
resizable = 'none', // Resizability config
|
|
30
|
+
height = null, // Table height
|
|
31
|
+
rowHeight = null, // Row height
|
|
32
|
+
optionsComponent, // Custom component to render in the last column
|
|
33
|
+
defaultPageSize = 10, // Default page size - number of rows to display per page
|
|
34
|
+
toggle = false, // Whether to display the fitToScreen toggle
|
|
35
|
+
pageSizes = [5, 10, 15, 20], // Page sizes to display in the pagination component
|
|
36
|
+
fitToScreen = true, // Whether to fit the table to the screen,
|
|
37
|
+
exportable = false // Whether to display the export button and enable export functionality
|
|
38
|
+
} = config;
|
|
39
|
+
|
|
40
|
+
// Creatign a type to access keys of the objects in the data store
|
|
41
|
+
type AccessorType = keyof (typeof $data)[number];
|
|
42
|
+
|
|
43
|
+
// Creating a dispatcher to dispatch actions to the parent component
|
|
44
|
+
const dispatch = createEventDispatcher();
|
|
45
|
+
const actionDispatcher = (obj) => dispatch('action', obj);
|
|
46
|
+
|
|
47
|
+
// Initializing the table
|
|
48
|
+
const table = createTable(data, {
|
|
49
|
+
colFilter: addColumnFilters(),
|
|
50
|
+
tableFilter: addTableFilter({
|
|
51
|
+
fn: searchFilter
|
|
52
|
+
}),
|
|
53
|
+
sort: addSortBy({ disableMultiSort: true }),
|
|
54
|
+
page: addPagination({ initialPageSize: defaultPageSize }),
|
|
55
|
+
expand: addExpandedRows(),
|
|
56
|
+
export: addDataExport({ format: 'csv' })
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// A variable to hold all the keys
|
|
60
|
+
const allCols: { [key: string]: any } = {};
|
|
61
|
+
// Iterating over each item to get all the possible keys
|
|
62
|
+
$data.forEach((item) => {
|
|
63
|
+
Object.keys(item).forEach((key) => {
|
|
64
|
+
if (!allCols[key]) {
|
|
65
|
+
allCols[key] = {};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
// Creating an array of all the keys
|
|
70
|
+
const accessors: AccessorType[] = Object.keys(allCols) as AccessorType[];
|
|
71
|
+
// Configuring every table column with the provided options
|
|
72
|
+
const tableColumns = [
|
|
73
|
+
...accessors
|
|
74
|
+
.filter((accessor) => {
|
|
75
|
+
// Filtering only unexcluded columns
|
|
76
|
+
const key = accessor as string;
|
|
77
|
+
if (columns !== undefined && key in columns && columns[key].exclude === true) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
})
|
|
82
|
+
.map((accessor) => {
|
|
83
|
+
const key = accessor as string;
|
|
84
|
+
// Applying configuration options for configured columns
|
|
85
|
+
if (columns !== undefined && key in columns) {
|
|
86
|
+
const {
|
|
87
|
+
header, // Custom header to display
|
|
88
|
+
colFilterFn, // Custom column filter function
|
|
89
|
+
colFilterComponent, // Custom column filter component
|
|
90
|
+
instructions, // Custom instructions for the column cells (sorting, filtering, searching, rendering)
|
|
91
|
+
disableFiltering = false, // Whether to disable filtering for the column
|
|
92
|
+
disableSorting = false // Whether to disable sorting for the column
|
|
93
|
+
} = columns[key];
|
|
94
|
+
|
|
95
|
+
const { toSortableValueFn, toFilterableValueFn, toStringFn, renderComponent } =
|
|
96
|
+
instructions ?? {};
|
|
97
|
+
|
|
98
|
+
return table.column({
|
|
99
|
+
// If header is not provided, use the key as the header
|
|
100
|
+
header: header ?? key,
|
|
101
|
+
accessor: accessor,
|
|
102
|
+
// Render the cell with the provided component, or use the toStringFn if provided, or just use the value
|
|
103
|
+
cell: ({ value, row }) => {
|
|
104
|
+
return renderComponent
|
|
105
|
+
? createRender(renderComponent, { value, row })
|
|
106
|
+
: toStringFn
|
|
107
|
+
? toStringFn(value)
|
|
108
|
+
: value;
|
|
109
|
+
},
|
|
110
|
+
plugins: {
|
|
111
|
+
// Sorting config
|
|
112
|
+
sort: {
|
|
113
|
+
disable: disableSorting,
|
|
114
|
+
invert: true,
|
|
115
|
+
getSortValue: (row) => {
|
|
116
|
+
// If provided, use the custom sorting function toSortableValueFn(), or just use the value
|
|
117
|
+
return toSortableValueFn ? toSortableValueFn(row) : row;
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
colFilter: !disableFiltering
|
|
121
|
+
? {
|
|
122
|
+
fn: ({ filterValue, value }) => {
|
|
123
|
+
// If provided, use the custom filtering function toFilterableValueFn(), or just use the value
|
|
124
|
+
const val = toFilterableValueFn ? toFilterableValueFn(value) : value;
|
|
125
|
+
// If provided, use the custom filtering function colFilterFn(), or just use the default columnFilter()
|
|
126
|
+
return colFilterFn
|
|
127
|
+
? colFilterFn({ filterValue, value: val })
|
|
128
|
+
: columnFilter({ filterValue, value: val });
|
|
129
|
+
},
|
|
130
|
+
render: ({ filterValue, values, id }) => {
|
|
131
|
+
// If provided, use the custom filter component, or use the default TableFilter component
|
|
132
|
+
return createRender(colFilterComponent ?? TableFilter, {
|
|
133
|
+
filterValue,
|
|
134
|
+
id,
|
|
135
|
+
tableId,
|
|
136
|
+
values,
|
|
137
|
+
toFilterableValueFn
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
: undefined,
|
|
142
|
+
tableFilter: {
|
|
143
|
+
// Search filter config
|
|
144
|
+
getFilterValue: (row) => {
|
|
145
|
+
// If provided, use the custom toString function toStringFn(), or just use the value
|
|
146
|
+
return toStringFn ? toStringFn(row) : row;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
} else {
|
|
152
|
+
// Default configuration for unconfigured columns
|
|
153
|
+
return table.column({
|
|
154
|
+
header: key,
|
|
155
|
+
accessor: accessor,
|
|
156
|
+
cell: ({ value }) => {
|
|
157
|
+
// If null or undefined, return an empty string
|
|
158
|
+
return value ? value : '';
|
|
159
|
+
},
|
|
160
|
+
plugins: {
|
|
161
|
+
// Sorting enabled by default
|
|
162
|
+
sort: {
|
|
163
|
+
invert: true
|
|
164
|
+
},
|
|
165
|
+
// Filtering enabled by default
|
|
166
|
+
colFilter: {
|
|
167
|
+
fn: columnFilter,
|
|
168
|
+
render: ({ filterValue, values, id }) =>
|
|
169
|
+
createRender(TableFilter, {
|
|
170
|
+
filterValue,
|
|
171
|
+
id,
|
|
172
|
+
tableId,
|
|
173
|
+
values
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
// If optionsComponent is provided, add a column for it at the end
|
|
183
|
+
if (optionsComponent !== undefined) {
|
|
184
|
+
tableColumns.push(
|
|
185
|
+
table.display({
|
|
186
|
+
id: 'optionsColumn',
|
|
187
|
+
header: '',
|
|
188
|
+
plugins: {
|
|
189
|
+
export: {
|
|
190
|
+
exclude: true
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
cell: ({ row }, _) => {
|
|
194
|
+
return createRender(optionsComponent!, {
|
|
195
|
+
row: row.isData() ? row.original : null,
|
|
196
|
+
dispatchFn: actionDispatcher
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}) as any
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Creating the table columns
|
|
204
|
+
const createdTableColumns = table.createColumns(tableColumns);
|
|
205
|
+
// Creating the table view model
|
|
206
|
+
const { headerRows, pageRows, tableAttrs, tableBodyAttrs, pluginStates } =
|
|
207
|
+
table.createViewModel(createdTableColumns);
|
|
208
|
+
// Extracting filterValue to bind it for the search input and search immediately on input
|
|
209
|
+
const { filterValue } = pluginStates.tableFilter;
|
|
210
|
+
// CSV content to be exported. If unexportable, then null
|
|
211
|
+
const { exportedData } = pluginStates.export;
|
|
212
|
+
|
|
213
|
+
// Function to determine minWidth for a column to simplify the logic in the HTML
|
|
214
|
+
const minWidth = (id: string) => {
|
|
215
|
+
if (columns && id in columns) {
|
|
216
|
+
return columns[id].minWidth ?? 0;
|
|
217
|
+
}
|
|
218
|
+
return 0;
|
|
219
|
+
};
|
|
220
|
+
// Function to determine fixedWidth for a column to simplify the logic in the HTML
|
|
221
|
+
const fixedWidth = (id: string) => {
|
|
222
|
+
if (columns && id in columns) {
|
|
223
|
+
return columns[id].fixedWidth ?? 0;
|
|
224
|
+
}
|
|
225
|
+
return 0;
|
|
226
|
+
};
|
|
227
|
+
// Function to create custom styles for the columns to simplify the logic in the HTML
|
|
228
|
+
const cellStyle = (id: string) => {
|
|
229
|
+
const minW = minWidth(id);
|
|
230
|
+
const fixedW = fixedWidth(id);
|
|
231
|
+
const styles: string[] = [];
|
|
232
|
+
|
|
233
|
+
// If minWidth is provided, add to styles
|
|
234
|
+
minW && styles.push(`min-width: ${minW}px`);
|
|
235
|
+
// If fixedWidth is provided, add to styles
|
|
236
|
+
fixedW && styles.push(`width: ${fixedW}px`);
|
|
237
|
+
// Create and return styles separated by ';'
|
|
238
|
+
return styles.join(';');
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// Resetting the resized columns and/or rows
|
|
242
|
+
const resetResize = () => {
|
|
243
|
+
// Run only if resizable is not none
|
|
244
|
+
if (resizable === 'columns' || resizable === 'both') {
|
|
245
|
+
$headerRows.forEach((row) => {
|
|
246
|
+
row.cells.forEach((cell) => {
|
|
247
|
+
const minW = minWidth(cell.id);
|
|
248
|
+
const fixedW = fixedWidth(cell.id);
|
|
249
|
+
// If a fixedWidth is provided for a column, then reset the width to that value
|
|
250
|
+
fixedW &&
|
|
251
|
+
document
|
|
252
|
+
.getElementById(`th-${tableId}-${cell.id}`)
|
|
253
|
+
?.style.setProperty('width', `${fixedW}px`);
|
|
254
|
+
// If a minWidth is provided for a column, then reset the width to that value
|
|
255
|
+
minW &&
|
|
256
|
+
document
|
|
257
|
+
.getElementById(`th-${tableId}-${cell.id}`)
|
|
258
|
+
?.style.setProperty('min-width', `${minW}px`);
|
|
259
|
+
// If neither minWidth nor fixedWidth provided for a column, then reset the width to auto
|
|
260
|
+
!minW &&
|
|
261
|
+
!fixedW &&
|
|
262
|
+
document.getElementById(`th-${tableId}-${cell.id}`)?.style.setProperty('width', 'auto');
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (resizable === 'rows' || resizable === 'both') {
|
|
268
|
+
$pageRows.forEach((row) => {
|
|
269
|
+
row.cells.forEach((cell) => {
|
|
270
|
+
// Reset all row heights to auto
|
|
271
|
+
document
|
|
272
|
+
.getElementById(`${tableId}-${cell.id}-${row.id}`)
|
|
273
|
+
?.style.setProperty('height', 'auto');
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const exportAsCsv = () => {
|
|
280
|
+
// Creating a hidden anchor element to download the CSV file
|
|
281
|
+
const anchor = document.createElement('a');
|
|
282
|
+
anchor.style.display = 'none';
|
|
283
|
+
anchor.href = `data:text/csv;charset=utf-8,${encodeURIComponent($exportedData)}`;
|
|
284
|
+
anchor.download = `${tableId}.csv`;
|
|
285
|
+
document.body.appendChild(anchor);
|
|
286
|
+
anchor.click();
|
|
287
|
+
document.body.removeChild(anchor);
|
|
288
|
+
};
|
|
289
|
+
</script>
|
|
290
|
+
|
|
291
|
+
<div class="grid gap-2 overflow-auto" class:w-fit={!fitToScreen} class:w-full={fitToScreen}>
|
|
292
|
+
<div class="table-container">
|
|
293
|
+
<!-- Enable the search filter if table is not empty -->
|
|
294
|
+
{#if $data.length > 0}
|
|
295
|
+
<input
|
|
296
|
+
class="input p-2 border border-primary-500"
|
|
297
|
+
type="text"
|
|
298
|
+
bind:value={$filterValue}
|
|
299
|
+
placeholder="Search rows..."
|
|
300
|
+
id="{tableId}-search"
|
|
301
|
+
/>
|
|
302
|
+
<div class="flex justify-between items-center py-2 w-full">
|
|
303
|
+
<div>
|
|
304
|
+
<!-- Enable the fitToScreen toggle if toggle === true -->
|
|
305
|
+
{#if toggle}
|
|
306
|
+
<SlideToggle
|
|
307
|
+
name="slider-label"
|
|
308
|
+
active="bg-primary-500"
|
|
309
|
+
size="sm"
|
|
310
|
+
checked={fitToScreen}
|
|
311
|
+
id="{tableId}-toggle"
|
|
312
|
+
on:change={() => (fitToScreen = !fitToScreen)}>Fit to screen</SlideToggle
|
|
313
|
+
>
|
|
314
|
+
{/if}
|
|
315
|
+
</div>
|
|
316
|
+
<div class="flex gap-2">
|
|
317
|
+
<!-- Enable the resetResize button if resizable !== 'none' -->
|
|
318
|
+
{#if resizable !== 'none'}
|
|
319
|
+
<button
|
|
320
|
+
type="button"
|
|
321
|
+
class="btn btn-sm variant-filled-primary rounded-full order-last"
|
|
322
|
+
on:click|preventDefault={resetResize}>Reset sizing</button
|
|
323
|
+
>
|
|
324
|
+
{/if}
|
|
325
|
+
{#if exportable}
|
|
326
|
+
<button
|
|
327
|
+
type="button"
|
|
328
|
+
class="btn btn-sm variant-filled-primary rounded-full order-last"
|
|
329
|
+
on:click|preventDefault={exportAsCsv}>Export as CSV</button
|
|
330
|
+
>
|
|
331
|
+
{/if}
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
{/if}
|
|
335
|
+
|
|
336
|
+
<div class="overflow-auto" style="height: {height}px">
|
|
337
|
+
<table
|
|
338
|
+
{...$tableAttrs}
|
|
339
|
+
class="table table-auto table-compact bg-tertiary-500/30 dark:bg-tertiary-900/10 overflow-clip"
|
|
340
|
+
id="{tableId}-table"
|
|
341
|
+
>
|
|
342
|
+
<!-- If table height is provided, making the top row sticky -->
|
|
343
|
+
<thead class=" {height != null ? `sticky top-0` : ''}">
|
|
344
|
+
{#if $data.length > 0}
|
|
345
|
+
{#each $headerRows as headerRow (headerRow.id)}
|
|
346
|
+
<Subscribe
|
|
347
|
+
rowAttrs={headerRow.attrs()}
|
|
348
|
+
let:rowAttrs
|
|
349
|
+
rowProps={headerRow.props()}
|
|
350
|
+
let:rowProps
|
|
351
|
+
>
|
|
352
|
+
<tr {...rowAttrs} class="bg-primary-300 dark:bg-primary-500 items-stretch">
|
|
353
|
+
{#each headerRow.cells as cell (cell.id)}
|
|
354
|
+
<Subscribe attrs={cell.attrs()} props={cell.props()} let:props let:attrs>
|
|
355
|
+
<th
|
|
356
|
+
scope="col"
|
|
357
|
+
class="!p-2 overflow-auto"
|
|
358
|
+
class:resize-x={(resizable === 'columns' || resizable === 'both') &&
|
|
359
|
+
!fixedWidth(cell.id)}
|
|
360
|
+
{...attrs}
|
|
361
|
+
id="th-{tableId}-{cell.id}"
|
|
362
|
+
style={cellStyle(cell.id)}
|
|
363
|
+
>
|
|
364
|
+
<div class="flex justify-between items-center">
|
|
365
|
+
<div class="flex gap-1 whitespace-pre-wrap">
|
|
366
|
+
<!-- Adding sorting config and styling -->
|
|
367
|
+
<span
|
|
368
|
+
class:underline={props.sort.order}
|
|
369
|
+
class:normal-case={cell.id !== cell.label}
|
|
370
|
+
class:cursor-pointer={!props.sort.disabled}
|
|
371
|
+
on:click={props.sort.toggle}
|
|
372
|
+
on:keydown={props.sort.toggle}
|
|
373
|
+
>
|
|
374
|
+
{cell.render()}
|
|
375
|
+
</span>
|
|
376
|
+
<div class="w-2">
|
|
377
|
+
{#if props.sort.order === 'asc'}
|
|
378
|
+
▾
|
|
379
|
+
{:else if props.sort.order === 'desc'}
|
|
380
|
+
▴
|
|
381
|
+
{/if}
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
<!-- Adding column filter config -->
|
|
385
|
+
{#if cell.isData()}
|
|
386
|
+
{#if props.colFilter?.render}
|
|
387
|
+
<div class="">
|
|
388
|
+
<Render of={props.colFilter.render} />
|
|
389
|
+
</div>
|
|
390
|
+
{/if}
|
|
391
|
+
{/if}
|
|
392
|
+
</div>
|
|
393
|
+
</th>
|
|
394
|
+
</Subscribe>
|
|
395
|
+
{/each}
|
|
396
|
+
</tr>
|
|
397
|
+
</Subscribe>
|
|
398
|
+
{/each}
|
|
399
|
+
{:else}
|
|
400
|
+
<!-- Table is empty -->
|
|
401
|
+
<p class="items-center justify-center flex w-full p-10 italic">Nothing to show here.</p>
|
|
402
|
+
{/if}
|
|
403
|
+
</thead>
|
|
404
|
+
|
|
405
|
+
<tbody class="overflow-auto" {...$tableBodyAttrs}>
|
|
406
|
+
{#if $data.length > 0}
|
|
407
|
+
{#each $pageRows as row (row.id)}
|
|
408
|
+
<Subscribe rowAttrs={row.attrs()} let:rowAttrs>
|
|
409
|
+
<tr {...rowAttrs} id="{tableId}-row-{row.id}" class="">
|
|
410
|
+
{#each row.cells as cell, index (cell?.id)}
|
|
411
|
+
<Subscribe attrs={cell.attrs()} let:attrs>
|
|
412
|
+
<td
|
|
413
|
+
{...attrs}
|
|
414
|
+
class="!p-2 overflow-auto {index === 0 &&
|
|
415
|
+
(resizable === 'rows' || resizable === 'both')
|
|
416
|
+
? 'resize-y'
|
|
417
|
+
: ''}"
|
|
418
|
+
id="{tableId}-{cell.id}-{row.id}"
|
|
419
|
+
>
|
|
420
|
+
<!-- Adding config for initial rowHeight, if provided -->
|
|
421
|
+
<div
|
|
422
|
+
class="flex items-center"
|
|
423
|
+
style="height: {rowHeight ? `${rowHeight}px` : 'auto'};"
|
|
424
|
+
>
|
|
425
|
+
<div class="grow h-full"><Render of={cell.render()} /></div>
|
|
426
|
+
</div>
|
|
427
|
+
</td>
|
|
428
|
+
</Subscribe>
|
|
429
|
+
{/each}
|
|
430
|
+
</tr>
|
|
431
|
+
</Subscribe>
|
|
432
|
+
{/each}
|
|
433
|
+
{/if}
|
|
434
|
+
</tbody>
|
|
435
|
+
</table>
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
{#if $data.length > 0}
|
|
439
|
+
<!-- Adding pagination, if table is not empty -->
|
|
440
|
+
<TablePagination pageConfig={pluginStates.page} {pageSizes} id={tableId} />
|
|
441
|
+
{/if}
|
|
442
|
+
</div>
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
export let version = 1;
|
|
22
22
|
|
|
23
23
|
import { onMount } from 'svelte';
|
|
24
|
+
import { ProgressBar } from '@skeletonlabs/skeleton';
|
|
24
25
|
|
|
25
26
|
// export let description="";
|
|
26
27
|
// export let status=0;
|
|
@@ -34,6 +35,8 @@
|
|
|
34
35
|
|
|
35
36
|
export let data: fileUploaderType | undefined;
|
|
36
37
|
|
|
38
|
+
let isUploading:boolean = false;
|
|
39
|
+
|
|
37
40
|
$: model = data;
|
|
38
41
|
$: submitBt = 'submit';
|
|
39
42
|
|
|
@@ -124,6 +127,7 @@
|
|
|
124
127
|
//console.log('SUBMIT');
|
|
125
128
|
|
|
126
129
|
dispatch('submit');
|
|
130
|
+
isUploading = true;
|
|
127
131
|
|
|
128
132
|
let url = submit + '?id=' + id;
|
|
129
133
|
|
|
@@ -156,6 +160,8 @@
|
|
|
156
160
|
files.accepted = [];
|
|
157
161
|
}
|
|
158
162
|
}
|
|
163
|
+
|
|
164
|
+
isUploading = false;
|
|
159
165
|
}
|
|
160
166
|
</script>
|
|
161
167
|
|
|
@@ -182,6 +188,9 @@
|
|
|
182
188
|
{/if}
|
|
183
189
|
</p>
|
|
184
190
|
</DropZone>
|
|
191
|
+
{#if isUploading}
|
|
192
|
+
<ProgressBar value={undefined}/>
|
|
193
|
+
{/if}
|
|
185
194
|
</div>
|
|
186
195
|
|
|
187
196
|
<button id={submitBt} color="primary" style="display:none"><Fa icon={faSave} /></button>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
function onMouseOut() {}
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
|
-
<div id="{id}-container" on:mouseover={onMouseOver} on:mouseout={onMouseOut}>
|
|
19
|
+
<div id="{id}-container" on:mouseover={onMouseOver} on:focus={onMouseOver} on:mouseout={onMouseOut} on:blur={onMouseOut}>
|
|
20
20
|
<label class="label">
|
|
21
21
|
<span
|
|
22
22
|
>{label}
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
{/if}
|
|
40
40
|
|
|
41
41
|
{#each links as link}
|
|
42
|
-
<span class="chip variant-soft hover:variant-filled" on:click={() => goTo(link.url, false)}>
|
|
42
|
+
<span class="chip variant-soft hover:variant-filled" on:click={() => goTo(link.url, false)} on:keypress={() => goTo(link.url, false)}>
|
|
43
43
|
<span>{link.label}</span>
|
|
44
44
|
</span>
|
|
45
45
|
{/each}
|