SYNC: Merge pull request #52 from dbgate/feature/group-by-timestamp

This commit is contained in:
Jan Prochazka
2026-02-18 15:44:56 +01:00
committed by Diflow
parent 991b648854
commit 53f940cd23
3 changed files with 57 additions and 6 deletions
+40 -1
View File
@@ -16,7 +16,46 @@ function getDateStringWithoutTimeZone(dateString) {
export function getFilterValueExpression(value, dataType?) {
if (value == null) return 'NULL';
if (isTypeDateTime(dataType)) return format(toDate(getDateStringWithoutTimeZone(value)), 'yyyy-MM-dd HH:mm:ss');
if (isTypeDateTime(dataType)) {
// Check for year as number (GROUP:YEAR)
if (typeof value === 'number' && Number.isInteger(value) && value >= 1000 && value <= 9999) {
return value.toString();
}
if (_isString(value)) {
// Year only
if (/^\d{4}$/.test(value)) {
return value;
}
// Year-month: validate month is in range 01-12
const yearMonthMatch = value.match(/^(\d{4})-(\d{1,2})$/);
if (yearMonthMatch) {
const month = parseInt(yearMonthMatch[2], 10);
if (month >= 1 && month <= 12) {
return value;
}
}
// Year-month-day: validate month and day
const yearMonthDayMatch = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
if (yearMonthDayMatch) {
const month = parseInt(yearMonthDayMatch[2], 10);
const day = parseInt(yearMonthDayMatch[3], 10);
// Quick validation: month 1-12, day 1-31
if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
// Construct a date to verify it's actually valid (e.g., reject 2024-02-30)
const dateStr = `${yearMonthDayMatch[1]}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const date = toDate(dateStr);
if (!isNaN(date.getTime())) {
return value;
}
}
}
}
return format(toDate(getDateStringWithoutTimeZone(value)), 'yyyy-MM-dd HH:mm:ss');
}
if (value === true) return 'TRUE';
if (value === false) return 'FALSE';
if (value.$oid) return `ObjectId("${value.$oid}")`;
@@ -292,7 +292,7 @@
schemaName: foreignKey.refSchemaName,
multiselect: true,
dataType,
onConfirm: keys => setFilter(keys.join(',')),
onConfirm: keys => setFilter(keys.map(x => getFilterValueExpression(x, dataType)).join(',')),
});
}
@@ -308,7 +308,7 @@
field: columnName || uniqueName,
formatterFunction,
dataType,
onConfirm: keys => setFilter(keys.map(x => getFilterValueExpression(x)).join(',')),
onConfirm: keys => setFilter(keys.map(x => getFilterValueExpression(x, dataType)).join(',')),
});
}
@@ -75,7 +75,9 @@
<FormProvider>
<ModalBase {...$$restProps}>
<svelte:fragment slot="header">{_t('dataGrid.chooseValue', { defaultMessage: 'Choose value from {field}', values: { field } })}</svelte:fragment>
<svelte:fragment slot="header"
>{_t('dataGrid.chooseValue', { defaultMessage: 'Choose value from {field}', values: { field } })}</svelte:fragment
>
<!-- <FormTextField name="search" label='Search' placeholder="Search" bind:value={search} /> -->
<div class="largeFormMarker">
@@ -114,7 +116,13 @@
{
fieldName: 'value',
header: _t('dataGrid.value', { defaultMessage: 'Value' }),
formatter: row => (row.value == null ? '(NULL)' : row.value?.$binary?.base64 ? base64ToHex(row.value.$binary.base64) : row.value),
formatter: row => {
if (row.value == null) return '(NULL)';
if (row.value?.$binary?.base64) return base64ToHex(row.value.$binary.base64);
if (row.value?.$decimal) return row.value.$decimal;
if (row.value?.$bigint) return row.value.$bigint;
return row.value;
},
},
]}
>
@@ -148,7 +156,11 @@
}}
/>
{/if}
<FormStyledButton type="button" value={_t('common.close', { defaultMessage: 'Close' })} on:click={closeCurrentModal} />
<FormStyledButton
type="button"
value={_t('common.close', { defaultMessage: 'Close' })}
on:click={closeCurrentModal}
/>
</svelte:fragment>
</ModalBase>
</FormProvider>