mirror of https://github.com/nocodb/nocodb
Raju Udava
2 years ago
committed by
GitHub
13 changed files with 490 additions and 93 deletions
@ -0,0 +1,83 @@ |
|||||||
|
import dayjs from 'dayjs' |
||||||
|
import { UITypes } from 'nocodb-sdk' |
||||||
|
|
||||||
|
export default function convertCellData(args: { from: UITypes; to: UITypes; value: any }, isMysql = false) { |
||||||
|
const { from, to, value } = args |
||||||
|
if (from === to && ![UITypes.Attachment, UITypes.Date, UITypes.DateTime, UITypes.Time, UITypes.Year].includes(to)) { |
||||||
|
return value |
||||||
|
} |
||||||
|
|
||||||
|
const dateFormat = isMysql ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ssZ' |
||||||
|
|
||||||
|
switch (to) { |
||||||
|
case UITypes.Number: { |
||||||
|
const parsedNumber = Number(value) |
||||||
|
if (isNaN(parsedNumber)) { |
||||||
|
throw new TypeError(`Cannot convert '${value}' to number`) |
||||||
|
} |
||||||
|
return parsedNumber |
||||||
|
} |
||||||
|
case UITypes.Checkbox: |
||||||
|
return Boolean(value) |
||||||
|
case UITypes.Date: { |
||||||
|
const parsedDate = dayjs(value) |
||||||
|
if (!parsedDate.isValid()) throw new Error('Not a valid date') |
||||||
|
return parsedDate.format('YYYY-MM-DD') |
||||||
|
} |
||||||
|
case UITypes.DateTime: { |
||||||
|
const parsedDateTime = dayjs(value) |
||||||
|
if (!parsedDateTime.isValid()) { |
||||||
|
throw new Error('Not a valid datetime value') |
||||||
|
} |
||||||
|
return parsedDateTime.format(dateFormat) |
||||||
|
} |
||||||
|
case UITypes.Time: { |
||||||
|
let parsedTime = dayjs(value) |
||||||
|
|
||||||
|
if (!parsedTime.isValid()) { |
||||||
|
parsedTime = dayjs(value, 'HH:mm:ss') |
||||||
|
} |
||||||
|
if (!parsedTime.isValid()) { |
||||||
|
parsedTime = dayjs(`1999-01-01 ${value}`) |
||||||
|
} |
||||||
|
if (!parsedTime.isValid()) { |
||||||
|
throw new Error('Not a valid time value') |
||||||
|
} |
||||||
|
return parsedTime.format(dateFormat) |
||||||
|
} |
||||||
|
case UITypes.Year: { |
||||||
|
if (/^\d+$/.test(value)) { |
||||||
|
return +value |
||||||
|
} |
||||||
|
|
||||||
|
const parsedDate = dayjs(value) |
||||||
|
|
||||||
|
if (parsedDate.isValid()) { |
||||||
|
return parsedDate.format('YYYY') |
||||||
|
} |
||||||
|
|
||||||
|
throw new Error('Not a valid year value') |
||||||
|
} |
||||||
|
case UITypes.Attachment: { |
||||||
|
let parsedVal |
||||||
|
try { |
||||||
|
parsedVal = typeof value === 'string' ? JSON.parse(value) : value |
||||||
|
parsedVal = Array.isArray(parsedVal) ? parsedVal : [parsedVal] |
||||||
|
} catch (e) { |
||||||
|
throw new Error('Invalid attachment data') |
||||||
|
} |
||||||
|
if (parsedVal.some((v: any) => v && !(v.url || v.data))) { |
||||||
|
throw new Error('Invalid attachment data') |
||||||
|
} |
||||||
|
return JSON.stringify(parsedVal) |
||||||
|
} |
||||||
|
case UITypes.LinkToAnotherRecord: |
||||||
|
case UITypes.Lookup: |
||||||
|
case UITypes.Rollup: |
||||||
|
case UITypes.Formula: |
||||||
|
case UITypes.QrCode: |
||||||
|
throw new Error(`Unsupported conversion from ${from} to ${to}`) |
||||||
|
default: |
||||||
|
return value |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
import { CellPageObject } from '.'; |
||||||
|
import BasePage from '../../../Base'; |
||||||
|
|
||||||
|
export class DateCellPageObject 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.cell.dblclick({ |
||||||
|
index, |
||||||
|
columnHeader, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
async selectDate({ |
||||||
|
// date in format `YYYY-MM-DD`
|
||||||
|
date, |
||||||
|
}: { |
||||||
|
date: string; |
||||||
|
}) { |
||||||
|
await this.rootPage.locator(`td[title="${date}"]`).click(); |
||||||
|
} |
||||||
|
|
||||||
|
async close() { |
||||||
|
await this.rootPage.keyboard.press('Escape'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,117 @@ |
|||||||
|
import { expect, test } from '@playwright/test'; |
||||||
|
import { DashboardPage } from '../pages/Dashboard'; |
||||||
|
import setup from '../setup'; |
||||||
|
|
||||||
|
test.describe('Grid operations', () => { |
||||||
|
let dashboard: DashboardPage; |
||||||
|
let context: any; |
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => { |
||||||
|
context = await setup({ page }); |
||||||
|
dashboard = new DashboardPage(page, context.project); |
||||||
|
}); |
||||||
|
|
||||||
|
test('Clipboard support', async () => { |
||||||
|
// close 'Team & Auth' tab
|
||||||
|
await dashboard.closeTab({ title: 'Team & Auth' }); |
||||||
|
|
||||||
|
await dashboard.treeView.createTable({ title: 'Sheet1' }); |
||||||
|
|
||||||
|
await dashboard.grid.column.create({ |
||||||
|
title: 'Number', |
||||||
|
type: 'Number', |
||||||
|
}); |
||||||
|
await dashboard.grid.column.create({ |
||||||
|
title: 'Checkbox', |
||||||
|
type: 'Checkbox', |
||||||
|
}); |
||||||
|
await dashboard.grid.column.create({ |
||||||
|
title: 'Date', |
||||||
|
type: 'Date', |
||||||
|
}); |
||||||
|
await dashboard.grid.column.create({ |
||||||
|
title: 'Attachment', |
||||||
|
type: 'Attachment', |
||||||
|
}); |
||||||
|
|
||||||
|
await dashboard.grid.addNewRow({ |
||||||
|
index: 0, |
||||||
|
}); |
||||||
|
await dashboard.grid.cell.click({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Number', |
||||||
|
}); |
||||||
|
await dashboard.grid.cell.fillText({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Number', |
||||||
|
text: '123', |
||||||
|
}); |
||||||
|
await dashboard.grid.cell.click({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Checkbox', |
||||||
|
}); |
||||||
|
|
||||||
|
const today = new Date().toISOString().slice(0, 10); |
||||||
|
await dashboard.grid.cell.date.open({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Date', |
||||||
|
}); |
||||||
|
await dashboard.grid.cell.date.selectDate({ |
||||||
|
date: today, |
||||||
|
}); |
||||||
|
await dashboard.grid.cell.date.close(); |
||||||
|
|
||||||
|
await dashboard.grid.cell.attachment.addFile({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Attachment', |
||||||
|
filePath: `${process.cwd()}/fixtures/sampleFiles/1.json`, |
||||||
|
}); |
||||||
|
|
||||||
|
await dashboard.grid.cell.copyToClipboard({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Title', |
||||||
|
}); |
||||||
|
expect(await dashboard.grid.cell.getClipboardText()).toBe('Row 0'); |
||||||
|
|
||||||
|
await dashboard.grid.cell.copyToClipboard({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Number', |
||||||
|
}); |
||||||
|
expect(await dashboard.grid.cell.getClipboardText()).toBe('123'); |
||||||
|
|
||||||
|
await dashboard.grid.cell.copyToClipboard( |
||||||
|
{ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Checkbox', |
||||||
|
}, |
||||||
|
{ position: { x: 1, y: 1 } } |
||||||
|
); |
||||||
|
await new Promise(resolve => setTimeout(resolve, 5000)); |
||||||
|
expect(await dashboard.grid.cell.getClipboardText()).toBe('true'); |
||||||
|
|
||||||
|
await dashboard.grid.cell.click({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Checkbox', |
||||||
|
}); |
||||||
|
await dashboard.grid.cell.copyToClipboard( |
||||||
|
{ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Checkbox', |
||||||
|
}, |
||||||
|
{ position: { x: 1, y: 1 } } |
||||||
|
); |
||||||
|
expect(await dashboard.grid.cell.getClipboardText()).toBe('false'); |
||||||
|
|
||||||
|
await dashboard.grid.cell.copyToClipboard({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Date', |
||||||
|
}); |
||||||
|
expect(await dashboard.grid.cell.getClipboardText()).toBe(today); |
||||||
|
|
||||||
|
await dashboard.grid.cell.copyToClipboard({ |
||||||
|
index: 0, |
||||||
|
columnHeader: 'Attachment', |
||||||
|
}); |
||||||
|
// expect(await dashboard.grid.cell.getClipboardText()).toBe('1.json');
|
||||||
|
}); |
||||||
|
}); |
Loading…
Reference in new issue