mirror of https://github.com/nocodb/nocodb
Daniel Spaude
2 years ago
91 changed files with 10226 additions and 526 deletions
@ -0,0 +1,58 @@
|
||||
<script lang="ts" setup> |
||||
import { Icon } from '@iconify/vue' |
||||
import InfiniteLoading from 'v3-infinite-loading' |
||||
import { emojiIcons } from '#imports' |
||||
|
||||
const emit = defineEmits(['selectIcon']) |
||||
let search = $ref('') |
||||
|
||||
// keep a variable to load icons with infinite scroll |
||||
// set initial value to 60 to load first 60 icons (index - `0 - 59`) |
||||
// and next value will be 120 and shows first 120 icons ( index - `0 - 129`) |
||||
let toIndex = $ref(60) |
||||
|
||||
const filteredIcons = computed(() => { |
||||
return emojiIcons.filter((icon) => !search || icon.toLowerCase().includes(search.toLowerCase())).slice(0, toIndex) |
||||
}) |
||||
|
||||
const load = () => { |
||||
// increment `toIndex` to include next set of icons |
||||
toIndex += Math.min(filteredIcons.value.length, toIndex + 60) |
||||
if (toIndex > filteredIcons.value.length) { |
||||
toIndex = filteredIcons.value.length |
||||
} |
||||
} |
||||
|
||||
const selectIcon = (icon: string) => { |
||||
search = '' |
||||
emit('selectIcon', `emojione:${icon}`) |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="p-1 w-[280px] h-[280px] flex flex-col gap-1 justify-start nc-emoji" data-testid="nc-emoji-container"> |
||||
<div @click.stop> |
||||
<input |
||||
v-model="search" |
||||
data-testid="nc-emoji-filter" |
||||
class="p-1 text-xs border-1 w-full overflow-y-auto" |
||||
placeholder="Search" |
||||
@input="toIndex = 60" |
||||
/> |
||||
</div> |
||||
<div class="flex gap-1 flex-wrap w-full flex-shrink overflow-y-auto scrollbar-thin-dull"> |
||||
<div v-for="icon of filteredIcons" :key="icon" @click="selectIcon(icon)"> |
||||
<span class="cursor-pointer nc-emoji-item"> |
||||
<Icon class="text-xl iconify" :icon="`emojione:${icon}`"></Icon> |
||||
</span> |
||||
</div> |
||||
<InfiniteLoading @infinite="load"><span /></InfiniteLoading> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style scoped> |
||||
.nc-emoji-item { |
||||
@apply hover:(bg-primary bg-opacity-10) active:(bg-primary !bg-opacity-20) rounded-md w-[38px] h-[38px] block flex items-center justify-center; |
||||
} |
||||
</style> |
@ -0,0 +1,22 @@
|
||||
<script lang="ts" setup> |
||||
import { Icon as IcIcon } from '@iconify/vue' |
||||
import type { TableType } from 'nocodb-sdk' |
||||
|
||||
const { meta: tableMeta } = defineProps<{ |
||||
meta: TableType |
||||
}>() |
||||
</script> |
||||
|
||||
<template> |
||||
<IcIcon |
||||
v-if="tableMeta.meta?.icon" |
||||
:data-testid="`nc-icon-${tableMeta.meta?.icon}`" |
||||
class="text-lg" |
||||
:icon="tableMeta.meta?.icon" |
||||
/> |
||||
|
||||
<MdiEyeCircleOutline v-else-if="tableMeta?.type === 'view'" class="w-5" /> |
||||
<MdiTableLarge v-else class="w-5" /> |
||||
</template> |
||||
|
||||
<style scoped></style> |
@ -0,0 +1,26 @@
|
||||
<script lang="ts" setup> |
||||
import { Icon as IcIcon } from '@iconify/vue' |
||||
import type { TableType } from 'nocodb-sdk' |
||||
import { viewIcons } from '#imports' |
||||
|
||||
const { meta: viewMeta } = defineProps<{ |
||||
meta: TableType |
||||
}>() |
||||
</script> |
||||
|
||||
<template> |
||||
<IcIcon |
||||
v-if="viewMeta?.meta?.icon" |
||||
:data-testid="`nc-icon-${viewMeta?.meta?.icon}`" |
||||
class="text-[16px]" |
||||
:icon="viewMeta?.meta?.icon" |
||||
/> |
||||
<component |
||||
:is="viewIcons[viewMeta.type]?.icon" |
||||
v-else |
||||
class="nc-view-icon group-hover" |
||||
:style="{ color: viewIcons[viewMeta.type]?.color }" |
||||
/> |
||||
</template> |
||||
|
||||
<style scoped></style> |
@ -0,0 +1,38 @@
|
||||
<script setup lang="ts"> |
||||
import { dateFormats, timeFormats, useVModel } from '#imports' |
||||
|
||||
const props = defineProps<{ |
||||
value: any |
||||
}>() |
||||
|
||||
const emit = defineEmits(['update:value']) |
||||
|
||||
const vModel = useVModel(props, 'value', emit) |
||||
|
||||
if (!vModel.value.meta?.date_format) { |
||||
if (!vModel.value.meta) vModel.value.meta = {} |
||||
vModel.value.meta.date_format = dateFormats[0] |
||||
} |
||||
|
||||
if (!vModel.value.meta?.time_format) { |
||||
if (!vModel.value.meta) vModel.value.meta = {} |
||||
vModel.value.meta.time_format = timeFormats[0] |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<a-form-item label="Date Format"> |
||||
<a-select v-model:value="vModel.meta.date_format" class="nc-date-select" dropdown-class-name="nc-dropdown-date-format"> |
||||
<a-select-option v-for="(format, i) of dateFormats" :key="i" :value="format"> |
||||
{{ format }} |
||||
</a-select-option> |
||||
</a-select> |
||||
</a-form-item> |
||||
<a-form-item label="Time Format"> |
||||
<a-select v-model:value="vModel.meta.time_format" class="nc-time-select" dropdown-class-name="nc-dropdown-time-format"> |
||||
<a-select-option v-for="(format, i) of timeFormats" :key="i" :value="format"> |
||||
{{ format }} |
||||
</a-select-option> |
||||
</a-select> |
||||
</a-form-item> |
||||
</template> |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
// Snowflake queries
|
||||
|
||||
const sfQueries = {}; |
||||
|
||||
export default sfQueries; |
@ -0,0 +1,137 @@
|
||||
export function convertUnits( |
||||
unit: string, |
||||
type: 'mysql' | 'mssql' | 'pg' | 'sqlite' |
||||
) { |
||||
switch (unit) { |
||||
case 'milliseconds': |
||||
case 'ms': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
return 'millisecond'; |
||||
case 'mysql': |
||||
// MySQL doesn't support millisecond
|
||||
// hence change from MICROSECOND to millisecond manually
|
||||
return 'MICROSECOND'; |
||||
case 'pg': |
||||
case 'sqlite': |
||||
return 'milliseconds'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'seconds': |
||||
case 's': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'second'; |
||||
case 'mysql': |
||||
return 'SECOND'; |
||||
case 'sqlite': |
||||
return 'seconds'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'minutes': |
||||
case 'm': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'minute'; |
||||
case 'mysql': |
||||
return 'MINUTE'; |
||||
case 'sqlite': |
||||
return 'minutes'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'hours': |
||||
case 'h': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'hour'; |
||||
case 'mysql': |
||||
return 'HOUR'; |
||||
case 'sqlite': |
||||
return 'hours'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'days': |
||||
case 'd': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'day'; |
||||
case 'mysql': |
||||
return 'DAY'; |
||||
case 'sqlite': |
||||
return 'days'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'weeks': |
||||
case 'w': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'week'; |
||||
case 'mysql': |
||||
return 'WEEK'; |
||||
case 'sqlite': |
||||
return 'weeks'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'months': |
||||
case 'M': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'month'; |
||||
case 'mysql': |
||||
return 'MONTH'; |
||||
case 'sqlite': |
||||
return 'months'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'quarters': |
||||
case 'Q': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'quarter'; |
||||
case 'mysql': |
||||
return 'QUARTER'; |
||||
case 'sqlite': |
||||
return 'quarters'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
case 'years': |
||||
case 'y': { |
||||
switch (type) { |
||||
case 'mssql': |
||||
case 'pg': |
||||
return 'year'; |
||||
case 'mysql': |
||||
return 'YEAR'; |
||||
case 'sqlite': |
||||
return 'years'; |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
||||
default: |
||||
return unit; |
||||
} |
||||
} |
@ -0,0 +1,975 @@
|
||||
import BaseModelXcMeta from './BaseModelXcMeta'; |
||||
|
||||
class ModelXcMetaSnowflake extends BaseModelXcMeta { |
||||
/** |
||||
* @param dir |
||||
* @param filename |
||||
* @param ctx |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare() { |
||||
const data: any = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data.tn = this.ctx.tn; |
||||
data.dbType = this.ctx.dbType; |
||||
|
||||
/* for complex code provide a func and args - do derivation within the func cbk */ |
||||
data.columns = { |
||||
func: this._renderXcColumns.bind(this), |
||||
args: { |
||||
tn: this.ctx.tn, |
||||
columns: this.ctx.columns, |
||||
relations: this.ctx.relations, |
||||
}, |
||||
}; |
||||
|
||||
/* for complex code provide a func and args - do derivation within the func cbk */ |
||||
data.hasMany = { |
||||
func: this._renderXcHasMany.bind(this), |
||||
args: { |
||||
tn: this.ctx.tn, |
||||
columns: this.ctx.columns, |
||||
hasMany: this.ctx.hasMany, |
||||
}, |
||||
}; |
||||
|
||||
/* for complex code provide a func and args - do derivation within the func cbk */ |
||||
data.belongsTo = { |
||||
func: this._renderXcBelongsTo.bind(this), |
||||
args: { |
||||
tn: this.ctx.tn, |
||||
columns: this.ctx.columns, |
||||
belongsTo: this.ctx.belongsTo, |
||||
}, |
||||
}; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
_renderXcHasMany(args) { |
||||
return JSON.stringify(args.hasMany); |
||||
} |
||||
|
||||
_renderXcBelongsTo(args) { |
||||
return JSON.stringify(args.belongsTo); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*/ |
||||
_renderXcColumns(args) { |
||||
let str = '[\r\n'; |
||||
|
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
str += `{\r\n`; |
||||
str += `cn: '${args.columns[i].cn}',\r\n`; |
||||
str += `type: '${this._getAbstractType(args.columns[i])}',\r\n`; |
||||
str += `dt: '${args.columns[i].dt}',\r\n`; |
||||
if (args.columns[i].rqd) str += `rqd: ${args.columns[i].rqd},\r\n`; |
||||
|
||||
if (args.columns[i].cdf) { |
||||
str += `default: "${args.columns[i].cdf}",\r\n`; |
||||
str += `columnDefault: "${args.columns[i].cdf}",\r\n`; |
||||
} |
||||
|
||||
if (args.columns[i].un) str += `un: ${args.columns[i].un},\r\n`; |
||||
|
||||
if (args.columns[i].pk) str += `pk: ${args.columns[i].pk},\r\n`; |
||||
|
||||
if (args.columns[i].ai) str += `ai: ${args.columns[i].ai},\r\n`; |
||||
|
||||
if (args.columns[i].dtxp) str += `dtxp: "${args.columns[i].dtxp}",\r\n`; |
||||
|
||||
if (args.columns[i].dtxs) str += `dtxs: ${args.columns[i].dtxs},\r\n`; |
||||
|
||||
str += `validate: {
|
||||
func: [], |
||||
args: [], |
||||
msg: [] |
||||
},`;
|
||||
str += `},\r\n`; |
||||
} |
||||
|
||||
str += ']\r\n'; |
||||
|
||||
return str; |
||||
} |
||||
|
||||
_getAbstractType(column) { |
||||
let str = ''; |
||||
switch (column.dt) { |
||||
case 'int': |
||||
str = 'integer'; |
||||
break; |
||||
case 'integer': |
||||
str = 'integer'; |
||||
break; |
||||
case 'bigint': |
||||
str = 'bigInteger'; |
||||
break; |
||||
case 'bigserial': |
||||
str = 'bigserial'; |
||||
break; |
||||
case 'char': |
||||
str = 'string'; |
||||
break; |
||||
case 'int2': |
||||
str = 'integer'; |
||||
break; |
||||
case 'int4': |
||||
str = 'integer'; |
||||
break; |
||||
case 'int8': |
||||
str = 'integer'; |
||||
break; |
||||
case 'int4range': |
||||
str = 'int4range'; |
||||
break; |
||||
case 'int8range': |
||||
str = 'int8range'; |
||||
break; |
||||
case 'serial': |
||||
str = 'serial'; |
||||
break; |
||||
case 'serial2': |
||||
str = 'serial2'; |
||||
break; |
||||
case 'serial8': |
||||
str = 'serial8'; |
||||
break; |
||||
case 'character': |
||||
str = 'string'; |
||||
break; |
||||
case 'bit': |
||||
str = 'bit'; |
||||
break; |
||||
case 'bool': |
||||
str = 'boolean'; |
||||
break; |
||||
case 'boolean': |
||||
str = 'boolean'; |
||||
break; |
||||
case 'date': |
||||
str = 'date'; |
||||
break; |
||||
case 'double precision': |
||||
str = 'double'; |
||||
break; |
||||
case 'event_trigger': |
||||
str = 'event_trigger'; |
||||
break; |
||||
case 'fdw_handler': |
||||
str = 'fdw_handler'; |
||||
break; |
||||
case 'float4': |
||||
str = 'float'; |
||||
break; |
||||
case 'float8': |
||||
str = 'float'; |
||||
break; |
||||
case 'uuid': |
||||
str = 'uuid'; |
||||
break; |
||||
case 'smallint': |
||||
str = 'integer'; |
||||
break; |
||||
case 'smallserial': |
||||
str = 'smallserial'; |
||||
break; |
||||
case 'character varying': |
||||
str = 'string'; |
||||
break; |
||||
case 'text': |
||||
str = 'text'; |
||||
break; |
||||
case 'real': |
||||
str = 'float'; |
||||
break; |
||||
case 'time': |
||||
str = 'time'; |
||||
break; |
||||
case 'time without time zone': |
||||
str = 'time'; |
||||
break; |
||||
case 'timestamp': |
||||
str = 'timestamp'; |
||||
break; |
||||
case 'timestamp without time zone': |
||||
str = 'timestamp'; |
||||
break; |
||||
case 'timestamptz': |
||||
str = 'timestampt'; |
||||
break; |
||||
case 'timestamp with time zone': |
||||
str = 'timestamp'; |
||||
break; |
||||
case 'timetz': |
||||
str = 'time'; |
||||
break; |
||||
case 'time with time zone': |
||||
str = 'time'; |
||||
break; |
||||
case 'daterange': |
||||
str = 'daterange'; |
||||
break; |
||||
case 'json': |
||||
str = 'json'; |
||||
break; |
||||
case 'jsonb': |
||||
str = 'jsonb'; |
||||
break; |
||||
case 'gtsvector': |
||||
str = 'gtsvector'; |
||||
break; |
||||
case 'index_am_handler': |
||||
str = 'index_am_handler'; |
||||
break; |
||||
case 'anyenum': |
||||
str = 'enum'; |
||||
break; |
||||
case 'anynonarray': |
||||
str = 'anynonarray'; |
||||
break; |
||||
case 'anyrange': |
||||
str = 'anyrange'; |
||||
break; |
||||
case 'box': |
||||
str = 'box'; |
||||
break; |
||||
case 'bpchar': |
||||
str = 'bpchar'; |
||||
break; |
||||
case 'bytea': |
||||
str = 'bytea'; |
||||
break; |
||||
case 'cid': |
||||
str = 'cid'; |
||||
break; |
||||
case 'cidr': |
||||
str = 'cidr'; |
||||
break; |
||||
case 'circle': |
||||
str = 'circle'; |
||||
break; |
||||
case 'cstring': |
||||
str = 'cstring'; |
||||
break; |
||||
case 'inet': |
||||
str = 'inet'; |
||||
break; |
||||
case 'internal': |
||||
str = 'internal'; |
||||
break; |
||||
case 'interval': |
||||
str = 'interval'; |
||||
break; |
||||
case 'language_handler': |
||||
str = 'language_handler'; |
||||
break; |
||||
case 'line': |
||||
str = 'line'; |
||||
break; |
||||
case 'lsec': |
||||
str = 'lsec'; |
||||
break; |
||||
case 'macaddr': |
||||
str = 'macaddr'; |
||||
break; |
||||
case 'money': |
||||
str = 'float'; |
||||
break; |
||||
case 'name': |
||||
str = 'name'; |
||||
break; |
||||
case 'numeric': |
||||
str = 'numeric'; |
||||
break; |
||||
case 'numrange': |
||||
str = 'numrange'; |
||||
break; |
||||
case 'oid': |
||||
str = 'oid'; |
||||
break; |
||||
case 'opaque': |
||||
str = 'opaque'; |
||||
break; |
||||
case 'path': |
||||
str = 'path'; |
||||
break; |
||||
case 'pg_ddl_command': |
||||
str = 'pg_ddl_command'; |
||||
break; |
||||
case 'pg_lsn': |
||||
str = 'pg_lsn'; |
||||
break; |
||||
case 'pg_node_tree': |
||||
str = 'pg_node_tree'; |
||||
break; |
||||
case 'point': |
||||
str = 'point'; |
||||
break; |
||||
case 'polygon': |
||||
str = 'polygon'; |
||||
break; |
||||
case 'record': |
||||
str = 'record'; |
||||
break; |
||||
case 'refcursor': |
||||
str = 'refcursor'; |
||||
break; |
||||
case 'regclass': |
||||
str = 'regclass'; |
||||
break; |
||||
case 'regconfig': |
||||
str = 'regconfig'; |
||||
break; |
||||
case 'regdictionary': |
||||
str = 'regdictionary'; |
||||
break; |
||||
case 'regnamespace': |
||||
str = 'regnamespace'; |
||||
break; |
||||
case 'regoper': |
||||
str = 'regoper'; |
||||
break; |
||||
case 'regoperator': |
||||
str = 'regoperator'; |
||||
break; |
||||
case 'regproc': |
||||
str = 'regproc'; |
||||
break; |
||||
case 'regpreocedure': |
||||
str = 'regpreocedure'; |
||||
break; |
||||
case 'regrole': |
||||
str = 'regrole'; |
||||
break; |
||||
case 'regtype': |
||||
str = 'regtype'; |
||||
break; |
||||
case 'reltime': |
||||
str = 'reltime'; |
||||
break; |
||||
case 'smgr': |
||||
str = 'smgr'; |
||||
break; |
||||
case 'tid': |
||||
str = 'tid'; |
||||
break; |
||||
case 'tinterval': |
||||
str = 'tinterval'; |
||||
break; |
||||
case 'trigger': |
||||
str = 'trigger'; |
||||
break; |
||||
case 'tsm_handler': |
||||
str = 'tsm_handler'; |
||||
break; |
||||
case 'tsquery': |
||||
str = 'tsquery'; |
||||
break; |
||||
case 'tsrange': |
||||
str = 'tsrange'; |
||||
break; |
||||
case 'tstzrange': |
||||
str = 'tstzrange'; |
||||
break; |
||||
case 'tsvector': |
||||
str = 'tsvector'; |
||||
break; |
||||
case 'txid_snapshot': |
||||
str = 'txid_snapshot'; |
||||
break; |
||||
case 'unknown': |
||||
str = 'unknown'; |
||||
break; |
||||
case 'void': |
||||
str = 'void'; |
||||
break; |
||||
case 'xid': |
||||
str = 'xid'; |
||||
break; |
||||
case 'xml': |
||||
str = 'xml'; |
||||
break; |
||||
default: |
||||
str += `"${column.dt}"`; |
||||
break; |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
getUIDataType(col): any { |
||||
switch (this.getAbstractType(col)) { |
||||
case 'integer': |
||||
return 'Number'; |
||||
case 'boolean': |
||||
return 'Checkbox'; |
||||
case 'float': |
||||
return 'Decimal'; |
||||
case 'date': |
||||
return 'Date'; |
||||
case 'datetime': |
||||
return 'DateTime'; |
||||
case 'time': |
||||
return 'Time'; |
||||
case 'year': |
||||
return 'Year'; |
||||
case 'string': |
||||
return 'SingleLineText'; |
||||
case 'text': |
||||
return 'LongText'; |
||||
case 'enum': |
||||
return 'SingleSelect'; |
||||
case 'set': |
||||
return 'MultiSelect'; |
||||
case 'json': |
||||
return 'JSON'; |
||||
case 'blob': |
||||
return 'LongText'; |
||||
case 'geometry': |
||||
return 'Geometry'; |
||||
default: |
||||
return 'SpecificDBType'; |
||||
} |
||||
} |
||||
|
||||
getAbstractType(col): any { |
||||
const dt = col.dt.toLowerCase(); |
||||
switch (dt) { |
||||
case 'anyenum': |
||||
return 'enum'; |
||||
case 'anynonarray': |
||||
case 'anyrange': |
||||
return dt; |
||||
|
||||
case 'bit': |
||||
return 'integer'; |
||||
case 'bigint': |
||||
case 'bigserial': |
||||
return 'integer'; |
||||
|
||||
case 'bool': |
||||
return 'boolean'; |
||||
|
||||
case 'bpchar': |
||||
case 'bytea': |
||||
return dt; |
||||
case 'char': |
||||
case 'character': |
||||
case 'character varying': |
||||
return 'string'; |
||||
|
||||
case 'cid': |
||||
case 'cidr': |
||||
case 'cstring': |
||||
return dt; |
||||
|
||||
case 'date': |
||||
return 'date'; |
||||
case 'daterange': |
||||
return 'string'; |
||||
case 'double precision': |
||||
return 'string'; |
||||
|
||||
case 'event_trigger': |
||||
case 'fdw_handler': |
||||
return dt; |
||||
|
||||
case 'float4': |
||||
case 'float8': |
||||
return 'float'; |
||||
|
||||
case 'gtsvector': |
||||
case 'index_am_handler': |
||||
case 'inet': |
||||
return dt; |
||||
|
||||
case 'int': |
||||
case 'int2': |
||||
case 'int4': |
||||
case 'int8': |
||||
case 'integer': |
||||
return 'integer'; |
||||
case 'int4range': |
||||
case 'int8range': |
||||
case 'internal': |
||||
case 'interval': |
||||
return 'string'; |
||||
case 'json': |
||||
case 'jsonb': |
||||
return 'json'; |
||||
|
||||
case 'language_handler': |
||||
case 'lsec': |
||||
case 'macaddr': |
||||
case 'money': |
||||
case 'name': |
||||
case 'numeric': |
||||
case 'numrange': |
||||
case 'oid': |
||||
case 'opaque': |
||||
case 'path': |
||||
case 'pg_ddl_command': |
||||
case 'pg_lsn': |
||||
case 'pg_node_tree': |
||||
return dt; |
||||
case 'real': |
||||
return 'float'; |
||||
case 'record': |
||||
case 'refcursor': |
||||
case 'regclass': |
||||
case 'regconfig': |
||||
case 'regdictionary': |
||||
case 'regnamespace': |
||||
case 'regoper': |
||||
case 'regoperator': |
||||
case 'regproc': |
||||
case 'regpreocedure': |
||||
case 'regrole': |
||||
case 'regtype': |
||||
case 'reltime': |
||||
return dt; |
||||
case 'serial': |
||||
case 'serial2': |
||||
case 'serial8': |
||||
case 'smallint': |
||||
case 'smallserial': |
||||
return 'integer'; |
||||
case 'smgr': |
||||
return dt; |
||||
case 'text': |
||||
return 'text'; |
||||
case 'tid': |
||||
return dt; |
||||
case 'time': |
||||
case 'time without time zone': |
||||
return 'time'; |
||||
case 'timestamp': |
||||
case 'timestamp without time zone': |
||||
case 'timestamptz': |
||||
case 'timestamp with time zone': |
||||
return 'datetime'; |
||||
case 'timetz': |
||||
case 'time with time zone': |
||||
return 'time'; |
||||
|
||||
case 'tinterval': |
||||
case 'trigger': |
||||
case 'tsm_handler': |
||||
case 'tsquery': |
||||
case 'tsrange': |
||||
case 'tstzrange': |
||||
case 'tsvector': |
||||
case 'txid_snapshot': |
||||
case 'unknown': |
||||
case 'void': |
||||
case 'xid': |
||||
case 'xml': |
||||
return dt; |
||||
|
||||
case 'tinyint': |
||||
case 'mediumint': |
||||
return 'integer'; |
||||
|
||||
case 'float': |
||||
case 'decimal': |
||||
case 'double': |
||||
return 'float'; |
||||
case 'boolean': |
||||
return 'boolean'; |
||||
case 'datetime': |
||||
return 'datetime'; |
||||
|
||||
case 'uuid': |
||||
case 'year': |
||||
case 'varchar': |
||||
case 'nchar': |
||||
return 'string'; |
||||
|
||||
case 'tinytext': |
||||
case 'mediumtext': |
||||
case 'longtext': |
||||
return 'text'; |
||||
|
||||
case 'binary': |
||||
case 'varbinary': |
||||
return 'text'; |
||||
|
||||
case 'blob': |
||||
case 'tinyblob': |
||||
case 'mediumblob': |
||||
case 'longblob': |
||||
return 'blob'; |
||||
case 'enum': |
||||
return 'enum'; |
||||
case 'set': |
||||
return 'set'; |
||||
|
||||
case 'line': |
||||
case 'point': |
||||
case 'polygon': |
||||
case 'circle': |
||||
case 'box': |
||||
case 'geometry': |
||||
case 'linestring': |
||||
case 'multipoint': |
||||
case 'multilinestring': |
||||
case 'multipolygon': |
||||
return 'geometry'; |
||||
} |
||||
} |
||||
|
||||
_sequelizeGetType(column) { |
||||
let str = ''; |
||||
switch (column.dt) { |
||||
case 'int': |
||||
str += `DataTypes.INTEGER(${column.dtxp})`; |
||||
if (column.un) str += `.UNSIGNED`; |
||||
break; |
||||
case 'tinyint': |
||||
str += `DataTypes.INTEGER(${column.dtxp})`; |
||||
if (column.un) str += `.UNSIGNED`; |
||||
|
||||
break; |
||||
case 'smallint': |
||||
str += `DataTypes.INTEGER(${column.dtxp})`; |
||||
if (column.un) str += `.UNSIGNED`; |
||||
|
||||
break; |
||||
case 'mediumint': |
||||
str += `DataTypes.INTEGER(${column.dtxp})`; |
||||
if (column.un) str += `.UNSIGNED`; |
||||
|
||||
break; |
||||
case 'bigint': |
||||
str += `DataTypes.BIGINT`; |
||||
if (column.un) str += `.UNSIGNED`; |
||||
|
||||
break; |
||||
case 'float': |
||||
str += `DataTypes.FLOAT`; |
||||
break; |
||||
case 'decimal': |
||||
str += `DataTypes.DECIMAL`; |
||||
break; |
||||
case 'double': |
||||
str += `"DOUBLE(${column.dtxp},${column.ns})"`; |
||||
break; |
||||
case 'real': |
||||
str += `DataTypes.FLOAT`; |
||||
break; |
||||
case 'bit': |
||||
str += `DataTypes.BOOLEAN`; |
||||
break; |
||||
case 'boolean': |
||||
str += `DataTypes.STRING(45)`; |
||||
break; |
||||
case 'serial': |
||||
str += `DataTypes.BIGINT`; |
||||
break; |
||||
case 'date': |
||||
str += `DataTypes.DATEONLY`; |
||||
break; |
||||
case 'datetime': |
||||
str += `DataTypes.DATE`; |
||||
break; |
||||
case 'timestamp': |
||||
str += `DataTypes.DATE`; |
||||
break; |
||||
case 'time': |
||||
str += `DataTypes.TIME`; |
||||
break; |
||||
case 'year': |
||||
str += `"YEAR"`; |
||||
break; |
||||
case 'char': |
||||
str += `DataTypes.CHAR(${column.dtxp})`; |
||||
break; |
||||
case 'varchar': |
||||
str += `DataTypes.STRING(${column.dtxp})`; |
||||
break; |
||||
case 'nchar': |
||||
str += `DataTypes.CHAR(${column.dtxp})`; |
||||
break; |
||||
case 'text': |
||||
str += `DataTypes.TEXT`; |
||||
break; |
||||
case 'tinytext': |
||||
str += `DataTypes.TEXT`; |
||||
break; |
||||
case 'mediumtext': |
||||
str += `DataTypes.TEXT`; |
||||
break; |
||||
case 'longtext': |
||||
str += `DataTypes.TEXT`; |
||||
break; |
||||
case 'binary': |
||||
str += `"BINARY(${column.dtxp})"`; |
||||
break; |
||||
case 'varbinary': |
||||
str += `"VARBINARY(${column.dtxp})"`; |
||||
break; |
||||
case 'blob': |
||||
str += `"BLOB"`; |
||||
break; |
||||
case 'tinyblob': |
||||
str += `"TINYBLOB"`; |
||||
break; |
||||
case 'mediumblob': |
||||
str += `"MEDIUMBLOB"`; |
||||
break; |
||||
case 'longblob': |
||||
str += `"LONGBLOB"`; |
||||
break; |
||||
case 'enum': |
||||
str += `DataTypes.ENUM(${column.dtxp})`; |
||||
break; |
||||
case 'set': |
||||
str += `"SET(${column.dtxp})"`; |
||||
break; |
||||
case 'geometry': |
||||
str += `DataTypes.GEOMETRY`; |
||||
break; |
||||
case 'point': |
||||
str += `"POINT"`; |
||||
break; |
||||
case 'linestring': |
||||
str += `"LINESTRING"`; |
||||
break; |
||||
case 'polygon': |
||||
str += `"POLYGON"`; |
||||
break; |
||||
case 'multipoint': |
||||
str += `"MULTIPOINT"`; |
||||
break; |
||||
case 'multilinestring': |
||||
str += `"MULTILINESTRING"`; |
||||
break; |
||||
case 'multipolygon': |
||||
str += `"MULTIPOLYGON"`; |
||||
break; |
||||
case 'json': |
||||
str += `DataTypes.JSON`; |
||||
break; |
||||
default: |
||||
str += `"${column.dt}"`; |
||||
break; |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
_sequelizeGetDefault(column) { |
||||
let str = ''; |
||||
switch (column.dt) { |
||||
case 'int': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'tinyint': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'smallint': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'mediumint': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'bigint': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'float': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'decimal': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'double': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'real': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'bit': |
||||
str += column.cdf ? column.cdf.split('b')[1] : column.cdf; |
||||
break; |
||||
case 'boolean': |
||||
str += column.cdf; |
||||
break; |
||||
case 'serial': |
||||
str += column.cdf; |
||||
break; |
||||
case 'date': |
||||
str += `sequelize.literal('${column.cdf_sequelize}')`; |
||||
break; |
||||
case 'datetime': |
||||
str += `sequelize.literal('${column.cdf_sequelize}')`; |
||||
break; |
||||
case 'timestamp': |
||||
str += `sequelize.literal('${column.cdf_sequelize}')`; |
||||
break; |
||||
case 'time': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'year': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'char': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'varchar': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'nchar': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'text': |
||||
str += column.cdf; |
||||
break; |
||||
case 'tinytext': |
||||
str += column.cdf; |
||||
break; |
||||
case 'mediumtext': |
||||
str += column.cdf; |
||||
break; |
||||
case 'longtext': |
||||
str += column.cdf; |
||||
break; |
||||
case 'binary': |
||||
str += column.cdf; |
||||
break; |
||||
case 'varbinary': |
||||
str += column.cdf; |
||||
break; |
||||
case 'blob': |
||||
str += column.cdf; |
||||
break; |
||||
case 'tinyblob': |
||||
str += column.cdf; |
||||
break; |
||||
case 'mediumblob': |
||||
str += column.cdf; |
||||
break; |
||||
case 'longblob': |
||||
str += column.cdf; |
||||
break; |
||||
case 'enum': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'set': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'geometry': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'point': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'linestring': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'polygon': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'multipoint': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'multilinestring': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'multipolygon': |
||||
str += `'${column.cdf}'`; |
||||
break; |
||||
case 'json': |
||||
str += column.cdf; |
||||
break; |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
/* getXcColumnsObject(args) { |
||||
const columnsArr = []; |
||||
|
||||
for (const column of args.columns) { |
||||
const columnObj = { |
||||
validate: { |
||||
func: [], |
||||
args: [], |
||||
msg: [] |
||||
}, |
||||
cn: column.cn, |
||||
_cn: column._cn || column.cn, |
||||
type: this._getAbstractType(column), |
||||
dt: column.dt, |
||||
uidt: column.uidt || this._getUIDataType(column), |
||||
uip: column.uip, |
||||
uicn: column.uicn, |
||||
...column |
||||
}; |
||||
|
||||
if (column.rqd) { |
||||
columnObj.rqd = column.rqd; |
||||
} |
||||
|
||||
if (column.cdf) { |
||||
columnObj.default = column.cdf; |
||||
columnObj.columnDefault = column.cdf; |
||||
} |
||||
|
||||
if (column.un) { |
||||
columnObj.un = column.un; |
||||
} |
||||
|
||||
if (column.pk) { |
||||
columnObj.pk = column.pk; |
||||
} |
||||
|
||||
if (column.ai) { |
||||
columnObj.ai = column.ai; |
||||
} |
||||
|
||||
if (column.dtxp) { |
||||
columnObj.dtxp = column.dtxp; |
||||
} |
||||
|
||||
if (column.dtxs) { |
||||
columnObj.dtxs = column.dtxs; |
||||
} |
||||
|
||||
columnsArr.push(columnObj); |
||||
} |
||||
|
||||
this.mapDefaultPrimaryValue(columnsArr); |
||||
return columnsArr; |
||||
}*/ |
||||
|
||||
/* getObject() { |
||||
return { |
||||
tn: this.ctx.tn, |
||||
_tn: this.ctx._tn, |
||||
columns: this.getXcColumnsObject(this.ctx), |
||||
pks: [], |
||||
hasMany: this.ctx.hasMany, |
||||
belongsTo: this.ctx.belongsTo, |
||||
dbType: this.ctx.dbType, |
||||
type: this.ctx.type, |
||||
} |
||||
|
||||
}*/ |
||||
} |
||||
|
||||
export default ModelXcMetaSnowflake; |
@ -0,0 +1,75 @@
|
||||
import dayjs from 'dayjs'; |
||||
|
||||
export const dateFormats = [ |
||||
'DD-MM-YYYY', |
||||
'MM-DD-YYYY', |
||||
'YYYY-MM-DD', |
||||
'DD/MM/YYYY', |
||||
'MM/DD/YYYY', |
||||
'YYYY/MM/DD', |
||||
'DD MM YYYY', |
||||
'MM DD YYYY', |
||||
'YYYY MM DD', |
||||
]; |
||||
|
||||
export function validateDateFormat(v: string) { |
||||
return dateFormats.includes(v); |
||||
} |
||||
|
||||
export function validateDateWithUnknownFormat(v: string) { |
||||
for (const format of dateFormats) { |
||||
if (dayjs(v, format, true).isValid() as any) { |
||||
return true; |
||||
} |
||||
for (const timeFormat of ['HH:mm', 'HH:mm:ss', 'HH:mm:ss.SSS']) { |
||||
if (dayjs(v, `${format} ${timeFormat}`, true).isValid() as any) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
export function getDateFormat(v: string) { |
||||
for (const format of dateFormats) { |
||||
if (dayjs(v, format, true).isValid()) { |
||||
return format; |
||||
} |
||||
} |
||||
return 'YYYY/MM/DD'; |
||||
} |
||||
|
||||
export function getDateTimeFormat(v: string) { |
||||
for (const format of dateFormats) { |
||||
for (const timeFormat of ['HH:mm', 'HH:mm:ss', 'HH:mm:ss.SSS']) { |
||||
const dateTimeFormat = `${format} ${timeFormat}`; |
||||
if (dayjs(v, dateTimeFormat, true).isValid() as any) { |
||||
return dateTimeFormat; |
||||
} |
||||
} |
||||
} |
||||
return 'YYYY/MM/DD'; |
||||
} |
||||
|
||||
export function parseStringDate(v: string, dateFormat: string) { |
||||
const dayjsObj = dayjs(v); |
||||
if (dayjsObj.isValid()) { |
||||
v = dayjsObj.format('YYYY-MM-DD'); |
||||
} else { |
||||
v = dayjs(v, dateFormat).format('YYYY-MM-DD'); |
||||
} |
||||
return v; |
||||
} |
||||
|
||||
export function convertToTargetFormat( |
||||
v: string, |
||||
oldDataFormat, |
||||
newDateFormat: string |
||||
) { |
||||
if ( |
||||
!dateFormats.includes(oldDataFormat) || |
||||
!dateFormats.includes(newDateFormat) |
||||
) |
||||
return v; |
||||
return dayjs(v, oldDataFormat).format(newDateFormat); |
||||
} |
@ -0,0 +1,23 @@
|
||||
export function parseMetaProp(model: { meta: any }): any { |
||||
if (!model) return; |
||||
|
||||
// parse meta property
|
||||
try { |
||||
return typeof model.meta === 'string' ? JSON.parse(model.meta) : model.meta; |
||||
} catch { |
||||
return {}; |
||||
} |
||||
} |
||||
|
||||
export function stringifyMetaProp(model: { meta?: any }): string | void { |
||||
if (!model) return; |
||||
|
||||
// stringify meta property
|
||||
try { |
||||
return typeof model.meta === 'string' |
||||
? model.meta |
||||
: JSON.stringify(model.meta); |
||||
} catch (e) { |
||||
return '{}'; |
||||
} |
||||
} |
@ -0,0 +1,67 @@
|
||||
import { CellPageObject } from '.'; |
||||
import BasePage from '../../../Base'; |
||||
|
||||
export class DateTimeCellPageObject extends BasePage { |
||||
readonly cell: CellPageObject; |
||||
|
||||
constructor(cell: CellPageObject) { |
||||
super(cell.rootPage); |
||||
this.cell = cell; |
||||
} |
||||
|
||||
get({ index, columnHeader }: { index?: number; columnHeader: string }) { |
||||
return this.cell.get({ index, columnHeader }); |
||||
} |
||||
|
||||
async open({ index, columnHeader }: { index: number; columnHeader: string }) { |
||||
await this.rootPage.locator('.nc-grid-add-new-cell').click(); |
||||
|
||||
await this.cell.dblclick({ |
||||
index, |
||||
columnHeader, |
||||
}); |
||||
} |
||||
|
||||
async save() { |
||||
await this.rootPage.locator('button:has-text("Ok")').click(); |
||||
} |
||||
|
||||
async selectDate({ |
||||
// date formats in `YYYY-MM-DD`
|
||||
date, |
||||
}: { |
||||
date: string; |
||||
}) { |
||||
// title date format needs to be YYYY-MM-DD
|
||||
await this.rootPage.locator(`td[title="${date}"]`).click(); |
||||
} |
||||
|
||||
async selectTime({ |
||||
// hour: 0 - 23
|
||||
// minute: 0 - 59
|
||||
// second: 0 - 59
|
||||
hour, |
||||
minute, |
||||
second, |
||||
}: { |
||||
hour: number; |
||||
minute: number; |
||||
second?: number | null; |
||||
}) { |
||||
await this.rootPage |
||||
.locator(`.ant-picker-time-panel-column:nth-child(1) > .ant-picker-time-panel-cell:nth-child(${hour + 1})`) |
||||
.click(); |
||||
await this.rootPage |
||||
.locator(`.ant-picker-time-panel-column:nth-child(2) > .ant-picker-time-panel-cell:nth-child(${minute + 1})`) |
||||
.click(); |
||||
if (second != null) { |
||||
await this.rootPage |
||||
.locator(`.ant-picker-time-panel-column:nth-child(3) > .ant-picker-time-panel-cell:nth-child(${second + 1})`) |
||||
.click(); |
||||
} |
||||
} |
||||
|
||||
async close() { |
||||
await this.rootPage.keyboard.press('Escape'); |
||||
} |
||||
} |
@ -0,0 +1,109 @@
|
||||
import { expect, test } from '@playwright/test'; |
||||
import { DashboardPage } from '../pages/Dashboard'; |
||||
import { GridPage } from '../pages/Dashboard/Grid'; |
||||
import setup from '../setup'; |
||||
|
||||
test.describe('Verify cell selection', () => { |
||||
let dashboard: DashboardPage, grid: GridPage; |
||||
let context: any; |
||||
|
||||
test.beforeEach(async ({ page }) => { |
||||
context = await setup({ page }); |
||||
dashboard = new DashboardPage(page, context.project); |
||||
grid = dashboard.grid; |
||||
}); |
||||
|
||||
test('#1 when range is selected, it has correct number of selected cells', async () => { |
||||
await dashboard.treeView.openTable({ title: 'Customer' }); |
||||
await grid.selectRange({ |
||||
start: { index: 0, columnHeader: 'FirstName' }, |
||||
end: { index: 2, columnHeader: 'Email' }, |
||||
}); |
||||
|
||||
expect(await grid.selectedCount()).toBe(9); |
||||
}); |
||||
|
||||
test('#2 when copied with clipboard, it copies correct text', async () => { |
||||
await dashboard.treeView.openTable({ title: 'Customer' }); |
||||
await grid.selectRange({ |
||||
start: { index: 0, columnHeader: 'FirstName' }, |
||||
end: { index: 1, columnHeader: 'LastName' }, |
||||
}); |
||||
|
||||
expect(await grid.copyWithKeyboard()).toBe('MARY \t SMITH\n' + ' PATRICIA \t JOHNSON\n'); |
||||
}); |
||||
|
||||
test('#3 when copied with mouse, it copies correct text', async () => { |
||||
await dashboard.treeView.openTable({ title: 'Customer' }); |
||||
await grid.selectRange({ |
||||
start: { index: 0, columnHeader: 'FirstName' }, |
||||
end: { index: 1, columnHeader: 'LastName' }, |
||||
}); |
||||
|
||||
expect(await grid.copyWithMouse({ index: 0, columnHeader: 'FirstName' })).toBe( |
||||
'MARY \t SMITH\n' + ' PATRICIA \t JOHNSON\n' |
||||
); |
||||
}); |
||||
|
||||
// FIXME: this is edge case, better be moved to integration tests
|
||||
test('#4 when cell inside selection range is clicked, it clears previous selection', async () => { |
||||
await dashboard.treeView.openTable({ title: 'Country' }); |
||||
await grid.selectRange({ |
||||
start: { index: 0, columnHeader: 'Country' }, |
||||
end: { index: 2, columnHeader: 'City List' }, |
||||
}); |
||||
|
||||
expect(await grid.selectedCount()).toBe(9); |
||||
|
||||
await grid.cell.get({ index: 0, columnHeader: 'Country' }).click(); |
||||
|
||||
expect(await grid.selectedCount()).toBe(1); |
||||
expect(await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Country' })); |
||||
}); |
||||
|
||||
// FIXME: this is edge case, better be moved to integration tests
|
||||
test('#5 when cell outside selection range is clicked, it clears previous selection', async () => { |
||||
await dashboard.treeView.openTable({ title: 'Country' }); |
||||
await grid.selectRange({ |
||||
start: { index: 0, columnHeader: 'Country' }, |
||||
end: { index: 2, columnHeader: 'City List' }, |
||||
}); |
||||
|
||||
expect(await grid.selectedCount()).toBe(9); |
||||
|
||||
await grid.cell.get({ index: 5, columnHeader: 'Country' }).click(); |
||||
|
||||
expect(await grid.selectedCount()).toBe(1); |
||||
expect(await grid.cell.verifyCellActiveSelected({ index: 5, columnHeader: 'Country' })); |
||||
}); |
||||
|
||||
// FIXME: this is edge case, better be moved to integration tests
|
||||
test('#6 when selection ends on locked field, it still works as expected', async () => { |
||||
await dashboard.treeView.openTable({ title: 'Country' }); |
||||
await dashboard.grid.toolbar.fields.toggleShowSystemFields(); |
||||
await grid.selectRange({ |
||||
start: { index: 2, columnHeader: 'City List' }, |
||||
end: { index: 0, columnHeader: 'CountryId' }, |
||||
}); |
||||
|
||||
expect(await grid.selectedCount()).toBe(12); |
||||
|
||||
await grid.cell.get({ index: 1, columnHeader: 'Country' }).click(); |
||||
|
||||
expect(await grid.selectedCount()).toBe(1); |
||||
expect(await grid.cell.verifyCellActiveSelected({ index: 1, columnHeader: 'Country' })); |
||||
}); |
||||
|
||||
// FIXME: this is edge case, better be moved to integration tests
|
||||
test('#7 when navigated with keyboard, only active cell is affected', async ({ page }) => { |
||||
await dashboard.treeView.openTable({ title: 'Country' }); |
||||
await grid.selectRange({ |
||||
start: { index: 0, columnHeader: 'Country' }, |
||||
end: { index: 2, columnHeader: 'City List' }, |
||||
}); |
||||
|
||||
await page.keyboard.press('ArrowRight'); |
||||
expect(await grid.selectedCount()).toBe(1); |
||||
expect(await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'LastUpdate' })); |
||||
}); |
||||
}); |
@ -0,0 +1,113 @@
|
||||
import { test } from '@playwright/test'; |
||||
import { DashboardPage } from '../pages/Dashboard'; |
||||
import setup from '../setup'; |
||||
|
||||
const dateTimeData = [ |
||||
{ |
||||
dateFormat: 'YYYY-MM-DD', |
||||
timeFormat: 'HH:mm', |
||||
date: '2022-12-12', |
||||
hour: 10, |
||||
minute: 20, |
||||
output: '2022-12-12 10:20', |
||||
}, |
||||
{ |
||||
dateFormat: 'YYYY-MM-DD', |
||||
timeFormat: 'HH:mm:ss', |
||||
date: '2022-12-11', |
||||
hour: 20, |
||||
minute: 30, |
||||
second: 40, |
||||
output: '2022-12-11 20:30:40', |
||||
}, |
||||
{ |
||||
dateFormat: 'YYYY/MM/DD', |
||||
timeFormat: 'HH:mm', |
||||
date: '2022-12-13', |
||||
hour: 10, |
||||
minute: 20, |
||||
output: '2022/12/13 10:20', |
||||
}, |
||||
{ |
||||
dateFormat: 'YYYY/MM/DD', |
||||
timeFormat: 'HH:mm:ss', |
||||
date: '2022-12-14', |
||||
hour: 5, |
||||
minute: 30, |
||||
second: 40, |
||||
output: '2022/12/14 05:30:40', |
||||
}, |
||||
{ |
||||
dateFormat: 'DD-MM-YYYY', |
||||
timeFormat: 'HH:mm', |
||||
date: '2022-12-10', |
||||
hour: 4, |
||||
minute: 30, |
||||
output: '10-12-2022 04:30', |
||||
}, |
||||
{ |
||||
dateFormat: 'DD-MM-YYYY', |
||||
timeFormat: 'HH:mm:ss', |
||||
date: '2022-12-26', |
||||
hour: 2, |
||||
minute: 30, |
||||
second: 40, |
||||
output: '26-12-2022 02:30:40', |
||||
}, |
||||
]; |
||||
|
||||
test.describe('DateTime Column', () => { |
||||
let dashboard: DashboardPage; |
||||
let context: any; |
||||
|
||||
test.beforeEach(async ({ page }) => { |
||||
context = await setup({ page }); |
||||
dashboard = new DashboardPage(page, context.project); |
||||
}); |
||||
|
||||
test('Create DateTime Column', async () => { |
||||
await dashboard.treeView.createTable({ title: 'test_datetime' }); |
||||
// Create DateTime column
|
||||
await dashboard.grid.column.create({ |
||||
title: 'NC_DATETIME_0', |
||||
type: 'DateTime', |
||||
dateFormat: dateTimeData[0].dateFormat, |
||||
timeFormat: dateTimeData[0].timeFormat, |
||||
}); |
||||
|
||||
for (let i = 0; i < dateTimeData.length; i++) { |
||||
// Edit DateTime column
|
||||
await dashboard.grid.column.openEdit({ |
||||
title: 'NC_DATETIME_0', |
||||
type: 'DateTime', |
||||
dateFormat: dateTimeData[i].dateFormat, |
||||
timeFormat: dateTimeData[i].timeFormat, |
||||
}); |
||||
|
||||
await dashboard.grid.column.save({ isUpdated: true }); |
||||
|
||||
await dashboard.grid.cell.dateTime.open({ |
||||
index: 0, |
||||
columnHeader: 'NC_DATETIME_0', |
||||
}); |
||||
|
||||
await dashboard.grid.cell.dateTime.selectDate({ |
||||
date: dateTimeData[i].date, |
||||
}); |
||||
|
||||
await dashboard.grid.cell.dateTime.selectTime({ |
||||
hour: dateTimeData[i].hour, |
||||
minute: dateTimeData[i].minute, |
||||
second: dateTimeData[i].second, |
||||
}); |
||||
|
||||
await dashboard.grid.cell.dateTime.save(); |
||||
|
||||
await dashboard.grid.cell.verifyDateCell({ |
||||
index: 0, |
||||
columnHeader: 'NC_DATETIME_0', |
||||
value: dateTimeData[i].output, |
||||
}); |
||||
} |
||||
}); |
||||
}); |
Loading…
Reference in new issue