fix: improve autodata table

This commit is contained in:
Ruben Fiszel
2024-04-24 23:22:37 +02:00
parent 96265a6f90
commit 613bc26749
3 changed files with 136 additions and 107 deletions
+2 -2
View File
@@ -12,7 +12,6 @@
import NumberTypeNarrowing from './NumberTypeNarrowing.svelte'
import ObjectResourceInput from './ObjectResourceInput.svelte'
import ObjectTypeNarrowing from './ObjectTypeNarrowing.svelte'
import Password from './Password.svelte'
import Range from './Range.svelte'
import ResourcePicker from './ResourcePicker.svelte'
import SchemaForm from './SchemaForm.svelte'
@@ -28,6 +27,7 @@
import CurrencyInput from './apps/components/inputs/currency/CurrencyInput.svelte'
import FileUpload from './common/fileUpload/FileUpload.svelte'
import autosize from '$lib/autosize'
import PasswordArgInput from './PasswordArgInput.svelte'
export let label: string = ''
export let value: any
@@ -651,7 +651,7 @@
<div class="flex flex-col w-full">
<div class="flex flex-row w-full items-center justify-between relative">
{#if password || extra?.['password'] == true}
<Password {disabled} bind:password={value} />
<PasswordArgInput {disabled} bind:value />
{:else}
{#key extra?.['minRows']}
<textarea
@@ -0,0 +1,65 @@
<script lang="ts">
import { VariableService } from '$lib/gen'
import { userStore, workspaceStore } from '$lib/stores'
import { generateRandomString } from '$lib/utils'
import Password from './Password.svelte'
export let value: string | undefined = undefined
export let disabled: boolean
let path = ''
let password = ''
async function getPasswordFromValue(value: string | undefined = undefined) {
if (value?.startsWith('$var:')) {
password = await VariableService.getVariableValue({
workspace: $workspaceStore!,
path: value.substring(5)
})
}
}
async function generateValue() {
let npath =
'u/' + ($userStore?.username ?? $userStore?.email) + '/secret_arg/' + generateRandomString(12)
let nvalue = '$var:' + npath
await VariableService.createVariable({
workspace: $workspaceStore!,
requestBody: {
value: password,
is_secret: true,
path: npath,
description: ''
}
})
path = npath
value = nvalue
}
async function updateValue() {
await VariableService.updateVariable({
workspace: $workspaceStore!,
path: path,
requestBody: {
value: password
}
})
}
let timeout: NodeJS.Timeout | undefined = undefined
function debouncedUpdate() {
timeout && clearTimeout(timeout)
setTimeout(updateValue, 500)
}
$: password && debouncedUpdate()
$: (value == '' || value == undefined) &&
$workspaceStore &&
($userStore?.username || $userStore?.email) &&
generateValue()
$: value != '' && value != undefined && getPasswordFromValue(value)
</script>
<Password {disabled} bind:password />
@@ -1,14 +1,5 @@
<script lang="ts">
import {
ArrowDown,
ArrowUp,
Download,
EyeIcon,
MoreVertical,
MoveVertical,
Columns,
EyeOff
} from 'lucide-svelte'
import { ArrowDown, ArrowUp, Download, MoreVertical, MoveVertical, Columns } from 'lucide-svelte'
import Dropdown from '../DropdownV2.svelte'
import Cell from './Cell.svelte'
import DataTable from './DataTable.svelte'
@@ -28,13 +19,35 @@
let perPage = 5
let search: string = ''
let nextId = 1
$: structuredObjects = objects.map((obj) => {
return {
_id: nextId++,
rowData: { ...obj }
$: structuredObjects = computeStructuredObjects(objects)
let headers: string[] = []
function computeStructuredObjects(objects: Array<Record<string, any>>) {
if (Array.isArray(objects)) {
let nextId = 1
let hds: string[] = []
let objs = objects.map((obj) => {
let rowData = obj && typeof obj == 'object' ? obj : {}
let ks = Object.keys(rowData)
ks.forEach((x) => {
if (!hds.includes(x)) {
hds.push(x)
}
})
return {
_id: nextId++,
rowData
}
})
headers = hds
return objs
} else {
headers = []
return []
}
})
}
function adjustCurrentPage() {
const totalItems = objects.length
@@ -47,24 +60,33 @@
$: perPage && adjustCurrentPage()
$: data = structuredObjects
.filter(({ rowData }) =>
Object.values(rowData).some((value) =>
JSON.stringify(value).toLowerCase().includes(search.toLowerCase())
)
.filter(
({ rowData }) =>
search == undefined ||
search == '' ||
Object.values(rowData).some((value) =>
JSON.stringify(value).toLowerCase().includes(search.toLowerCase())
)
)
.sort((a, b) => {
if (!activeSorting) return 0
const valA = a.rowData[activeSorting.column]
const valB = b.rowData[activeSorting.column]
if (activeSorting.direction === 'asc') {
const isAsc = activeSorting.direction === 'asc'
if (valA == undefined || valA == null) {
return isAsc ? -1 : 1
}
if (valB == undefined || valB == null) {
return isAsc ? 1 : -1
}
if (isAsc) {
return valA > valB ? 1 : -1
} else {
return valA < valB ? 1 : -1
return valA > valB ? -1 : 1
}
})
.slice((currentPage - 1) * perPage, currentPage * perPage)
let hiddenColumns = [] as Array<string>
let activeSorting:
| {
column: string
@@ -111,13 +133,11 @@
let darkMode = false
let wrapperWidth = 0
function isSortable(key: string) {
return (
(objects?.[0]?.[key] != undefined && typeof objects[0][key] === 'string') ||
typeof objects[0][key] === 'number' ||
typeof objects[0][key] === 'boolean'
)
}
// function isSortable(key: string) {
// let value = objects?.[0]?.[key]
// let typof = typeof value
// return (value != undefined && typof === 'string') || typof === 'number' || typof === 'boolean'
// }
function convertJsonToCsv(arr: Array<Record<string, any>>): string {
try {
@@ -142,24 +162,6 @@
{pluralize(selection?.length ?? 1, 'item') + ' selected'}
</span>
{/if}
{#if hiddenColumns.length > 0}
<div class="flex flex-row gap-2 justify-center items-center mx-2">
<span class="text-xs text-gray-500 dark:text-gray-200" />
<Button
size="xs2"
color="light"
variant="border"
on:click={() => {
hiddenColumns = []
}}
startIcon={{
icon: Columns
}}
>
Display hidden columns ({pluralize(hiddenColumns?.length ?? 1, 'column')})
</Button>
</div>
{/if}
</div>
<div class="flex flex-row items-center gap-2">
<Button
@@ -224,16 +226,6 @@
}
]
if (hiddenColumns.length > 0) {
actions.push({
displayName: 'Display hidden columns',
icon: EyeIcon,
action: () => {
hiddenColumns = []
}
})
}
if (selection.length > 0) {
actions.push({
displayName: 'Clear selection',
@@ -288,65 +280,39 @@
<Cell head first={true} last={false}>
<input type="checkbox" class="!w-4 !h-4" on:change={handleSelectAllChange} />
</Cell>
{#each Object.keys(data?.[0]?.rowData ?? {}) ?? [] as key, index}
<Cell head last={index == Object.keys(objects?.[0] ?? {}).length - 1}>
{#each headers ?? [] as key, index}
<Cell head last={index == headers.length - 1}>
<div class="flex flex-row gap-1 items-center">
{key}
{#if hiddenColumns.includes(key)}
{#if activeSorting?.column === key}
<button
class="p-1 w-6 h-6 flex justify-center items-center"
on:click={() => {
hiddenColumns = hiddenColumns.filter((col) => col !== key)
activeSorting = {
column: key,
direction: activeSorting?.direction == 'asc' ? 'desc' : 'asc'
}
}}
>
<EyeOff size="16" class="hover:text-gray-600 text-gray-400 rounded-full " />
{#if activeSorting?.direction == 'asc'}
<ArrowDown size="16" />
{:else}
<ArrowUp size="16" />
{/if}
</button>
{:else}
<button
class="p-1 w-6 h-6 flex justify-center items-center"
on:click={() => {
hiddenColumns = [...hiddenColumns, key]
activeSorting = {
column: key,
direction: activeSorting?.direction == 'asc' ? 'desc' : 'asc'
}
}}
>
<EyeIcon
size="16"
class="hover:text-gray-600 text-gray-400 rounded-full "
/>
<MoveVertical size="16" class=" hover:text-gray-600 text-gray-400" />
</button>
{/if}
{#if isSortable(key)}
{#if activeSorting?.column === key}
<button
class="p-1 w-6 h-6 flex justify-center items-center"
on:click={() => {
activeSorting = {
column: key,
direction: activeSorting?.direction == 'asc' ? 'desc' : 'asc'
}
}}
disabled={hiddenColumns.includes(key)}
>
{#if activeSorting?.direction == 'asc'}
<ArrowDown size="16" />
{:else}
<ArrowUp size="16" />
{/if}
</button>
{:else}
<button
class="p-1 w-6 h-6 flex justify-center items-center"
on:click={() => {
activeSorting = {
column: key,
direction: activeSorting?.direction == 'asc' ? 'desc' : 'asc'
}
}}
disabled={hiddenColumns.includes(key)}
>
<MoveVertical size="16" class=" hover:text-gray-600 text-gray-400" />
</button>
{/if}
{/if}
</div>
</Cell>
{/each}
@@ -363,12 +329,10 @@
on:change={() => handleCheckboxChange(_id)}
/>
</Cell>
{#each Object.keys(data?.[0]?.rowData ?? {}) ?? [] as key, index}
{#each headers as key, index}
{@const value = rowData[key]}
<Cell last={index == Object.values(rowData ?? {}).length - 1}>
{#if hiddenColumns.includes(key)}
...
{:else if Array.isArray(value) && value.length === 0}
{#if Array.isArray(value) && value.length === 0}
<div />
{:else if Array.isArray(value) && typeof value?.[0] === 'string'}
<div class="flex flex-row gap-1 w-full max-w-32 flex-wrap min-w-32">