Skip to content

Commit

Permalink
Introduce a replace step ui component
Browse files Browse the repository at this point in the history
  • Loading branch information
vdestraitt authored and adimascio committed Jul 27, 2019
1 parent e2c15c6 commit a745da6
Show file tree
Hide file tree
Showing 8 changed files with 563 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/components/ActionMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<div class="action-menu__option" @click="createStep('rename')">Rename column</div>
<div class="action-menu__option" @click="createDeleteColumnStep">Delete column</div>
<div class="action-menu__option" @click="createStep('fillna')">Fill null values</div>
<div class="action-menu__option" @click="createStep('replace')">Replace values</div>
<div class="action-menu__option" @click="createStep('filter')">Filter values</div>
<div class="action-menu__option" @click="createStep('sort')">Sort values</div>
</div>
Expand Down
102 changes: 102 additions & 0 deletions src/components/stepforms/ReplaceStepForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<template>
<div>
<step-form-title :title="title"></step-form-title>
<ColumnPicker
id="searchColumnInput"
v-model="editedStep.search_column"
name="Search in column..."
placeholder="Enter a column"
></ColumnPicker>
<WidgetInputText
id="newColumnInput"
v-model="editedStep.new_column"
name="(Optional) Write output in..."
placeholder="Enter a new column name"
></WidgetInputText>
<WidgetList
addFieldName="Add a value to replace"
id="toReplace"
name="Values to replace:"
v-model="toReplace"
:defaultItem="[]"
:widget="widgetToReplace"
:automatic-new-field="false"
></WidgetList>
<step-form-buttonbar :errors="errors" :cancel="cancelEdition" :submit="submit"></step-form-buttonbar>
</div>
</template>

<script lang="ts">
import { Prop } from 'vue-property-decorator';
import { Getter } from 'vuex-class';
import { StepFormComponent } from '@/components/formlib';
import ColumnPicker from '@/components/stepforms/ColumnPicker.vue';
import WidgetInputText from '@/components/stepforms/WidgetInputText.vue';
import WidgetList from '@/components/stepforms/WidgetList.vue';
import WidgetToReplace from '@/components/stepforms/WidgetToReplace.vue';
import BaseStepForm from './StepForm.vue';
import { ReplaceStep } from '@/lib/steps';
import { DataSetColumn } from '@/lib/dataset';
@StepFormComponent({
vqbstep: 'replace',
name: 'replace-step-form',
components: {
ColumnPicker,
WidgetInputText,
WidgetList,
},
})
export default class ReplaceStepForm extends BaseStepForm<ReplaceStep> {
@Prop({ type: Object, default: () => ({ name: 'replace', search_column: '', to_replace: [[]] }) })
initialStepValue!: ReplaceStep;
@Getter columnHeaders!: DataSetColumn[];
readonly title: string = 'Replace values';
widgetToReplace = WidgetToReplace;
get stepSelectedColumn() {
return this.editedStep.search_column;
}
set stepSelectedColumn(colname: string | null) {
if (colname === null) {
throw new Error('should not try to set null on search_column field');
}
this.editedStep.search_column = colname;
}
get toReplace() {
if (this.editedStep.to_replace.length) {
return this.editedStep.to_replace;
} else {
return [[]];
}
}
set toReplace(newval) {
this.editedStep.to_replace = [...newval];
}
submit() {
const type = this.columnHeaders.filter(h => h.name === this.editedStep.search_column)[0].type;
if (type === 'integer' || type === 'float') {
for (const tuple of this.editedStep.to_replace) {
if (!isNaN(Number(tuple[0]))) {
tuple[0] = Number(tuple[0]);
}
if (!isNaN(Number(tuple[1]))) {
tuple[1] = Number(tuple[1]);
}
}
} else if (type === 'boolean') {
for (const tuple of this.editedStep.to_replace) {
tuple[0] = tuple[0] === 'true';
tuple[1] = tuple[1] === 'true';
}
}
this.$$super.submit();
}
}
</script>
49 changes: 49 additions & 0 deletions src/components/stepforms/WidgetToReplace.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<div class="widget-to-replace__container">
<WidgetInputText id="valueToReplace" v-model="toReplace[0]" placeholder="Value to replace"></WidgetInputText>
<WidgetInputText id="newValue" v-model="toReplace[1]" placeholder="New value"></WidgetInputText>
</div>
</template>
<script lang="ts">
import _ from 'lodash';
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import WidgetInputText from './WidgetInputText.vue';
@Component({
name: 'widget-to-replace',
components: {
WidgetInputText,
},
})
export default class WidgetToReplace extends Vue {
@Prop({
type: Array,
default: () => ['', ''],
})
value!: any[];
toReplace: any[] = [...this.value];
@Watch('toReplace', { immediate: true, deep: true })
onToReplaceChanged(newval: any[], oldval: any[]) {
if (!_.isEqual(newval, oldval)) {
this.$emit('input', this.toReplace);
}
}
}
</script>
<style lang="scss" scoped>
.widget-to-replace__container {
background-color: white;
display: flex;
min-height: 45px;
width: 100%;
}
.widget-input-text__container {
margin-bottom: 0px;
margin-left: 5px;
margin-right: 5px;
width: 50%;
}
</style>
1 change: 1 addition & 0 deletions src/components/stepforms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import './FormulaStepForm.vue';
import './PercentageStepForm.vue';
import './PivotStepForm.vue';
import './RenameStepForm.vue';
import './ReplaceStepForm.vue';
import './SelectColumnStepForm.vue';
import './TopStepForm.vue';
import './UnpivotStepForm.vue';
Expand Down
2 changes: 2 additions & 0 deletions src/components/stepforms/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import formulaSchema from './formula';
import percentageBuildSchema from './percentage';
import pivotSchema from './pivot';
import renameBuildSchema from './rename';
import replaceBuildSchema from './replace';
import selectSchema from './select';
import topBuildSchema from './top';
import unpivotSchema from './unpivot';
Expand All @@ -30,6 +31,7 @@ const factories: { [stepname: string]: buildSchemaType } = {
percentage: percentageBuildSchema,
pivot: pivotSchema,
rename: renameBuildSchema,
replace: replaceBuildSchema,
select: selectSchema,
top: topBuildSchema,
unpivot: unpivotSchema,
Expand Down
58 changes: 58 additions & 0 deletions src/components/stepforms/schemas/replace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { StepFormType, addNotInColumnNamesConstraint } from './utils';

const schema = {
$schema: 'http://json-schema.org/draft-07/schema#',
title: 'Replace step',
type: 'object',
properties: {
name: {
type: 'string',
enum: ['replace'],
},
search_column: {
type: 'string',
items: {
type: 'string',
minLength: 1,
},
title: 'Search',
description: 'Columns in which to search values to replace',
attrs: {
placeholder: 'Enter a column',
},
},
new_column: {
type: 'string',
items: {
type: 'string',
minLength: 0,
},
title: 'Search',
description: 'Columns in which to search values to replace',
attrs: {
placeholder: 'Enter a column',
},
},
to_replace: {
type: 'array',
items: {
type: 'array',
items: {
type: ['string', 'number', 'boolean'],
minItems: 2,
maxItems: 2,
},
minItems: 1,
},
minItems: 1,
title: 'To replace',
description: 'Values to replace',
},
},
required: ['name', 'search_column', 'to_replace'],
additionalProperties: false,
};

export default function buildSchema(form: StepFormType) {
return addNotInColumnNamesConstraint(schema, 'new_column', form.columnNames);
}

0 comments on commit a745da6

Please sign in to comment.