Skip to content

Commit

Permalink
RDISCROWD-6793 - ANCO builder component
Browse files Browse the repository at this point in the history
  • Loading branch information
peterkle committed Jan 2, 2024
1 parent 788c8e6 commit 8194c84
Show file tree
Hide file tree
Showing 13 changed files with 472 additions and 47 deletions.
177 changes: 177 additions & 0 deletions static/src/components/builder/components/Anco/AncoForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<template>
<div class="row">
<h4>Annotation Copilot Settings</h4>
<div class="form-group">
<label
class="col-labels"
for="pyb-answer"
>
Answer field name | <span class="label-tip">The field where the worker's answer is stored. Can be JSON path like a.b.c.</span>
</label>
<input
id="pyb-answer"
:value="pybAnswer"
class="form-control form-control-sm"
type="text"
@input="updatePybanswer($event.target.value)"
>
</div>
<div class="form-group">
<label
class="col-labels"
for="doc-url"
>
Document URL field name | <span class="label-tip">A JavaScript expression that returns the document URL, e.g.'task.info.document__upload_file'.</span>
</label>
<input
id="doc-url"
:value="docUrl"
class="form-control form-control-sm"
type="text"
@input="updateDocUrl($event.target.value)"
>
</div>
<div class="form-group">
<label
class="col-labels"
for="annotation-url"
>
Annotation URL field name | <span class="label-tip">A JavaScript expression that returns the annotation URL, e.g.'task.info.annotation'.</span>
</label>
<input
id="annotation-url"
:value="annotationUrl"
class="form-control form-control-sm"
type="text"
@input="updateAnnotationUrl($event.target.value)"
>
</div>
<hr>
<h4>
Categories
</h4>
<div class="scroll col-md-12">
<div class="row">
<div class="col-md-12">
<div
v-for="(category, index) in categoryList"
:key="index"
class="row"
name="columns"
>
<hr
v-if="index != 0"
size="100px"
>
<label>Category {{ index + 1 }}</label>
<button
v-if="index > 0"
class="btn btn-times-delete pull-right fa fa-times"
@click="deleteCategoryListItem(index)"
/><br>
<label
class="block-label"
>
Category Label | <span class="label-tip">Text to display for the category.</span>
<input
:value="category.name"
class="form-control form-control-sm"
type="text"
@input="updateCategoryItem(category, index, 'name', $event.target.value)"
>
</label>
<label
class="block-label"
>
Data Type | <span class="label-tip">Data type of the caputured data value.</span>
<select
:value="category.type"
class="form-control form-control-sm"
@change="updateCategoryItem(category, index, 'type', $event.target.value)"
>
<option selected />
<option
v-for="categoryType in categoryTypes"
:key="categoryType"
:value="categoryType"
>
{{ categoryType }}
</option>
</select>
</label>
<label
class="block-label"
>
CSS Style | <span class="label-tip">Inline CSS string, e.g. 'color: red;'.</span>
<input
id="value"
class="form-control form-control-sm"
type="text"
:value="category.style"
@input="updateCategoryItem(category, index, 'style', $event.target.value)"
>
</label>
</div>
<br>
</div>
</div>
</div>
<div class="col-sm-10 col-md-11" />
<button
id="add"
class="btn btn-default btn-sm col-sm-2 col-md-1"
@click="addCategoryListItem"
>
Add
</button>
</div>
</template>

<script>
import { cloneDeep } from 'lodash';
import { mapMutations, mapState } from 'vuex';
import '../../../../../css/component_builder.css';
import * as types from '../../store/types';
export default {
name: 'AncoForm',
data () {
return {
categoryTypes: ['Date', 'Datetime', 'Integer', 'Number', 'Text']
};
},
computed: {
...mapState({
pybAnswer: state => state.anco.pybAnswer,
categoryList: state => state.anco.categoryList,
docUrl: state => state.anco.docUrl,
annotationUrl: state => state.anco.annotationUrl
})
},
updated () {
this.scrollToEnd();
},
methods: {
...mapMutations({
'updatePybanswer': types.MUTATE_ANCO_PYB_ANSWER,
'addCategoryListItem': types.MUTATE_ANCO_ADD_LIST_ITEM,
'deleteCategoryListItem': types.MUTATE_ANCO_DELETE_LIST_ITEM,
'updateDocUrl': types.MUTATE_ANCO_DOC_URL,
'updateAnnotationUrl': types.MUTATE_ANCO_ANNOTATION_URL
}),
updateCategoryItem (category, index, fieldName, value) {
const newCategory = cloneDeep(category);
newCategory[fieldName] = value;
this.$store.commit(types.MUTATE_ANCO_UPDATE_LIST_ITEM, { category: newCategory, index });
this.scrollToEnd();
},
scrollToEnd () {
const container = document.querySelector('.scroll');
if (container) {
const scrollHeight = container.scrollHeight;
container.scrollTop = scrollHeight;
}
}
}
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<anco-loader
v-if='{{docUrl}}'
pyb-answer='{{pybAnswer}}'
:doc-url='{{docUrl}}'
:annotation-url='{{annotationUrl}}'
annotation-type='{{annotationType}}'
categories='{{categories}}'
></anco-loader>
7 changes: 4 additions & 3 deletions static/src/components/builder/components/PreviewCommons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@
</style>

<script>
import components from '@dtwebservices/task-presenter-components';
import 'prismjs';
import 'prismjs/themes/prism.css';
import Prism from 'vue-prism-component';
import ComponentRender from './ComponentRender/ComponentRender';
import components from '@dtwebservices/task-presenter-components';
import * as types from '../store/types';
import utils from '../utils';
import ComponentRender from './ComponentRender/ComponentRender';
export default {
components: {
Expand All @@ -86,7 +86,8 @@ export default {
MULTISELECT_INPUT: 'multi-select-input',
CONDITIONAL_DISPLAY: 'conditionaldisplay-creator',
FILE_UPLOAD: 'file-upload',
INPUT_TEXT_AREA: 'input-text-area'
INPUT_TEXT_AREA: 'input-text-area',
ANCO_LOADER: 'anco'
}
};
},
Expand Down
11 changes: 11 additions & 0 deletions static/src/components/builder/components/Questions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
:style="isPublic ? 'display:none' : ''"
/>
<custom-router-link :component="inputTextArea" />
<custom-router-link
:component="anco"
:style="isPublic ? 'display:none' : ''"
/>
</div>
<div class="col-md-8">
<div class="row">
Expand Down Expand Up @@ -242,6 +246,13 @@ export default {
componentName: 'INPUT_TEXT_AREA',
header: 'Input Text Area'
}
},
anco: {
name: 'ANCO_FORM',
params: {
componentName: 'ANCO',
header: 'Annotation Copilot'
}
}
};
},
Expand Down
50 changes: 38 additions & 12 deletions static/src/components/builder/router.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import Questions from './components/Questions.vue';
import Header from './components/Header.vue';
import Content from './components/Content.vue';
import AncoForm from './components/Anco/AncoForm';
import AssistantLLMForm from './components/AssistantLLM/AssistantLLMForm.vue';
import CheckboxForm from './components/CheckboxInput/CheckboxInputForm.vue';
import TextInputForm from './components/TextInput/TextInputForm.vue';
import TableForm from './components/Table/TableForm.vue';
import PreviewCommons from './components/PreviewCommons.vue';
import RadioForm from './components/RadioInput/RadioInputForm.vue';
import TextTaggingForm from './components/TextTagging/TextTaggingForm.vue';
import DropdownForm from './components/DropdownInput/DropdownForm.vue';
import MultiselectForm from './components/MultiselectInput/MultiselectForm.vue';
import ConditionalDisplayForm from './components/ConditionalDisplay/ConditionalDisplayForm.vue';
import Content from './components/Content.vue';
import DropdownForm from './components/DropdownInput/DropdownForm.vue';
import FileUploadForm from './components/FileUpload/FileUploadForm.vue';
import TaskTimerForm from './components/TaskTimer/TaskTimerForm.vue';
import Header from './components/Header.vue';
import InputTextAreaForm from './components/InputTextArea/InputTextAreaForm.vue';
import AssistantLLMForm from './components/AssistantLLM/AssistantLLMForm.vue';
import MultiselectForm from './components/MultiselectInput/MultiselectForm.vue';
import PreviewCommons from './components/PreviewCommons.vue';
import Questions from './components/Questions.vue';
import RadioForm from './components/RadioInput/RadioInputForm.vue';
import TableForm from './components/Table/TableForm.vue';
import TaskPresenterForm from './components/TaskPresenter/TaskPresenterForm.vue';
import TaskTimerForm from './components/TaskTimer/TaskTimerForm.vue';
import TextInputForm from './components/TextInput/TextInputForm.vue';
import TextTaggingForm from './components/TextTagging/TextTaggingForm.vue';

export const routes = [
{
Expand Down Expand Up @@ -376,6 +377,31 @@ export const routes = [
}
]
},
{
path: '/anco',
name: 'ANCO',
components: {
default: Content,
header: Header
},
children: [
{
path: 'form',
name: 'ANCO_FORM',
components: { default: AncoForm }
},
{
path: 'preview',
name: 'ANCO_PREVIEW',
components: { default: PreviewCommons }
},
{
path: 'code',
name: 'ANCO_CODE',
components: { default: PreviewCommons }
}
]
},
{ path: '/redirect-me', redirect: { name: 'home' } },
{ path: '*', redirect: '/' }
];
12 changes: 7 additions & 5 deletions static/src/components/builder/store/__mocks__/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import Vue from 'vue';
import Vuex from 'vuex';
import textInput from './modules/textInput';
import anco from './modules/anco';
import checkboxInput from './modules/checkboxInput';
import table from './modules/table';
import inputTextArea from './modules/inputTextArea';
import table from './modules/table';
import textInput from './modules/textInput';

Vue.use(Vuex);
export function __createMocks (
custom = { getters: {}, mutations: {}, actions: {}, state: {} }
) {
const mockGetters = Object.assign({}, textInput.getters, checkboxInput.getters, table.getters, inputTextArea.getters);
const mockGetters = Object.assign({}, textInput.getters, checkboxInput.getters, table.getters, inputTextArea.getters, anco.getters);
const mockMutations = Object.assign(
{},
textInput.mutations,
checkboxInput.mutations,
table.mutations,
inputTextArea.mutations
inputTextArea.mutations,
anco.mutations
);
const mockActions = Object.assign({}, textInput.actions, custom.actions, inputTextArea.actions);
const mockState = Object.assign({}, textInput.state, checkboxInput.state, table.state, inputTextArea.state);
const mockState = Object.assign({}, textInput.state, checkboxInput.state, table.state, inputTextArea.state,anco.state);
return {
getters: mockGetters,
mutations: mockMutations,
Expand Down
34 changes: 34 additions & 0 deletions static/src/components/builder/store/__mocks__/modules/anco.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as types from '../../types';

export const state = {
anco: {
'pyb-answer': 'myPybAnswer',
categoryList: [{name: 'category1', type: 'text', stle: 'color:red'}],
docUrl: 'http://boomberg.next/doc.pdf',
annotationUrl: 'http://boomberg.next/annotation.json',
isValidForm: true
}
};

export const getters = {
[types.GET_TEXT_INPUT_PROPS]: jest.fn().mockReturnValue({
id: '1',
'pyb-answer': 'pybanswer',
label: 'label',
labelAdded: true
})
};

export const mutations = {
[types.MUTATE_ANCO_PYB_ANSWER]: jest.fn(),
[types.MUTATE_ANCO_DOC_URL]: jest.fn(),
[types.MUTATE_ANCO_ANNOTATION_URL]: jest.fn(),
[types.MUTATE_ANCO_ADD_LIST_ITEM]: jest.fn(),
};

export default {
state,
mutations,
actions: {},
getters
};
Loading

0 comments on commit 8194c84

Please sign in to comment.