Commit b8d47cb2 authored by Anton's avatar Anton

Add pba vocabularies

parent 684af85d
......@@ -15,6 +15,7 @@ and this project adheres to
- Cell datatype available as vuex store module
- SwimLane component in post-annotator and on standalone page
- Annotations can have durations through target.selector.value
- PBA vocabularies (titles for pieces)
### Changed
......
......@@ -104,8 +104,9 @@
},
annotationText (text) {
if (!text) this.currentSelectorValue = undefined
else if (!this.selectedEntry) {
this.currentSelectorValue = this.getSelectorValue()
else if (!this.selectedEntry) this.currentSelectorValue = this.getSelectorValue()
if (this.$refs.vocabulary && this.$refs.vocabulary.visible) {
this.$refs.vocabulary.updateFilter(text)
}
},
selectedEntry (entry) {
......@@ -132,7 +133,7 @@
selectEntry (entry, andCreate = false) {
this.selectedEntry = entry
this.currentBody = ObjectUtil.merge({}, this.defaultBodyVocabulary, {
source: { id: entry.id }
source: { id: entry.id, type: entry.type }
})
if (andCreate) {
this.createAnnotation()
......@@ -169,7 +170,10 @@
}
else {
this.enterDown = 0
if (event.target.tagName.toLowerCase() !== 'textarea') this.setFocusOnInput() // only set focus if not already in a textfield
if (event.target.tagName.toLowerCase() !== 'textarea') {
// only set focus if not already in a textfield
this.setFocusOnInput()
}
}
},
onInputFocus () {
......@@ -193,9 +197,15 @@
}
}
}
if (!this.selectedEntry && this.annotationText) annotation.body.value = this.annotationText.trim()
if (!this.selectedEntry && this.annotationText) {
annotation.body.value = this.annotationText.trim()
}
else if (this.selectedEntry) {
annotation.body.value = this.selectedEntry.value
}
this.reset()
this.$emit('annotation', annotation)
console.debug('emit annotation', annotation)
}
}
}
......
......@@ -20,42 +20,46 @@
div.text-primary {{ newVocabularyEntry }}
div into your vocabularies?
.q-pa-md(v-if="visible")
q-btn.q-px-lg.q-mr-sm(v-for="vocabulary in vocabularies",
@click="selectVocabulary(vocabulary)", size="sm") {{ vocabulary.title }}
.q-pa-md(v-if="visible && !loading")
q-btn.q-px-lg.q-mr-sm(v-for="vocabulary in vocabularyLabels.slice(0, 3)",
@click="selectVocabulary(vocabulary.id)", size="sm") {{ vocabulary.label }}
div(ref="tagList", v-if="visible", style="max-height: 66vh; overflow-y: scroll;")
.q-mt-lg.q-mb-lg(v-if="loading")
q-spinner.q-mr-lg(:size="30")
span Loading vocabularies...
// LIST RESULTS
//
.q-pa-sm(v-if="selectedVocabulary")
// (todo: most used?)
q-list.no-border.no-margin.no-padding
q-item.no-padding.moba-tag-hover(v-for="(entry, i) in selectedVocabulary.entries", :key="`entry-${entry.id}-${i}`",
q-item.no-padding.moba-tag-hover(v-for="(entry, i) in entries", :key="`entry-${entry.id}-${i}`",
:class="{ 'bg-grey-9': highlight && entry.id === highlight.id }")
// q-item-side.q-px-sm.q-caption(style="min-width: 5rem;")
span.text-grey-6 {{ getInitials(tag.title) }}
q-item-side.q-px-sm.q-py
// q-item-side.q-px-sm.q-py
// div(v-if="!pressedAlt")
div
q-btn.text-primary(no-caps, round, size="sm") {{ getInitials(entry.value) }}
// div
// q-btn.text-primary(no-caps, round, size="sm") {{ getInitials(entry.value) }}
q-btn.text-grey-8.cursor-pointer.no-margin(
icon="keyboard",
round, size="sm",
@click="enterSetShortcut(entry.id)") {{ getShortcutKey(entry) }}
// q-btn.text-grey-8.cursor-pointer.no-margin(
// icon="keyboard",
// round, size="sm",
// @click="enterSetShortcut(entry.id)") {{ getShortcutKey(entry) }}
// div(v-else)
.text-primary {{ tag.shortcutKey.value }}
// .text-primary {{ tag.shortcutKey.value }}
q-item-main
q-btn.full-width(
v-shortkey="entry.key",
@shortkey.native="selectEntry(entry.id)",
@dblclick.native="selectEntry(entry.id, true)",
@click="selectEntry(entry.id)",
@shortkey.native="selectEntry(entry)",
@dblclick.native="selectEntry(entry, true)",
@click="selectEntry(entry)",
no-caps, flat, align="left",
color="transparent")
.text-white.text-weight-regular {{ entry.value }}
......@@ -66,6 +70,8 @@
</template>
<script>
import { mapGetters } from 'vuex'
import { userHasFeature } from 'mbjs-quasar/src/lib'
import ModalConfirm from '../../shared/dialogs/ModalConfirm'
export default {
......@@ -78,9 +84,11 @@
data () {
return {
visible: false,
loading: false,
vocabularies: [],
selectedVocabulary: undefined,
filterValue: undefined,
shortcuts: {},
keyBlacklist: ['enter', '#', 'arrowdown', 'tab', 'delete', 'alt'],
......@@ -89,15 +97,34 @@
newShortcutEntry: undefined
}
},
computed: {
...mapGetters({
user: 'auth/getUserState',
vocabularyLabels: 'vocabularies/getLabels'
}),
entries () {
if (this.selectedVocabulary && this.filterValue) {
return this.selectedVocabulary
.filter(entry => entry.value.toLocaleLowerCase().indexOf(this.filterValue) > -1)
}
return this.selectedVocabulary
}
},
async mounted () {
window.addEventListener('keypress', this.onKeyPress)
this.loading = true
if (userHasFeature(this.user, 'pba')) await this.$store.dispatch('vocabularies/loadPBATitles', 4)
if (this.vocabularyLabels.length) this.selectVocabulary(this.vocabularyLabels[0].id)
for (let key of Object.keys(this.shortcuts)) {
if (Array.isArray(this.shortcuts[key])) {
this.keyBlacklist = this.keyBlacklist.concat(this.shortcuts[key])
}
}
this.vocabularies = await this.$vocabularies.find()
if (this.vocabularies && this.vocabularies.length > 0) this.selectVocabulary(this.vocabularies[0])
this.loading = false
},
beforeDestroy () {
window.removeEventListener('keypress', this.onKeyPress)
......@@ -106,23 +133,22 @@
toggle () {
this.visible = !this.visible
},
selectVocabulary (vocabulary) {
this.selectedVocabulary = vocabulary
async selectVocabulary (id) {
this.selectedVocabulary = await this.$store.dispatch('vocabularies/get', id)
},
async addEntry (value) {
async addEntry () {
if (this.selectedVocabulary) {
await this.selectedVocabulary.addTerm(value)
// await this.selectedVocabulary.addTerm(value)
}
},
async selectEntry (id, createImmediatly = false) {
const entry = await this.selectedVocabulary.get(id)
async selectEntry (entry, createImmediatly = false) {
this.$emit('select-entry', entry, createImmediatly)
},
async enterSetShortcut (val) {
this.isSetShortcut = true
this.$refs.shortcutModal.show()
const result = await this.selectedVocabulary.find({ id: val })
if (result.length) this.newShortcutEntry = result[0]
async enterSetShortcut () {
// this.isSetShortcut = true
// this.$refs.shortcutModal.show()
// const result = await this.selectedVocabulary.find({ id: val })
// if (result.length) this.newShortcutEntry = result[0]
},
exitSetShortcut () {
this.isSetShortcut = false
......@@ -131,9 +157,9 @@
},
async setShortcut () {
// TODO: store it properly!
console.debug('set shortcut', this.newShortcut, this.newShortcutEntry)
await this.selectedVocabulary.setKey(this.newShortcutEntry.id, this.newShortcut)
this.exitSetShortcut()
// console.debug('set shortcut', this.newShortcut, this.newShortcutEntry)
// await this.selectedVocabulary.setKey(this.newShortcutEntry.id, this.newShortcut)
// this.exitSetShortcut()
},
getInitials (val) {
return val.split(' ')
......@@ -161,6 +187,11 @@
else if (key === '#') {
// TODO: filter terms
}
},
updateFilter (value) {
value = value.trim()
if (value && !value.length) this.filterValue = undefined
else this.filterValue = value.toLocaleLowerCase()
}
}
}
......
......@@ -335,7 +335,6 @@
if (this.video) {
this.metadata = await this.$store.dispatch('metadata/getLocal', this.video)
}
// console.log('video', this.video)
},
async getAnnotations () {
const
......@@ -352,7 +351,7 @@
}
const results = await this.$store.dispatch('annotations/find', query)
for (let item of results.items) {
if (item.body.type === 'VocabularyEntry') {
if (item.body.type === 'VocabularyEntry' && !item.body.value) {
const entry = await this.$vocabularies.getEntry(item.body.source.id)
item.body.value = entry.value
}
......@@ -371,7 +370,7 @@
const payload = ObjectUtil.merge(annotation, { target })
console.debug('create annotation', target, payload)
const result = await this.$store.dispatch('annotations/post', payload)
if (result.body.type === 'VocabularyEntry') {
if (result.body.type === 'VocabularyEntry' && !result.body.value) {
const entry = await this.$vocabularies.getEntry(result.body.source.id)
result.body.value = entry.value
}
......
......@@ -26,7 +26,8 @@ import {
metadata,
mosys,
notifications,
swimLaneSettings
swimLaneSettings,
vocabularies
} from './modules'
/** Instantiate Motion Bank API Client */
......@@ -66,7 +67,8 @@ const store = new Vuex.Store({
metadata,
mosys,
notifications,
swimLaneSettings
swimLaneSettings,
vocabularies
}
})
......
......@@ -9,6 +9,7 @@ import metadata from './metadata'
import tags from './tags'
import files from './files'
import swimLaneSettings from './swim-lane-settings'
import vocabularies from './vocabularies'
export {
auth,
......@@ -21,5 +22,6 @@ export {
metadata,
mosys,
notifications,
swimLaneSettings
swimLaneSettings,
vocabularies
}
import axios from 'axios'
const vocabularies = {
namespaced: true,
state: {
scopes: [],
scopedLabels: {},
scopedTerms: {}
},
getters: {
getLabels: state => {
return state.scopes
.filter(scope => state.scopedTerms[scope] && state.scopedTerms[scope].length)
.map(scope => {
return {
id: scope,
label: state.scopedLabels[scope]
}
})
}
},
actions: {
async loadPBATitles (context, limit = 0) {
console.log(limit)
// let count = 0
const headers = {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
const result = await axios.get(`${process.env.API_HOST}/pba/pieces`, { headers })
const pieces = result.data.sort((a, b) => a.label.localeCompare(b.label))
for (let piece of pieces) {
const result = await axios.get(`${process.env.API_HOST}/pba/pieces/${piece.piece_id}/titles`, {headers})
context.commit('addTermsForScope', [piece.piece_id, result.data.map(title => {
return {
value: title.label,
id: title.title,
type: 'PBATitle'
}
}).sort((a, b) => a.value.localeCompare(b.value))])
context.commit('setScopeLabel', [piece.piece_id, piece.label])
}
},
get (context, id) {
return context.state.scopedTerms[id]
}
},
mutations: {
addTermsForScope (state, [scope, terms]) {
if (!Array.isArray(terms)) throw new Error('terms must be type array')
if (state.scopes.indexOf(scope) === -1) state.scopes.push(scope)
if (!Array.isArray(state.scopedTerms[scope])) state.scopedTerms[scope] = terms
else state.scopedTerms[scope] = state.scopedTerms[scope].concat(terms)
},
setScopeLabel (state, [scope, label]) {
state.scopedLabels[scope] = label
}
}
}
export default vocabularies
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment