Skip to content

Commit

Permalink
feat(ui): added import from file with built-in import data sources #3837
Browse files Browse the repository at this point in the history
  • Loading branch information
ymarcon committed May 12, 2024
1 parent 2597332 commit cf1e7a3
Show file tree
Hide file tree
Showing 13 changed files with 490 additions and 57 deletions.
160 changes: 114 additions & 46 deletions opal-ui/src/components/datasource/ImportDataDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
:options="fileImporters"
:label="$t('data_format')"
dense
@update:model-value="onFileImporterChange"
class="q-mb-md"/>
<div class="text-help q-mb-md">
{{ $t('select_dictionary_file') }}
Expand All @@ -38,7 +39,6 @@
:folder="filesStore.current"
selection="single"
:extensions="fileExtensions"
@select="onFileSelection"
class="q-mb-md"/>
</div>
</q-step>
Expand All @@ -49,59 +49,89 @@
icon="table_chart"
:done="step > 2"
>
<div v-if="fileImporter.value === 'csv'">
<import-csv-form v-model="factory" :file="dataFile" />
</div>
<div v-else>
TODO: configure import source
<div v-if="dataFile">
<div v-if="fileImporter.value === 'csv'">
<import-csv-form v-model="factory" :file="dataFile" />
</div>
<div v-else-if="fileImporter.value === 'opal'">
<import-fs-form v-model="factory" :file="dataFile" />
</div>
<div v-else>
<import-haven-form v-model="factory" :file="dataFile" />
</div>
</div>
</q-step>

<q-step
:name="3"
:title="$t('preview_import_source')"
icon="table_chart"
:title="$t('select_import_options')"
:caption="$t('optional')"
icon="assignment"
:done="step > 3"
>
TODO: make transient datasource and preview values
<pre>{{ transientDatasourceStore.datasource }}</pre>
<div>
<q-checkbox v-model="merge" :label="$t('merge_dictionaries')" />
<div class="text-hint q-mb-md">
{{ $t('merge_dictionaries_hint') }}
</div>
<q-input
v-model="limit"
:label="$t('limit')"
dense
type="number"
min="0"
step="1000"
class="q-mb-md"
:hint="$t('import_limit_hint')"
/>
<q-checkbox v-model="incremental" :label="$t('incremental_import')" />
<div class="text-hint q-mb-md">
{{ $t('incremental_import_hint') }}
</div>
</div>
</q-step>

<q-step
:name="4"
:title="$t('select_import_options')"
:caption="$t('optional')"
icon="assignment"
:title="$t('preview_import_source')"
icon="table_chart"
>
TODO: incremental etc.
<q-select
v-show="transientDatasourceStore.datasource?.table?.length > 1"
v-model="selectedTable"
:options="transientDatasourceStore.datasource.table"
:label="$t('tables')"
dense
@update:model-value="onTableSelection"
class="q-mb-md"/>
<table-preview
v-if="transientDatasourceStore.datasource"
:table="transientDatasourceStore.table"
:variables="transientDatasourceStore.variables"
:loading="variablesLoading" />
</q-step>

<q-stepper-navigation>
<q-btn
v-if="step > 1"
size="sm"
flat
icon="navigate_before"
color="secondary"
@click="$refs.stepper.previous()"
:label="$t('back')" />
<q-btn
v-if="step < 4"
size="sm"
icon-right="navigate_next"
@click="$refs.stepper.next()"
color="primary"
:label="$t('continue')"
:disable="!canNext"
class="on-right"/>

</q-stepper-navigation>
</q-stepper>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-grey-3">
<q-btn
v-if="step > 1"
flat
icon="navigate_before"
color="primary"
@click="$refs.stepper.previous()"
:label="$t('back')" />
<q-btn
v-if="step < 4"
flat
icon-right="navigate_next"
@click="$refs.stepper.next()"
color="primary"
:label="$t('continue')"
:disable="!canNext"
class="on-right"/>
<q-btn
flat
:label="$t('cancel')"
Expand All @@ -110,7 +140,7 @@
@click="onCancel"
/>
<q-btn
:disable="step < 3"
:disable="step < 4"
flat
:label="$t('import')"
color="primary"
Expand All @@ -135,6 +165,9 @@ import { FileDto } from 'src/models/Opal';
import { DatasourceFactory } from 'src/components/models';
import FileSelect from 'src/components/files/FileSelect.vue';
import ImportCsvForm from 'src/components/datasource/import/ImportCsvForm.vue';
import ImportFsForm from 'src/components/datasource/import/ImportFsForm.vue';
import ImportHavenForm from 'src/components/datasource/import/ImportHavenForm.vue';
import TablePreview from 'src/components/datasource/TablePreview.vue';
import { notifyError, notifySuccess } from 'src/utils/notify';
interface DialogProps {
Expand Down Expand Up @@ -178,6 +211,11 @@ const showDialog = ref(props.modelValue);
const step = ref(1);
const dataFile = ref<FileDto>();
const factory = ref<DatasourceFactory>();
const merge = ref(false);
const incremental = ref(false);
const limit = ref();
const selectedTable = ref<string>();
const variablesLoading = ref(false);
const fileImporter = ref(fileImporters[0]);
Expand Down Expand Up @@ -216,6 +254,10 @@ function onCancel() {
transientDatasourceStore.deleteDatasource();
}
function onFileImporterChange() {
dataFile.value = undefined;
}
function onImportData() {
const dsName = transientDatasourceStore.datasource.name;
const options = {
Expand All @@ -230,19 +272,45 @@ function onImportData() {
});
}
function onFileSelection(file: FileDto) {
console.log('File selected', file);
console.log('File data', dataFile.value);
}
function onStepChange(value: number) {
console.log('Step change', value);
if (value === 2) {
function onStepChange(value: string | number) {
if (value === 3) {
// clear transient datasource if any
transientDatasourceStore.deleteDatasource();
}
if (value === 3) {
transientDatasourceStore.createDatasource(factory.value);
if (value === 4 && factory.value) {
if (limit.value) {
factory.value.batchConfig = { limit: parseInt(limit.value) };
}
if (incremental.value) {
factory.value.incrementalConfig = {
incremental: true,
incrementalDestinationName: projectsStore.project.name,
}
}
transientDatasourceStore.createDatasource(factory.value, merge.value).then(() => {
selectedTable.value = transientDatasourceStore.datasource.table[0];
onTableSelection();
}).catch((err) => {
console.error(err);
notifyError(err);
})
}
}
function onTableSelection() {
if (!selectedTable.value) {
return;
}
variablesLoading.value = true;
transientDatasourceStore.loadTable(selectedTable.value).then(() => {
transientDatasourceStore.loadVariables().catch((err) => {
notifyError(err);
}).finally(() => {
variablesLoading.value = false;
});
}).catch((err) => {
variablesLoading.value = false;
notifyError(err);
});
}
</script>
54 changes: 54 additions & 0 deletions opal-ui/src/components/datasource/TablePreview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<template>
<div v-if="props.table">
<q-tabs
v-model="tableTab"
class="text-primary"
>
<q-tab name="variables" :label="$t('dictionary')">
<q-badge v-if="props.table.variableCount !== undefined" color="red">{{ props.table.variableCount }}</q-badge>
</q-tab>
<q-tab name="values" :label="$t('values')">
<q-badge v-if="props.table.valueSetCount !== undefined" color="red">{{ props.table.valueSetCount }}</q-badge>
</q-tab>
</q-tabs>
<q-separator />
<q-tab-panels v-model="tableTab">
<q-tab-panel name="variables">
<variables-list
:variables="props.variables" :loading="props.loading" />
</q-tab-panel>
<q-tab-panel name="values">
<pre>{{ props.table }}</pre>
</q-tab-panel>
</q-tab-panels>
</div>
</template>


<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'TablePreviewList',
});
</script>
<script setup lang="ts">
import VariablesList from 'src/components/datasource/VariablesList.vue';
import { TableDto, VariableDto } from 'src/models/Magma';
interface TablePreviewProps {
table: TableDto | undefined;
variables: VariableDto[];
loading: boolean;
}
const props = defineProps<TablePreviewProps>();
const tableTab = ref('variables');
watch(() => props.table, (value) => {
if (value) {
tableTab.value = 'variables';
}
});
</script>
11 changes: 6 additions & 5 deletions opal-ui/src/components/datasource/TableValues.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,13 @@

<script lang="ts">
import { defineComponent } from 'vue';
import { QTableColumn } from 'quasar';
export default defineComponent({
name: 'TableValues',
});
</script>
<script setup lang="ts">
import { VariableDto } from 'src/models/Magma';
import { ValueSetsDto, VariableDto } from 'src/models/Magma';
import ValueCell from 'src/components/datasource/ValueCell.vue';
import { t } from 'src/boot/i18n';
Expand All @@ -114,9 +115,9 @@ const pagination = ref({
const COLUMNS_COUNT = 20;
const rows = ref([]);
const columns = ref([]);
const columns = ref<QTableColumn[]>([]);
const visibleColumns = ref<string[]>([]);
const varFilter = ref<string>();
const varFilter = ref<string>('');
const dsName = computed(() => route.params.id as string);
const tName = computed(() => route.params.tid as string);
Expand Down Expand Up @@ -173,11 +174,11 @@ function onRequest(props) {
const limit = rowsPerPage;
const select = visibleColumns.value;
loading.value = true;
datasourceStore.loadValueSets(offset, limit, select).then((res) => {
datasourceStore.loadValueSets(offset, limit, select).then((res: ValueSetsDto) => {
if (res.valueSets) {
rows.value = res.valueSets.map((vs) => {
const row = { _id: vs.identifier };
vs.values.forEach((val, idx) => {
vs.values.forEach((val, idx: number) => {
row[res.variables[idx]] = val;
});
return row;
Expand Down
Loading

0 comments on commit cf1e7a3

Please sign in to comment.