feat: "now" and "random" options added in datetime related data in insert rows tool, closes #402

This commit is contained in:
Fabio Di Stasio 2023-10-10 18:36:35 +02:00
parent c0dcf30e73
commit 9f9c63bfcc
6 changed files with 83 additions and 70 deletions

View File

@ -51,6 +51,7 @@ export default class {
{ name: 'collation', group: 'database', types: ['string'] }, { name: 'collation', group: 'database', types: ['string'] },
{ name: 'engine', group: 'database', types: ['string'] }, { name: 'engine', group: 'database', types: ['string'] },
{ name: 'now', group: 'date', types: ['string', 'datetime'] },
{ name: 'past', group: 'date', types: ['string', 'datetime'] }, { name: 'past', group: 'date', types: ['string', 'datetime'] },
{ name: 'future', group: 'date', types: ['string', 'datetime'] }, { name: 'future', group: 'date', types: ['string', 'datetime'] },
// { name: 'between', group: 'date', types: ['string'] }, // { name: 'between', group: 'date', types: ['string'] },
@ -161,7 +162,9 @@ export default class {
{ name: 'filePath', group: 'system', types: ['string'] }, { name: 'filePath', group: 'system', types: ['string'] },
{ name: 'semver', group: 'system', types: ['string'] }, { name: 'semver', group: 'system', types: ['string'] },
{ name: 'now', group: 'time', types: ['string', 'time'] },
{ name: 'recent', group: 'time', types: ['string', 'time'] }, { name: 'recent', group: 'time', types: ['string', 'time'] },
{ name: 'random', group: 'time', types: ['string', 'time'] },
{ name: 'vehicle', group: 'vehicle', types: ['string'] }, { name: 'vehicle', group: 'vehicle', types: ['string'] },
{ name: 'manufacturer', group: 'vehicle', types: ['string'] }, { name: 'manufacturer', group: 'vehicle', types: ['string'] },

View File

@ -363,8 +363,7 @@ export interface QueryBuilderObject {
offset: number; offset: number;
join: string[]; join: string[];
update: string[]; update: string[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any insert: {[key: string]: string | boolean | number }[];
insert: {[key: string]: any}[];
delete: boolean; delete: boolean;
} }

View File

@ -0,0 +1,17 @@
import { faker } from '@faker-js/faker';
import * as moment from 'moment';
export const fakerCustom = {
seed: faker.seed,
setLocale: faker.setLocale,
...faker,
date: {
now: () => moment().format('YYYY-MM-DD HH:mm:ss'),
...faker.date
},
time: {
now: () => moment().format('HH:mm:ss'),
random: () => moment(faker.date.recent()).format('HH:mm:ss'),
...faker.time
}
};

View File

@ -1,8 +1,8 @@
import { faker } from '@faker-js/faker';
import customizations from 'common/customizations'; import customizations from 'common/customizations';
import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes'; import { ARRAY, BIT, BLOB, BOOLEAN, DATE, DATETIME, FLOAT, LONG_TEXT, NUMBER, TEXT, TEXT_SEARCH } from 'common/fieldTypes';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import { InsertRowsParams } from 'common/interfaces/tableApis'; import { InsertRowsParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { sqlEscaper } from 'common/libs/sqlUtils'; import { sqlEscaper } from 'common/libs/sqlUtils';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import * as fs from 'fs'; import * as fs from 'fs';
@ -371,19 +371,19 @@ export default (connections: {[key: string]: antares.Client}) => {
let fakeValue; let fakeValue;
if (params.locale) if (params.locale)
faker.locale = params.locale; fakerCustom.locale = params.locale;
if (Object.keys(params.row[key].params).length) { if (Object.keys(params.row[key].params).length) {
Object.keys(params.row[key].params).forEach(param => { Object.keys(params.row[key].params).forEach(param => {
if (!isNaN(params.row[key].params[param])) if (!isNaN(params.row[key].params[param]))// Converts string numerics params to number
parsedParams[param] = +params.row[key].params[param]; parsedParams[param] = Number(params.row[key].params[param]);
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](parsedParams); fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method](parsedParams);
} }
else else
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
fakeValue = (faker as any)[params.row[key].group][params.row[key].method](); fakeValue = (fakerCustom as any)[params.row[key].group][params.row[key].method]();
if (typeof fakeValue === 'string') { if (typeof fakeValue === 'string') {
if (params.row[key].length) if (params.row[key].length)

View File

@ -3,7 +3,7 @@
ref="tableWrapper" ref="tableWrapper"
class="vscroll no-outline" class="vscroll no-outline"
tabindex="0" tabindex="0"
:style="{'height': resultsSize+'px'}" :style="{ 'height': resultsSize + 'px' }"
@blur="deselectRows" @blur="deselectRows"
@focus="hasFocus = true" @focus="hasFocus = true"
@keyup.delete="showDeleteConfirmModal" @keyup.delete="showDeleteConfirmModal"
@ -28,7 +28,7 @@
v-for="(result, index) in resultsWithRows" v-for="(result, index) in resultsWithRows"
:key="index" :key="index"
class="tab-item" class="tab-item"
:class="{'active': resultsetIndex === index}" :class="{ 'active': resultsetIndex === index }"
@click="selectResultset(index)" @click="selectResultset(index)"
> >
<a>{{ result.fields ? result.fields[0]?.table : '' }} ({{ result.rows.length }})</a> <a>{{ result.fields ? result.fields[0]?.table : '' }} ({{ result.rows.length }})</a>
@ -57,7 +57,7 @@
<span>{{ field.alias || field.name }}</span> <span>{{ field.alias || field.name }}</span>
<BaseIcon <BaseIcon
v-if="isSortable && currentSort === field.name || currentSort === `${field.table}.${field.name}`" v-if="isSortable && currentSort === field.name || currentSort === `${field.table}.${field.name}`"
:icon-name="currentSortDir === 'asc' ? 'mdiSortAscending':'mdiSortDescending'" :icon-name="currentSortDir === 'asc' ? 'mdiSortAscending' : 'mdiSortDescending'"
:size="18" :size="18"
class="sort-icon ml-1" class="sort-icon ml-1"
/> />
@ -90,7 +90,7 @@
:fields="fieldsObj" :fields="fieldsObj"
:key-usage="keyUsage" :key-usage="keyUsage"
:element-type="elementType" :element-type="elementType"
:class="{'selected': selectedRows.includes(row._antares_id)}" :class="{ 'selected': selectedRows.includes(row._antares_id) }"
:selected="selectedRows.includes(row._antares_id)" :selected="selectedRows.includes(row._antares_id)"
:selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null" :selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null"
@start-editing="isEditingRow = true" @start-editing="isEditingRow = true"
@ -163,7 +163,7 @@
<BaseSelect <BaseSelect
v-model="sqlExportOptions.sqlInsertDivider" v-model="sqlExportOptions.sqlInsertDivider"
class="form-select" class="form-select"
:options="[{value: 'bytes', label: 'KiB'}, {value: 'rows', label: t('database.row', 2)}]" :options="[{ value: 'bytes', label: 'KiB' }, { value: 'rows', label: t('database.row', 2) }]"
/> />
</div> </div>
</div> </div>
@ -208,9 +208,9 @@
v-model="csvExportOptions.stringDelimiter" v-model="csvExportOptions.stringDelimiter"
class="form-select" class="form-select"
:options="[ :options="[
{value: '', label: t('general.none')}, { value: '', label: t('general.none') },
{value: 'single', label: t('general.singleQuote')}, { value: 'single', label: t('general.singleQuote') },
{value: 'double', label: t('general.doubleQuote')} { value: 'double', label: t('general.doubleQuote') }
]" ]"
/> />
</div> </div>
@ -235,7 +235,10 @@
</label> </label>
</div> </div>
<div class="column col-7"> <div class="column col-7">
<label class="form-switch d-inline-block" @click.prevent="csvExportOptions.header = !csvExportOptions.header"> <label
class="form-switch d-inline-block"
@click.prevent="csvExportOptions.header = !csvExportOptions.header"
>
<input type="checkbox" :checked="csvExportOptions.header"> <input type="checkbox" :checked="csvExportOptions.header">
<i class="form-icon" /> <i class="form-icon" />
</label> </label>
@ -249,10 +252,10 @@
<script setup lang="ts"> <script setup lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import faker from '@faker-js/faker';
import { BLOB, DATE, DATETIME, LONG_TEXT, TEXT, TIME } from 'common/fieldTypes'; import { BLOB, DATE, DATETIME, LONG_TEXT, TEXT, TIME } from 'common/fieldTypes';
import { QueryResult, TableField } from 'common/interfaces/antares'; import { QueryResult, TableField } from 'common/interfaces/antares';
import { TableUpdateParams } from 'common/interfaces/tableApis'; import { TableUpdateParams } from 'common/interfaces/tableApis';
import { fakerCustom } from 'common/libs/fakerCustom';
import { jsonToSqlInsert } from 'common/libs/sqlUtils'; import { jsonToSqlInsert } from 'common/libs/sqlUtils';
import { uidGen } from 'common/libs/uidGen'; import { uidGen } from 'common/libs/uidGen';
import * as json2php from 'json2php'; import * as json2php from 'json2php';
@ -299,7 +302,7 @@ const emit = defineEmits([
'duplicate-row' 'duplicate-row'
]); ]);
const resultTable: Ref<Component & {updateWindow: () => void}> = ref(null); const resultTable: Ref<Component & { updateWindow: () => void }> = ref(null);
const tableWrapper: Ref<HTMLDivElement> = ref(null); const tableWrapper: Ref<HTMLDivElement> = ref(null);
const table: Ref<HTMLDivElement> = ref(null); const table: Ref<HTMLDivElement> = ref(null);
const resultsSize = ref(0); const resultsSize = ref(0);
@ -377,7 +380,7 @@ const keyUsage = computed(() => resultsWithRows.value.length ? resultsWithRows.v
const fieldsObj = computed(() => { const fieldsObj = computed(() => {
if (sortedResults.value.length) { if (sortedResults.value.length) {
const fieldsObj: {[key: string]: TableField} = {}; const fieldsObj: { [key: string]: TableField } = {};
for (const key in sortedResults.value[0]) { for (const key in sortedResults.value[0]) {
if (key === '_antares_id') continue; if (key === '_antares_id') continue;
@ -483,7 +486,7 @@ const resizeResults = () => {
const refreshScroller = () => resizeResults(); const refreshScroller = () => resizeResults();
const updateField = (payload: { field: string; type: string; content: any }, row: {[key: string]: any}) => { const updateField = (payload: { field: string; type: string; content: any }, row: { [key: string]: any }) => {
const orgRow: any = localResults.value.find((lr: any) => lr._antares_id === row._antares_id); const orgRow: any = localResults.value.find((lr: any) => lr._antares_id === row._antares_id);
Object.keys(orgRow).forEach(key => { // remap the row Object.keys(orgRow).forEach(key => { // remap the row
@ -598,7 +601,7 @@ const copyRow = (format: string) => {
json: contentToCopy, json: contentToCopy,
client: workspaceClient.value, client: workspaceClient.value,
fields: fieldsObj.value as { fields: fieldsObj.value as {
[key: string]: {type: string; datePrecision: number}; [key: string]: { type: string; datePrecision: number };
}, },
table: getTable(resultsetIndex.value) table: getTable(resultsetIndex.value)
}); });
@ -670,28 +673,18 @@ const fillCell = (event: { name: string; group: string; type: string }) => {
datePrecision += i === 0 ? '.S' : 'S'; datePrecision += i === 0 ? '.S' : 'S';
} }
if (event.group === 'custom') { fakeValue = (fakerCustom as any)[event.group][event.name]();
if (event.type === 'time' && event.name === 'now') if (['string', 'number'].includes(typeof fakeValue)) {
fakeValue = moment().format(`HH:mm:ss${datePrecision}`); if (typeof fakeValue === 'number')
else if (event.type === 'time' && event.name === 'random') fakeValue = String(fakeValue);
fakeValue = moment(faker.date.recent()).format(`HH:mm:ss${datePrecision}`);
else if (event.type === 'datetime' && event.name === 'now')
fakeValue = moment().format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
}
else {
fakeValue = (faker as any)[event.group][event.name]();
if (['string', 'number'].includes(typeof fakeValue)) {
if (typeof fakeValue === 'number')
fakeValue = String(fakeValue);
if (selectedCell.value.length) if (selectedCell.value.length)
fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024); fakeValue = fakeValue.substring(0, selectedCell.value.length < 1024 ? Number(selectedCell.value.length) : 1024);
}
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
} }
else if ([...DATE, ...DATETIME].includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`);
else if (TIME.includes(selectedCell.value.type))
fakeValue = moment(fakeValue).format(`HH:mm:ss${datePrecision}`);
const params = { const params = {
primary: primaryField.value?.name, primary: primaryField.value?.name,
@ -859,12 +852,12 @@ const downloadTable = (format: 'csv' | 'json' | 'sql' | 'php', table: string, po
type: format, type: format,
content: rows, content: rows,
fields: JSON.parse(JSON.stringify(fieldsObj.value)) as { fields: JSON.parse(JSON.stringify(fieldsObj.value)) as {
[key: string]: {type: string; datePrecision: number}; [key: string]: { type: string; datePrecision: number };
}, },
client: workspaceClient.value, client: workspaceClient.value,
table, table,
sqlOptions: popup ? { ...sqlExportOptions.value }: null, sqlOptions: popup ? { ...sqlExportOptions.value } : null,
csvOptions: popup ? { ...csvExportOptions.value }: null csvOptions: popup ? { ...csvExportOptions.value } : null
}); });
}; };
@ -897,7 +890,7 @@ const onKey = async (e: KeyboardEvent) => {
if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) { if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) {
e.preventDefault(); e.preventDefault();
const aviableFields= Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id const aviableFields = Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id
if (!selectedField.value) if (!selectedField.value)
selectedField.value = aviableFields[0]; selectedField.value = aviableFields[0];
@ -914,8 +907,8 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex + 1; nextIndex = selectedIndex + 1;
nextFieldIndex = selectedFieldIndex; nextFieldIndex = selectedFieldIndex;
if (nextIndex > sortedResults.value.length -1) if (nextIndex > sortedResults.value.length - 1)
nextIndex = sortedResults.value.length -1; nextIndex = sortedResults.value.length - 1;
break; break;
case 'ArrowUp': case 'ArrowUp':
@ -931,7 +924,7 @@ const onKey = async (e: KeyboardEvent) => {
nextIndex = selectedIndex; nextIndex = selectedIndex;
nextFieldIndex = selectedFieldIndex + 1; nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1) if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0; nextFieldIndex = 0;
break; break;
@ -941,7 +934,7 @@ const onKey = async (e: KeyboardEvent) => {
nextFieldIndex = selectedFieldIndex - 1; nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0) if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1; nextFieldIndex = aviableFields.length - 1;
break; break;
@ -950,11 +943,11 @@ const onKey = async (e: KeyboardEvent) => {
if (e.shiftKey) { if (e.shiftKey) {
nextFieldIndex = selectedFieldIndex - 1; nextFieldIndex = selectedFieldIndex - 1;
if (nextFieldIndex < 0) if (nextFieldIndex < 0)
nextFieldIndex = aviableFields.length -1; nextFieldIndex = aviableFields.length - 1;
} }
else { else {
nextFieldIndex = selectedFieldIndex + 1; nextFieldIndex = selectedFieldIndex + 1;
if (nextFieldIndex > aviableFields.length -1) if (nextFieldIndex > aviableFields.length - 1)
nextFieldIndex = 0; nextFieldIndex = 0;
} }
} }
@ -1049,32 +1042,33 @@ onUnmounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.vscroll { .vscroll {
height: 1000px; height: 1000px;
overflow: auto; overflow: auto;
overflow-anchor: none; overflow-anchor: none;
} }
.column-resizable { .column-resizable {
&:hover,
&:active { &:hover,
resize: horizontal; &:active {
overflow: hidden; resize: horizontal;
} overflow: hidden;
}
} }
.table-column-title { .table-column-title {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.sort-icon { .sort-icon {
font-size: 0.7rem; font-size: 0.7rem;
line-height: 1; line-height: 1;
margin-left: 0.2rem; margin-left: 0.2rem;
} }
.result-tabs { .result-tabs {
background: transparent !important; background: transparent !important;
margin: 0; margin: 0;
} }
</style> </style>

View File

@ -197,13 +197,13 @@ const fakerMethods = {
{ name: 'amount', group: 'finance' } { name: 'amount', group: 'finance' }
], ],
datetime: [ datetime: [
{ name: 'now', group: 'custom' }, { name: 'now', group: 'date' },
{ name: 'past', group: 'date' }, { name: 'past', group: 'date' },
{ name: 'future', group: 'date' } { name: 'future', group: 'date' }
], ],
time: [ time: [
{ name: 'now', group: 'custom' }, { name: 'now', group: 'time' },
{ name: 'random', group: 'custom' } { name: 'random', group: 'time' }
], ],
uuid: [ uuid: [
{ name: 'uuid', group: 'random' } { name: 'uuid', group: 'random' }