Commit 0da86222 authored by Anton's avatar Anton

add components from systems-frontend

parent 286a4442
<template lang="pug">
div
q-chips-input(
v-model="tags",
dark,
:float-label="$t('labels.tags')",
chips-color="white",
chips-bg-color="primary")
</template>
<script>
export default {
data () {
return {
tags: []
}
},
watch: {
tags (val) {
this.$emit('updateTags', val)
}
}
}
</script>
<style scoped lang="stylus">
</style>
<template lang="pug">
div
q-card.shadow-6(v-if="env.IS_STAGING && resource")
q-card-title.text-grey-8 {{ $t('labels.access_control') }}
q-card-separator
q-card-main.no-padding
q-list(v-if="groups.length", no-border)
template(v-for="(group, index) in groups")
q-item.row.q-px-md(:class="{'q-py-md': $q.screen.lt.lg}")
q-item-main.ellipsis(:class="{'col-12': $q.screen.lt.lg}") {{ group.title }}
q-item-side.no-margin(:class="{'col-10 q-pt-sm': $q.screen.lt.lg}")
// span.q-mr-sm May:
q-checkbox(v-for="(checkbox, i) in checkboxes", v-model="group.model", :val="checkbox.title",
:class="{'q-mr-lg': i < checkboxes.length - 1, 'text-primary': group.model.includes(checkbox.title)}",
:checked-icon="checkbox.icon", :unchecked-icon="checkbox.icon")
.q-pl-sm(v-if="$q.screen.gt.sm") {{ checkbox.title }}
q-item-side.no-margin.text-right(:class="{'col-2 q-pt-sm': $q.screen.lt.lg}")
q-btn(@click="", :class="{'q-ml-xl': $q.screen.gt.md}", round)
q-icon(name="delete")
// q-item-separator.bg-grey-10(v-if="$q.screen.lt.lg")
q-item-separator.bg-grey-9
div(v-else) {{ $t('labels.empty') }}
//q-card-separator
<!--q-card-actions(:class="[!showForm ? 'q-pa-md' : 'q-px-md q-pb-md q-pt-none']")-->
<!--q-btn(v-if="!showForm", @click="showForm = true", :label="$t('labels.add_group')", color="primary")-->
<!--form-main.full-width(v-if="showForm", v-model="payload", :schema="schema")-->
<!--q-btn(slot="form-buttons-add", :label="$t('buttons.cancel')", @click="showForm = false, payloard = ''")-->
</template>
<script>
import FormMain from '../../../components/shared/forms/FormMain'
import { ObjectUtil } from 'mbjs-utils'
export default {
components: {
FormMain
},
props: [
'resource'
],
async mounted () {
await this.loadACL()
},
watch: {
async resource () {
await this.loadACL()
}
},
data () {
return {
acl: {},
env: process.env,
checked: [],
checkboxes: [{
title: this.$t('checkboxes.read'),
icon: 'remove_red_eye'
}, {
title: this.$t('checkboxes.write'),
icon: 'edit'
}, {
title: this.$t('checkboxes.delete'),
icon: 'clear'
}],
groups: [{
title: 'Hier steht ein Gruppentitel',
model: []
}, {
title: 'Ein weiterer Titel',
model: []
}, {
title: 'Klasse von Vorname Nachname',
model: []
}]
// payload: '',
// schema: {
// fields: {
// title: {
// fullWidth: true,
// type: 'text',
// label: 'labels.new_group_title',
// errorLabel: 'errors.field_required',
// validators: {
// required
// }
// }
// },
// submit: {
// label: _this.$t('labels.add_group'),
// handler () {
// _this.showForm = false
// return _this.groups.push({title: _this.payload.title, model: []})
// }
// }
// },
// showForm: false
}
},
methods: {
async loadACL () {
if (!this.resource) return
const aclQuery = {role: 'public', id: this.resource.id, permission: 'get'}
const permissions = await this.$store.dispatch('acl/isRoleAllowed', aclQuery)
this.acl.public = permissions.get === true
},
async setACL (action, payload, recursive = false) {
await this.$store.dispatch(action, payload)
if (recursive) {
const results = await this.$store.dispatch('annotations/find', { 'target.id': payload.id })
for (let item of results.items) {
const itemPayload = ObjectUtil.merge({}, payload)
itemPayload.uuid = item.uuid
await this.$store.dispatch(action, payload)
}
}
},
async updateACL () {
console.debug('setting acl...', this.acl)
if (this.acl.public) {
await this.setACL('acl/set', { role: 'public', id: this.timeline.id, permissions: ['get'] }, this.acl.recursive)
}
else {
await this.setACL('acl/remove', { role: 'public', id: this.timeline.id, permission: 'get' }, this.acl.recursive)
}
if (this.acl.group) {
await this.setACL('acl/set', { role: this.acl.group, id: this.timeline.id, permissions: ['get'] }, this.acl.recursive)
}
if (this.acl.group_remove) {
await this.setACL('acl/remove', { role: this.acl.group_remove, id: this.timeline.id, permission: 'get' }, this.acl.recursive)
}
this.$store.commit('notifications/addMessage', {
body: 'messages.acl_updated',
type: 'success'
})
}
}
}
</script>
<template lang="pug">
.annotation
.annotation-top
slot(name="annotation-timestamp").annotation-top-item.annotation-timestamp timestamp
.annotation-top-item.annotation-buttons
a(@click="EditForm ($event.target)") edit
a(@click="DeleteAnnotation ($event.target)") delete
.annotation-form
form-add
q-field(slot="form-middle-item")
q-input(value="value")
a(slot="form-bottom-item" @click="SaveEdit ($event.target)") Save changes
a(slot="form-bottom-item" @click="CancelEdit ($event.target)") Cancel
div copy-text
slot(name="annotation-text").text
slot(name="annotation-status").text
.annotation-buttons
slot(name="annotation-button")
</template>
<script>
import FormAdd from '../forms/FormAdd'
export default {
components: {
FormAdd
},
methods: {
CancelEdit (target) {
var el = target.parentElement.parentElement.parentElement.parentElement
console.log(el)
// el[0].style.display = 'none'
el[0].style.backgroundColor = 'red'
},
DeleteAnnotation () {
},
EditForm (target) {
var el = target.parentNode.parentNode.parentElement.getElementsByClassName('annotation-form')
el[0].style.display = 'block'
},
SaveEdit () {
}
}
// name: "annotation"
}
</script>
<style scoped>
.annotation {
padding: 1em;
border-bottom: 1px solid #eee;
}
.annotation-buttons * {
display: inline-block;
background-color: red;
margin-right: .2em;
padding: .2em .5em;
cursor: pointer;
}
.annotation-top {
display: inline-block;
padding: .2em .5em;
margin-right: .2em;
cursor: pointer;
width: 100%;
}
.annotation-form {
display: none;
}
</style>
<template lang="pug">
#content-bar
slot(name="content-bar-item")
div.search-bar
q-search
</template>
<script>
export default {}
</script>
<style scoped>
.search-bar {
width: 50%;
background-color: antiquewhite;
}
.content-bar-item {
color: black;
padding: .2em .5em;
border-radius: .2em;
background-color: #eee;
text-transform: uppercase;
}
#content-bar {
/* background-color: #eee; */
padding-bottom: .5em;
/*border-bottom: 2px solid black; */
/* margin: .5em 1em 1em; */
/* background: rgba( 185, 165, 130, .2 ); */
/* box-shadow: 0 0 10px 10px antiquewhite; */
}
#content-bar > * {
display: inline-block;
vertical-align: top;
margin: .5em;
}
.search-bar {
/*box-shadow: 0 0 20px 0 rgba( 0, 0, 0, .2 );
margin: 1em;*/
}
</style>
<template lang="pug">
span {{ userState ? userState.name : '' }}
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'CurrentUser',
computed: {
...mapGetters({
userState: 'auth/getUserState'
})
}
}
</script>
<template lang="pug">
q-modal(v-model="showModal", minimized)
.bg-dark.position-relative.q-pa-xl
slot(name="content")
slot(name="buttons")
q-btn.q-ml-lg(@click="close", :icon="closeIcon", round)
</template>
<script>
export default {
props: ['closeIcon'],
data () {
return {
showModal: false
}
},
methods: {
show () {
this.showModal = true
},
close () {
this.showModal = false
}
}
}
</script>
<template lang="pug">
modal(ref="modal")
template(slot="content")
slot(name="content")
.q-mt-md.text-center(slot="buttons")
q-btn.q-mx-sm(@click="confirm") {{ $t('buttons.yes') }}
q-btn.q-mx-sm(@click="cancel") {{ $t('buttons.no') }}
</template>
<script>
import Modal from './Modal'
export default {
props: ['payload'],
components: {
Modal
},
methods: {
show () {
this.$refs.modal.show()
},
confirm () {
this.$emit('confirm', this.payload)
this.cancel()
},
cancel () {
this.$emit('cancel')
this.$refs.modal.close()
}
}
}
</script>
<template lang="pug">
q-chips-input(
v-if="targetUuid",
v-model="tags", float-label="Add tags",
class="text-white", color="primary",
:dark="true", @change="inputChanged")
</template>
<script>
import constants from 'mbjs-data-models/src/constants'
export default {
props: ['targetUuid', 'targetType'],
data () {
return {
tags: [],
annotations: [{
body: {
value: 'Joe'
}
}]
}
},
async mounted () {
this.timeline = await this.$store.dispatch('maps/get', this.targetUuid)
await this.loadTags()
},
watch: {
async targetUuid (val) {
this.timeline = await this.$store.dispatch('maps/get', val)
await this.loadTags()
}
},
methods: {
inputChanged () {
this.updateTags()
},
enforceUniqueTags (tags) {
let uniqueTags = tags
if (tags.length > 1) {
let tagMap = {}
tags.forEach(t => {
tagMap[t] = 1
})
uniqueTags = Object.keys(tagMap)
}
// console.log('removed', tags.length - uniqueTags.length, 'tags')
return uniqueTags
},
updateTags () {
const _this = this
let annotationTags = this.annotations.map(a => {
return a.body.value
})
annotationTags = this.enforceUniqueTags(annotationTags)
// console.log(this.annotations, annotationTags)
this.tags = this.enforceUniqueTags(this.tags)
let tagsDelete = annotationTags.filter(at => {
return _this.tags.indexOf(at) === -1
})
// console.log('delete', tagsDelete)
tagsDelete = tagsDelete.map(t => {
let a = _this.annotations.find(a => {
return a.body.value === t
})
// console.log('remove', a.uuid, t)
if (a && a.uuid) return this.$store.dispatch('annotations/remove', a.uuid)
return null
})
let tagsAdd = this.tags.filter(t => {
return annotationTags.indexOf(t) === -1
})
// console.log('add', tagsAdd)
tagsAdd = tagsAdd.map(t => {
let annotation = {
body: {
purpose: 'tagging',
type: 'TextualBody',
value: t
},
target: {
id: _this.timeline.id,
type: _this.targetType || _this.typeFromRoute()
}
}
// console.log('add', t, annotation)
return this.$store.dispatch('annotations/create', annotation)
})
Promise.all([...tagsDelete, ...tagsAdd]).then(() => {
_this.loadTags()
})
},
typeFromRoute () {
let path = this.$route.path
if (/.+\/timelines\/[^/]+\/edit$/.test(path)) {
return constants.MAP_TYPE_TIMELINE
}
else if (/.+\/videos\/[^/]+\/edit$/.test(path)) {
return 'Video'
}
else if (/.+\/grids\/[^/]+\/edit$/.test(path)) {
return constants.MAP_TYPE_2D_GRID
}
else {
return 'Unknown'
}
},
loadTags () {
const _this = this
const query = { 'target.id': this.timeline.id, 'body.purpose': 'tagging' }
this.$store.dispatch('annotations/find', query)
.then(annotations => {
_this.annotations = annotations.filter(a => a.target.id === _this.timeline.id) // TODO: Anton, why is target id ignored in the query?
let newTags = annotations.map(a => {
// this.$store.dispatch('annotations/remove', a.uuid) // clean up tags
return a.body.value
})
newTags = this.enforceUniqueTags(newTags)
_this.tags = newTags
})
}
}
}
</script>
<style scoped lang="stylus">
</style>
<template lang="pug">
q-toolbar(color="dark")
// q-btn.hide-on-drawer-visible(flat, icon="menu", @click='$refs.drawer.open()')
q-toolbar-title(:padding='2')
//q-btn(:class="{ 'text-primary': currentApp === null }", big, flat,
@click="currentApp = null; $router.push({ name: 'site.welcome' })") Motionbank
q-btn(
:class="{ 'text-primary': currentApp === 'piecemaker' }",
@click="executeApp('piecemaker', 'piecemaker.timelines.list')",
big, flat
) Piecemaker
q-btn(
:color="currentApp === 'mosys' ? 'primary' : ''",
@click="executeApp('mosys', 'mosys.grids.list')",
big, flat
) Mosys
q-btn(v-if="userHasAssets",
:color="currentApp === 'assets' ? 'primary' : ''",
@click="executeApp('assets', 'assets.list')",
big, flat
) Assets
q-btn(color="primary", flat, icon="settings",
v-if="user", @click="$router.push({ name: 'users.manage' })") {{ user.profile ? user.profile.name : '' }}
q-btn(color="primary", flat, icon="eject",
v-if="user", @click="logout") {{ $t('navigation.logout') }}
q-btn(color="primary", flat, icon="arrow_forward",
v-if="!user", @click="login") {{ $t('navigation.login') }}
</template>
<script>
import { mapGetters } from 'vuex'
import userHasFeature from '../../../lib/user-has-feature'
export default {
data () {
return {
currentApp: null,
env: process.env
}
},
computed: {
...mapGetters({
user: 'auth/getUserState'
}),
userHasAssets () {
return userHasFeature(this.user, 'assets')
}
},
methods: {
executeApp (appName, routeName) {
this.currentApp = appName
this.$router.push({ name: routeName })
},
login () {
this.$auth.authenticate()
},
logout () {
this.$store.commit('auth/setUser', undefined)
this.$auth.logout()
}
}
}
</script>
<style></style>
<template lang="pug">
div
// div(v-for="u in usr", :key="ut")
div(v-for="timeline in u.timelines", :key="timeline")
div(v-for="tl in timeline", :key="tl") {{ tl }}
.row(v-for="u in usr", :key="u")
q-list.col-7.no-border.no-padding.margin-bottom(v-if="sc == 'timeline'")
q-item.item-hover
q-item-main ...is allowed to add videos to this timeline.
q-item-side.text-white
q-toggle(v-for="ut in u.timelines", v-model="ut.add", :key="ut")
q-item.item-hover
q-item-main ...is allowed to edit this timeline.
q-item-side.text-white
q-toggle(v-for="ut in u.timelines", v-model="ut.edit", :key="ut")
q-item.item-hover
q-item-main ...is allowed to delete this timeline.
q-item-side.text-white
q-toggle(v-for="ut in u.timelines", v-model="ut.delete", :key="ut")
q-item.item-hover
q-item-main ...is allowed to live annotate this timeline.
q-item-side.text-white
q-toggle(v-for="ut in u.timelines", v-model="ut.live_annotate", :key="ut")
q-list.col-7.no-border.no-padding.margin-bottom(v-if="sc == 'grid'")
q-item.item-hover
q-item-main ...is allowed to add videos to this grid.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to edit this grid.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to delete this grid.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to live annotate this grid.
q-item-side.text-white
q-toggle(v-model="toggle")
q-list.col-7.no-border.no-padding.margin-bottom(v-if="sc == 'timeline'")
q-item.item-hover
q-item-main ...is allowed to add videos.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to videos.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to delete videos.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to annotate videos.
q-item-side.text-white
q-toggle(v-model="toggle")
q-list.col-7.no-border.no-padding.margin-bottom(v-if="sc == 'timeline' || sc == 'grid'")
q-item.item-hover
q-item-main ...is allowed to add new users.
q-item-side.text-white
q-toggle(v-model="toggle")
q-item.item-hover
q-item-main ...is allowed to add remove users.
q-item-side.text-white
q-toggle(v-model="toggle")
.col-7.text-right(style="border-top: 1px solid white; padding-top: 1rem;")
q-btn save changes
</template>
<script>
export default {
props: ['user', 'scope'],
data () {
return {
usr: this.user,
sc: this.scope,
toggle: true
}
}
// name: "user-rights"
}
</script>
<style scoped>
.item-hover:hover {
background-color: rgba( 255, 255, 255, .1 );
}
.margin-bottom {
margin-bottom: 1rem;
}
</style>
<template lang="pug">
div.shadow-3(style="padding: 1rem;")
q-modal(v-model="openModal")
div.bg-black.q-pa-lg.row
h5.no-margin.no-padding.col-12 Send an invitation
form-main.col-12(
:schema="schemaMail"
)
// .text-center
q-btn(@click="openModal = false") Abort
div.q-px-md
h5.light-paragraph
| {{ headl }}
span.float-right
q-btn(@click="openModal = true") Add user
q-data-table(
@rowclick="onRowClick($event)",
:dark="true",
:data="users",
:config="conf",
:columns="cols",
:actions="actns"
)
template(slot="col-name", slot-scope="cell")
template(v-for="c in cell")
// span(v-if="c.status") {{ c.name }}
| {{ c.name }}
template.text-center(slot="col-confirmed", slot-scope="cell")
div.text-center(v-if="cell.data")
q-icon(name="done")
template(slot="col-action", slot-scope="cell")
q-btn(
flat,
small,
v-for="a in actions",
:color="a.color || 'neutral'",
:key="a.type",
@click="action(a.type, cell, a.scope)"
) {{ $t(a.title) }}
</template>
<script>
import FormMain from '../forms/FormMain'
import Username from './Username'
import { DateTime } from 'luxon'
import constants from '../../../lib/constants'
import { required } from 'vuelidate/lib/validators'
export default {
components: {
Username,
FormMain
},
// props: ['entries', 'config', 'columns', 'actions'],
props: ['columns', 'actions', 'headline'],
data () {
const _this = this
const defaultConfig = {
rowHeight: '50px',
noHeader: false,
leftStickyColumns: 0,