/**
* Created by Samuel Gratzl on 29.09.2016.
*/
import {BaseUtils} from 'phovea_core';
import * as d3 from 'd3';
import {ITypeDefinition, ValueTypeEditor, ValueTypeUtils} from '../valuetype/valuetypes';
import {IDataDescription} from 'phovea_core';
import {UserSession} from 'phovea_core';
import {I18nextManager} from 'phovea_core';
export interface IColumnDefinition {
name: string;
column: string | number;
value: ITypeDefinition;
}
export class ImportUtils {
static commonFields(name: string) {
const prefix = 'i' + BaseUtils.randomId(3);
return `
`;
}
static extractCommonFields($root: d3.Selection) {
return {
name: $root.select('input[name="name"]').property('value'),
description: $root.select('textarea[name="desc"]').property('value')
};
}
static async importTable(editors: ValueTypeEditor[], $root: d3.Selection, header: string[], data: string[][], name: string) {
$root.html(`${ImportUtils.commonFields(name)}
| ${I18nextManager.getInstance().i18n.t('phovea:importer.column')} |
${I18nextManager.getInstance().i18n.t('phovea:importer.type')} |
`);
const configPromises = header.map((name, i) => {
return ValueTypeUtils.guessValueType(editors, name, i, data, (row) => row[i]);
});
const guessedEditors = await Promise.all(configPromises);
const config = await Promise.all(header.map(async (name, i) => {
const value = await guessedEditors[i].guessOptions({type: null}, data, (col) => col[i]);
const markup = await ValueTypeUtils.createTypeEditor(editors, guessedEditors[i], value);
return {
column: i,
name,
color: '#DDDDDD',
value,
editor: guessedEditors[i],
markup
};
}));
const $rows = $root.select('tbody').selectAll('tr').data(config);
function getCellMarkup(d) {
return `
|
${d.markup}
| `;
}
const $rowsEnter = $rows.enter().append('tr')
.html(getCellMarkup);
$rowsEnter.select('input').on('change', function (d) {
d.name = this.value;
});
$rowsEnter.select('select').on('change', ValueTypeUtils.updateType(editors));
$rowsEnter.select('button').on('click', (d) => {
d.editor.edit(d.value);
});
const common = ImportUtils.extractCommonFields($root);
return () => ({data, desc: ImportUtils.toTableDataDescription(config, data, common)});
}
static toTableDataDescription(config: IColumnDefinition[], data: any[], common: {name: string, description: string}) {
//derive all configs
config = config.filter((c) => (c).editor != null);
config.forEach((d) => {
const editor = (d).editor;
editor.parse(d.value, data, (row, value?) => {
if (typeof value !== 'undefined') {
return row[d.column] = value;
}
return row[d.column];
});
});
//generate config
let idProperty = config.filter((d) => d.value.type === 'idType')[0];
if (!idProperty) {
//create an artificial one
idProperty = {value: {type: 'idType', idType: 'Custom'}, name: 'IDType', column: '_index'};
data.forEach((d, i) => d._index = i);
}
const columns = config.filter((c) => c !== idProperty).map((c) => {
const r: IColumnDefinition = BaseUtils.mixin({}, c);
delete (r).editor;
return r;
});
const desc: IDataDescription = {
type: 'table',
id: BaseUtils.fixId(common.name + BaseUtils.randomId(2)),
name: common.name,
description: common.description,
creator: UserSession.getInstance().currentUserNameOrAnonymous(),
ts: Date.now(),
fqname: 'upload/' + common.name,
size: [data.length, columns.length],
idtype: (idProperty).value.idType,
columns,
idcolumn: idProperty.column
};
return desc;
}
static async importMatrix(editors: ValueTypeEditor[], $root: d3.Selection, header: string[], data: string[][], name: string) {
const prefix = 'a' + BaseUtils.randomId(3);
const rows = header.slice(1),
cols = data.map((d) => d.shift());
const dataRange = d3.range(rows.length * cols.length);
function byIndex(i, v?) {
const m = i % cols.length;
if (v !== undefined) {
return data[(i - m) / cols.length][m] = v;
} else {
return data[(i - m) / cols.length][m];
}
}
const editor = await ValueTypeUtils.guessValueType(editors, 'value', -1, dataRange, byIndex);
const configs = [{
column: -1,
name: I18nextManager.getInstance().i18n.t('phovea:importer.rowName'),
value: {
type: 'idType'
},
editor: editors.filter((e) => e.id === 'idType')[0]
}, {
column: -1,
name: I18nextManager.getInstance().i18n.t('phovea:importer.columnName'),
value: {
type: 'idType'
},
editor: editors.filter((e) => e.id === 'idType')[0]
}, {
column: -1,
name: I18nextManager.getInstance().i18n.t('phovea:importer.value'),
value: {
type: null
},
editor
}];
const $rows = $root.html(ImportUtils.commonFields(name)).selectAll('div.field').data(configs);
$rows.enter().append('div').classed('form-group', true).html((d, i) => `
`);
$rows.select('select').on('change', ValueTypeUtils.updateType(editors, false));
$rows.select('button').on('click', (d, i) => {
if (i < 2) {
d.editor.guessOptions(d.value, i === 0 ? rows : cols, BaseUtils.identity);
} else {
d.editor.guessOptions(d.value, dataRange, byIndex);
}
d.editor.edit(d.value);
});
//parse data
//TODO set rows and cols
configs[0].editor.parse(configs[0].value, rows, BaseUtils.identity);
configs[1].editor.parse(configs[1].value, cols, BaseUtils.identity);
configs[2].editor.parse(configs[2].value, dataRange, byIndex);
const common = ImportUtils.extractCommonFields($root);
const desc: IDataDescription = {
type: 'matrix',
id: BaseUtils.fixId(common.name + BaseUtils.randomId(3)),
name: common.name,
fqname: 'upload/' + common.name,
creator: UserSession.getInstance().currentUserNameOrAnonymous(),
ts: Date.now(),
description: common.description,
size: [rows.length, cols.length],
rowtype: (configs[0]).value.idType,
coltype: (configs[1]).value.idType,
value: configs[1].value
};
return () => ({rows, cols, data, desc});
}
}