- Complete GGZ Ecademy Nuxt.js user portal - Learning products browser and management - Member management interface - User authentication and roles - Multi-language support (NL/EN) - Vuex store for state management - Component-based architecture
This commit is contained in:
604
components/Learning/ProductOverview/Accreditation.vue
Normal file
604
components/Learning/ProductOverview/Accreditation.vue
Normal file
@@ -0,0 +1,604 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.accreditation')">
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="accreditations"
|
||||
:options="options"
|
||||
hide-default-footer
|
||||
item-key="accreditation"
|
||||
flat
|
||||
v-if="hasAccreditations"
|
||||
>
|
||||
<!-- Translates dynamically headers -->
|
||||
<template v-for="h in headers" v-slot:[`header.${h.value}`]="{ header }">
|
||||
{{ h.text ? $t(`learning.accreditation.${h.text}`) : '' }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.register="{ item }">
|
||||
{{ getFilterItem('register', item).title }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.date_start="{ item }">
|
||||
{{ formatDate(item.date_start) }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.date_end="{ item }">
|
||||
{{ formatDate(item.date_end) }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-menu
|
||||
offset-y
|
||||
v-if="
|
||||
editMode && ($store.getters.isAdmin || $store.getters.isOperator)
|
||||
"
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-hover v-slot:default="{ hover }">
|
||||
<v-btn
|
||||
:color="hover ? 'info' : ''"
|
||||
:outlined="hover"
|
||||
depressed
|
||||
fab
|
||||
small
|
||||
v-on="on"
|
||||
>
|
||||
<v-icon>icon-options</v-icon>
|
||||
</v-btn>
|
||||
</v-hover>
|
||||
</template>
|
||||
<v-list width="200">
|
||||
<v-list-item @click="editItem(item)">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-edit</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>{{
|
||||
$t('general.edit') | capitalize
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-dialog max-width="740" persistent v-model="dialogDelete">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-list-item v-on="on">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-remove</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>{{
|
||||
$t('general.delete') | capitalize
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-card class="primary pa-10" flat>
|
||||
<v-card-title class="headline">
|
||||
{{ $t('learning.delete_accreditation_confirmation') }}
|
||||
</v-card-title>
|
||||
<v-card-actions>
|
||||
<div class="ma-4">
|
||||
<v-btn
|
||||
@click="deleteItem(item)"
|
||||
class="mx-2"
|
||||
color="accent"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.delete') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
@click="dialogDelete = false"
|
||||
class="mx-2"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</div>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<v-dialog
|
||||
v-model="dialogAccreditation"
|
||||
max-width="75%"
|
||||
v-if="editMode && ($store.getters.isAdmin || $store.getters.isOperator)"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn
|
||||
class="cta-secondary my-10"
|
||||
block
|
||||
depressed
|
||||
min-height="60px"
|
||||
:disabled="isCreateMode"
|
||||
v-on="on"
|
||||
@click="resetAccreditationsFilters"
|
||||
>
|
||||
<v-icon x-small class="mx-4">icon-add</v-icon>
|
||||
|
||||
{{ $t('learning.add_new_accreditation') }}</v-btn
|
||||
>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline">{{ formTitle }}</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t(`learning.filters.register`)
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="register"
|
||||
:editMode="editMode"
|
||||
target="accreditations"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-text-field
|
||||
v-model="editedItem.credits"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.accreditation_period')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9" class="d-flex pl-2">
|
||||
<v-menu
|
||||
ref="menuStart"
|
||||
v-model="menuStart"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
margin-top="20px"
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`accreditation-start-date-${Math.random()}`"
|
||||
v-model="computedDateFormattedStart"
|
||||
append-icon="icon-events"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
readonly
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.date_start"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuStart = false">Cancel</v-btn>
|
||||
<v-btn
|
||||
text
|
||||
@click="$refs.menuStart.save(editedItem.date_start)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
<span class="mx-5 my-3 font-weight-bold">
|
||||
tot
|
||||
</span>
|
||||
<v-menu
|
||||
ref="menuEnd"
|
||||
v-model="menuEnd"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`accreditation-end-date-${Math.random()}`"
|
||||
v-model="computedDateFormattedEnd"
|
||||
append-icon="icon-events"
|
||||
readonly
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.date_end"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuEnd = false">Cancel</v-btn>
|
||||
<v-btn text @click="$refs.menuEnd.save(editedItem.date_end)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider />
|
||||
<v-card-actions v-if="editMode">
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
:disabled="loading"
|
||||
@click="save"
|
||||
>{{ $t('general.save') }}</v-btn
|
||||
>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="txt"
|
||||
depressed
|
||||
text
|
||||
:disabled="loading"
|
||||
@click="close"
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<p v-if="isCreateMode" class="text-center">
|
||||
Bij het aanmaken van een nieuw product kiest u eerst voor 'Opslaan' om
|
||||
deze functie te activeren.
|
||||
</p>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
import universalFilterSelector from '@/components/UniversalFilterSelector/UniversalFilterSelector'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
universalFilterSelector,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isCreateMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
itemsPerPage: -1,
|
||||
},
|
||||
headers: [
|
||||
{ text: 'register', value: 'register' },
|
||||
{ text: 'credits', value: 'credits' },
|
||||
{ text: 'date_start', value: 'date_start' },
|
||||
{ text: 'date_end', value: 'date_end' },
|
||||
{ text: '', value: 'actions' },
|
||||
],
|
||||
accreditationEditMode: false,
|
||||
dialogAccreditation: false,
|
||||
dialogDelete: false,
|
||||
editedIndex: -1,
|
||||
editedItem: {
|
||||
date_start: '',
|
||||
date_end: '',
|
||||
credits: '',
|
||||
},
|
||||
defaultItem: {
|
||||
date_start: '',
|
||||
date_end: '',
|
||||
credits: '',
|
||||
},
|
||||
loading: false,
|
||||
date: null,
|
||||
menuStart: false,
|
||||
menuEnd: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
remote() {
|
||||
return this.$store.state.learning.remote
|
||||
},
|
||||
local() {
|
||||
return this.$store.state.learning.local
|
||||
},
|
||||
accreditations() {
|
||||
if (!this.local || !Array.isArray(this.local.accreditations)) return []
|
||||
return this.local.accreditations
|
||||
},
|
||||
hasAccreditations() {
|
||||
if (!this.accreditations) return false
|
||||
return this.accreditations.length > 0
|
||||
},
|
||||
formTitle() {
|
||||
return this.editedIndex === -1
|
||||
? this.$t('learning.new_accreditation')
|
||||
: this.$t('learning.edit_accreditation')
|
||||
},
|
||||
accreditationsFiltersSelected() {
|
||||
return this.$store.state.learning.accreditationsFiltersSelected
|
||||
},
|
||||
computedDateFormattedStart() {
|
||||
return this.formatDate(this.editedItem.date_start)
|
||||
},
|
||||
computedDateFormattedEnd() {
|
||||
return this.formatDate(this.editedItem.date_end)
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
dialogAccreditation(val) {
|
||||
val || this.close()
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getFilterItem(filterTitle, accreditation) {
|
||||
const filter = this.$store.getters.getFilterByTitle(filterTitle)
|
||||
|
||||
const arrayTmp = []
|
||||
if (!accreditation.filters) return {}
|
||||
accreditation.filters.forEach((f) => {
|
||||
const filterItemTmp = this.$store.getters.getFilterItemById(
|
||||
f.filter_item_id
|
||||
)
|
||||
arrayTmp.push(filterItemTmp)
|
||||
})
|
||||
|
||||
const filterItem = arrayTmp.find((e) => e.filter_id === filter.id)
|
||||
return filterItem || {}
|
||||
},
|
||||
formatDate(date) {
|
||||
if (!date) return null
|
||||
|
||||
const [year, month, day, time] = date.replace(' ', '-').split('-')
|
||||
return `${day}/${month}/${year}`
|
||||
},
|
||||
|
||||
resetAccreditationsFilters() {
|
||||
this.$store.commit('learning/RESET_ACCREDITATIONS_FILTERS')
|
||||
},
|
||||
|
||||
setAccreditationsFilters(item) {
|
||||
item.filters.forEach(async (f) => {
|
||||
const filterItem = this.$store.getters.getFilterItemById(
|
||||
f.filter_item_id
|
||||
)
|
||||
|
||||
await this.$store.commit('learning/UPDATE_FILTERS', {
|
||||
filterId: filterItem.filter_id,
|
||||
target: 'accreditations',
|
||||
value: f.filter_item_id,
|
||||
})
|
||||
})
|
||||
|
||||
this.editedIndex = this.accreditations.indexOf(item)
|
||||
this.editedItem = Object.assign({}, item)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
|
||||
close() {
|
||||
this.dialogAccreditation = false
|
||||
this.$nextTick(() => {
|
||||
this.editedItem = Object.assign({}, this.defaultItem)
|
||||
this.editedIndex = -1
|
||||
})
|
||||
},
|
||||
|
||||
setFiltersSelectedInEditedItem() {
|
||||
let accreditationFiltersItemsIds = []
|
||||
|
||||
for (const [key, value] of Object.entries(
|
||||
this.accreditationsFiltersSelected
|
||||
)) {
|
||||
accreditationFiltersItemsIds.push(value)
|
||||
}
|
||||
|
||||
this.editedItem['filter_items'] = accreditationFiltersItemsIds
|
||||
},
|
||||
|
||||
editItem(item) {
|
||||
if (!this.editMode) return
|
||||
this.setAccreditationsFilters(item)
|
||||
this.dialogAccreditation = true
|
||||
},
|
||||
|
||||
async deleteItem(item) {
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
if (!item.id) {
|
||||
this.$notifier.showMessage({
|
||||
content: `No accredication to delete selected`,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(`/accreditations/${item.id}`)
|
||||
|
||||
this.$store.commit('learning/DELETE_ACCREDITATION_LOCAL', item)
|
||||
|
||||
this.dialogDelete = false
|
||||
this.dialogAccreditation = false
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Accreditation deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
} catch (error) {
|
||||
this.$nuxt.$loading.finish()
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to delete the selected accreditation`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async save() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
|
||||
// Edit mode
|
||||
if (this.editedIndex > -1) {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.setFiltersSelectedInEditedItem()
|
||||
|
||||
const response = await this.$axios.post(
|
||||
'/accreditations',
|
||||
this.editedItem
|
||||
)
|
||||
|
||||
this.$store.commit('learning/EDIT_ACCREDITATION_LOCAL', {
|
||||
index: this.editedIndex,
|
||||
accreditation: response.data,
|
||||
})
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Accreditation stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the accreditation`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
// Create new mode
|
||||
} else {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.setFiltersSelectedInEditedItem()
|
||||
|
||||
const response = await this.$axios.post(
|
||||
'/accreditations',
|
||||
this.editedItem
|
||||
)
|
||||
|
||||
this.dialog = false
|
||||
|
||||
this.$store.commit('learning/ADD_ACCREDITATION_LOCAL', response.data)
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Accreditation stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the accreditation`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
this.loading = false
|
||||
this.close()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-application >>> .v-menu__content{
|
||||
top: 230px !important;
|
||||
}
|
||||
.v-card >>> table,
|
||||
.v-card >>> .v-data-table-header tr,
|
||||
.v-card >>> .v-data-footer {
|
||||
background-color: var(--v-primary-base);
|
||||
}
|
||||
.v-card >>> .v-data-table-header th span {
|
||||
color: var(--v-tertiary-base);
|
||||
}
|
||||
.v-card >>> .text-start,
|
||||
.v-card >>> .v-icon,
|
||||
.v-dialog__content >>> .v-subheader,
|
||||
.v-dialog__content >>> i {
|
||||
color: var(--v-txt-base);
|
||||
font-weight: bold;
|
||||
}
|
||||
.v-dialog__content >>> .v-dialog {
|
||||
border: 4px solid var(--v-secAccent-base);
|
||||
/* box-shadow: inset 0px 0px 2px 2px var(--v-secAccent-base),
|
||||
inset 6px 6px 14px -14px var(--v-secAccent-base) !important; */
|
||||
}
|
||||
.v-dialog .v-card {
|
||||
background: var(--v-secondary-base);
|
||||
}
|
||||
|
||||
.v-dialog__content >>> .v-input__slot {
|
||||
background: var(--v-primary-base);
|
||||
border: 1px solid var(--v-lines-base);
|
||||
}
|
||||
.v-menu__content >>> .v-date-picker-table {
|
||||
height: 242px !important;
|
||||
}
|
||||
</style>
|
||||
262
components/Learning/ProductOverview/Administration.vue
Normal file
262
components/Learning/ProductOverview/Administration.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.administration')">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black in_the_picture"
|
||||
>Van leden voor leden</v-subheader
|
||||
>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9" class="mb-4 d-flex flex-column">
|
||||
<div class="pb-0 mb-0 d-flex">
|
||||
<v-switch
|
||||
:disabled="!editMode"
|
||||
inset
|
||||
class="my-3 toggle"
|
||||
v-model="for_members"
|
||||
/>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.owner')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="owner"
|
||||
:placeholder="$t('learning.product_overview.placeholder.description')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.partner')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="partner"
|
||||
:placeholder="$t('learning.product_overview.placeholder.description')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Leverancier
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="supplier"
|
||||
:placeholder="$t('learning.product_overview.placeholder.description')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.contract_agreements')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<quill-editor
|
||||
v-model="contract_agreements"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
@focus="isEditorFocused = true"
|
||||
@blur="isEditorFocused = false"
|
||||
@change="onEditorChange()"
|
||||
:class="{ focused: isEditorFocused }"
|
||||
v-if="editMode"
|
||||
/>
|
||||
|
||||
<span v-html="contract_agreements" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Prognose gebruik aantal leden
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="prognosis_members"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Prognose gebruik aantal deelnemers
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="prognosis_attendees"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import 'quill/dist/quill.bubble.css'
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
quillEditor,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditorFocused: false,
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: [
|
||||
[{ size: ['small', false, 'large'] }],
|
||||
['bold', 'italic'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }],
|
||||
['link'],
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
local() {
|
||||
return this.$store.state.learning.local
|
||||
},
|
||||
owner: {
|
||||
get() {
|
||||
return this.local.owner || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'owner',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
partner: {
|
||||
get() {
|
||||
return this.local.partner || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'partner',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
supplier: {
|
||||
get() {
|
||||
return this.local.supplier || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'supplier',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
contract_agreements: {
|
||||
get() {
|
||||
return this.local.contract_agreements || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'contract_agreements',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
prognosis_members: {
|
||||
get() {
|
||||
return this.local.prognosis_members || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'prognosis_members',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
prognosis_attendees: {
|
||||
get() {
|
||||
return this.local.prognosis_attendees || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'prognosis_attendees',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
for_members: {
|
||||
get() {
|
||||
return this.local.for_members
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'for_members',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onEditorChange() {
|
||||
if (!this.isEditorFocused) this.isEditorFocused = true
|
||||
// console.log('editor change!', editor)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
603
components/Learning/ProductOverview/Basic.vue
Normal file
603
components/Learning/ProductOverview/Basic.vue
Normal file
@@ -0,0 +1,603 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.basic')">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.title')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="title"
|
||||
:rules="rules.title"
|
||||
:placeholder="$t('learning.product_overview.placeholder.titel')"
|
||||
:hide-details="!editMode"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
required
|
||||
error
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode"></v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.code')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="code"
|
||||
:placeholder="$t('learning.product_overview.placeholder.productcode')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
:rules="rules.code"
|
||||
required
|
||||
error
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black in_the_picture"
|
||||
>Van leden voor leden</v-subheader
|
||||
>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9" class="mb-4 d-flex flex-column">
|
||||
<div class="pb-0 mb-0 d-flex">
|
||||
<v-switch
|
||||
:disabled="!editMode"
|
||||
inset
|
||||
class="my-3 toggle"
|
||||
v-model="for_members"
|
||||
/>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black"> Url </v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="url"
|
||||
:placeholder="$t('learning.product_overview.placeholder.url')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.status')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector filterTitle="status" :editMode="editMode" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Tegel afbeelding
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<vue-dropzone
|
||||
ref="imgDropZoneTile"
|
||||
class="cta-secondary my-4"
|
||||
id="customdropzoneTile"
|
||||
:options="dropzoneOptions"
|
||||
@vdropzone-complete="afterCompleteTile"
|
||||
v-if="editMode"
|
||||
/>
|
||||
|
||||
<v-img
|
||||
:src="tileComputed || noImage"
|
||||
:lazy-src="noImage"
|
||||
contain
|
||||
v-cloak
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode" class="mt-12">
|
||||
{{ $t('learning.product_overview.allowed') }} <br />
|
||||
{{ $t('learning.product_overview.allowed2') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('general.image')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<vue-dropzone
|
||||
ref="imgDropZoneCover"
|
||||
class="cta-secondary my-4"
|
||||
id="customdropzone"
|
||||
:options="dropzoneOptions"
|
||||
@vdropzone-complete="afterCompleteCover"
|
||||
v-if="editMode"
|
||||
/>
|
||||
|
||||
<v-img
|
||||
:src="coverComputed || noImage"
|
||||
:lazy-src="noImage"
|
||||
contain
|
||||
v-cloak
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode" class="mt-12">
|
||||
{{ $t('learning.product_overview.allowed') }} <br />
|
||||
{{ $t('learning.product_overview.allowed2') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">Video</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<v-text-field
|
||||
v-model="video"
|
||||
prepend-inner-icon="mdi-youtube"
|
||||
:placeholder="$t('learning.product_overview.placeholder.trailer')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
v-if="editMode"
|
||||
class="youtube"
|
||||
/>
|
||||
|
||||
<iframe
|
||||
v-if="video"
|
||||
width="100%"
|
||||
height="480"
|
||||
frameborder="0"
|
||||
scrolling="auto"
|
||||
marginheight="0"
|
||||
marginwidth="0"
|
||||
:src="video"
|
||||
allowfullscreen
|
||||
msallowfullscreen
|
||||
allow="fullscreen"
|
||||
></iframe>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode">
|
||||
{{ $t('learning.product_overview.allowed_trailer') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.duration')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="lead_time"
|
||||
:placeholder="$t('learning.product_overview.duration')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.level') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
id="level"
|
||||
filterTitle="level"
|
||||
:editMode="editMode"
|
||||
filterType="mixed"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
SEO Title
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="seo_title"
|
||||
:placeholder="$t('learning.product_overview.placeholder.seo_title')"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
:rules="rules.seo_title"
|
||||
required
|
||||
error
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Meta description
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-textarea
|
||||
v-model="meta_description"
|
||||
:placeholder="
|
||||
$t('learning.product_overview.placeholder.meta_description')
|
||||
"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:disabled="!editMode"
|
||||
:flat="!editMode"
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Synoniemen
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<synonyms-selector :editMode="editMode" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
import universalFilterSelector from '@/components/UniversalFilterSelector/UniversalFilterSelector'
|
||||
import synonymsSelector from '@/components/Learning/SynonymsSelector'
|
||||
import vueDropzone from 'vue2-dropzone'
|
||||
import 'vue2-dropzone/dist/vue2Dropzone.min.css'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
vueDropzone,
|
||||
universalFilterSelector,
|
||||
synonymsSelector,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
date: new Date().toISOString().substr(0, 7),
|
||||
menu: false,
|
||||
modal: false,
|
||||
dialog: false,
|
||||
valid: true,
|
||||
lazy: false,
|
||||
loading: false,
|
||||
dropzoneOptions: {
|
||||
url: 'https://httpbin.org/post',
|
||||
maxFilesize: 1.2, // MB
|
||||
maxFiles: 1,
|
||||
thumbnailWidth: 150,
|
||||
thumbnailHeight: 150,
|
||||
addRemoveLinks: true,
|
||||
acceptedFiles: '.jpg, .jpeg, .png',
|
||||
dictDefaultMessage: `<p><i class='icon icon-image mr-2'></i> Upload afbeelding</p>`,
|
||||
},
|
||||
images: [],
|
||||
rules: {
|
||||
// title: [(v) => 'De titel is verplicht'],
|
||||
// code: [(v) => !!v || 'De productcode is verplicht'],
|
||||
// seo_title: [(v) => !!v || 'De SEO-titel is verplicht'],
|
||||
title: [(v) => 'De titel is verplicht'],
|
||||
code: [(v) => 'De productcode is verplicht'],
|
||||
seo_title: [(v) => 'De SEO-titel is verplicht'],
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
local() {
|
||||
return this.$store.getters.localProduct
|
||||
},
|
||||
|
||||
title: {
|
||||
get() {
|
||||
return this.local.title
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', { field: 'title', value })
|
||||
},
|
||||
},
|
||||
code: {
|
||||
get() {
|
||||
return this.local.code
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', { field: 'code', value })
|
||||
},
|
||||
},
|
||||
|
||||
for_members: {
|
||||
get() {
|
||||
return this.local.for_members
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'for_members',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
status: {
|
||||
get() {
|
||||
return this.local.status
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', { field: 'status', value })
|
||||
},
|
||||
},
|
||||
video: {
|
||||
get() {
|
||||
return this.local.video
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', { field: 'video', value })
|
||||
},
|
||||
},
|
||||
lead_time: {
|
||||
get() {
|
||||
return this.local.lead_time
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'lead_time',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
seo_title: {
|
||||
get() {
|
||||
return this.local.seo_title
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'seo_title',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
meta_description: {
|
||||
get() {
|
||||
return this.local.meta_description
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'meta_description',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
url: {
|
||||
get() {
|
||||
return this.local.url
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'url',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
level: {
|
||||
get() {
|
||||
return this.local.level
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'level',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
levelItems() {
|
||||
if (!this.$store.getters.filters.length > 0) return []
|
||||
return this.$store.getters.filters.find(
|
||||
(filter) => filter.title === 'level'
|
||||
).items
|
||||
},
|
||||
|
||||
cover() {
|
||||
return this.local.cover
|
||||
},
|
||||
|
||||
coverComputed() {
|
||||
if (this.$store.state.learning.cover.url)
|
||||
return this.$store.state.learning.cover.url
|
||||
if (this.local.cover) return this.local.cover.full
|
||||
return null
|
||||
},
|
||||
|
||||
tile() {
|
||||
return this.local.tile
|
||||
},
|
||||
|
||||
tileComputed() {
|
||||
if (this.$store.state.learning.tile.url)
|
||||
return this.$store.state.learning.tile.url
|
||||
if (this.local.tile) return this.local.tile.full
|
||||
return null
|
||||
},
|
||||
noImage() {
|
||||
return require(`@/assets/img/no_image.png`)
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
async afterCompleteTile(file) {
|
||||
if (file === undefined) return
|
||||
if (file.name.lastIndexOf('.') <= 0) return
|
||||
|
||||
if (file.size > 2000000) {
|
||||
this.$notifier.showMessage({
|
||||
content: `Exceeded Max filesize`,
|
||||
color: 'error',
|
||||
icon: 'mdi-alert-circle',
|
||||
})
|
||||
this.$store.commit('learning/RESET_TILE')
|
||||
return
|
||||
}
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
try {
|
||||
const fr = new FileReader()
|
||||
fr.readAsDataURL(file)
|
||||
fr.addEventListener('load', () => {
|
||||
this.$store.commit('learning/UPDATE_TILE', {
|
||||
name: file.name,
|
||||
url: fr.result,
|
||||
file: file,
|
||||
})
|
||||
})
|
||||
this.isLoading = false
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
this.$refs.imgDropZoneTile.removeFile(file)
|
||||
},
|
||||
|
||||
async afterCompleteCover(file) {
|
||||
if (file === undefined) return
|
||||
if (file.name.lastIndexOf('.') <= 0) return
|
||||
|
||||
if (file.size > 2000000) {
|
||||
this.$notifier.showMessage({
|
||||
content: `Exceeded Max filesize`,
|
||||
color: 'error',
|
||||
icon: 'mdi-alert-circle',
|
||||
})
|
||||
this.$store.commit('learning/RESET_COVER')
|
||||
return
|
||||
}
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
try {
|
||||
const fr = new FileReader()
|
||||
fr.readAsDataURL(file)
|
||||
fr.addEventListener('load', () => {
|
||||
this.$store.commit('learning/UPDATE_COVER', {
|
||||
name: file.name,
|
||||
url: fr.result,
|
||||
file: file,
|
||||
})
|
||||
})
|
||||
this.isLoading = false
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
this.$refs.imgDropZoneCover.removeFile(file)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#level >>> .v-input__slot .v-select__slot {
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.image-div {
|
||||
display: flex;
|
||||
margin: 25px;
|
||||
}
|
||||
.image {
|
||||
max-width: 250px;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
#customdropzone {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
#customdropzone >>> .icon {
|
||||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
#customdropzone >>> p {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mt-12 {
|
||||
margin-top: 35px !important;
|
||||
}
|
||||
|
||||
.v-input >>> .v-text-field__slot input {
|
||||
color: var(--v-txt-base) !important;
|
||||
}
|
||||
.v-input >>> .v-text-field__slot textarea {
|
||||
color: var(--v-txt-base) !important;
|
||||
}
|
||||
|
||||
.youtube >>> .v-input__icon--prepend-inner i {
|
||||
color: #e64e0f !important;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.youtube >>> .v-text-field__slot {
|
||||
border-left: 1px solid var(--v-lines-base) !important;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.youtube >>> .v-input__icon--prepend-inner {
|
||||
margin: auto 14px auto 10px;
|
||||
}
|
||||
</style>
|
||||
181
components/Learning/ProductOverview/Links.vue
Normal file
181
components/Learning/ProductOverview/Links.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.links')">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('general.sharepoint')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
prepend-inner-icon="icon-sharepoint"
|
||||
v-model="sharepoint_link"
|
||||
placeholder="https://sharepoint.com/"
|
||||
outlined
|
||||
flat
|
||||
class="links"
|
||||
v-if="editMode"
|
||||
></v-text-field>
|
||||
<v-btn
|
||||
v-if="!editMode && sharepoint_link"
|
||||
:href="sharepoint_link"
|
||||
target="_blank"
|
||||
text
|
||||
link
|
||||
|
||||
><v-icon left>icon-sharepoint</v-icon> {{ sharepoint_link }}</v-btn
|
||||
>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<!-- <v-subheader v-if="editMode">{{ $t('general.add_link') }}</v-subheader> -->
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('general.support_site')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="support_link"
|
||||
prepend-inner-icon="icon-link"
|
||||
placeholder="https://support.ggzecademy.nl/"
|
||||
outlined
|
||||
flat
|
||||
class="links"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<v-btn
|
||||
v-if="!editMode && support_link"
|
||||
:href="support_link"
|
||||
link
|
||||
text
|
||||
target="_blank"
|
||||
|
||||
><v-icon left>icon-link</v-icon>{{ support_link }}</v-btn
|
||||
>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<!-- <v-subheader v-if="editMode">{{ $t('general.add_link') }}</v-subheader> -->
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('general.support_tickets')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field
|
||||
v-model="support_tickets_link"
|
||||
prepend-inner-icon="icon-link"
|
||||
placeholder="https://support.ggzecademy.nl/"
|
||||
outlined
|
||||
flat
|
||||
class="links"
|
||||
v-if="editMode"
|
||||
></v-text-field>
|
||||
<v-btn
|
||||
v-if="!editMode && support_tickets_link"
|
||||
:href="support_tickets_link"
|
||||
text
|
||||
target="_blank"
|
||||
link
|
||||
><v-icon left>icon-link</v-icon>{{ support_tickets_link }}</v-btn
|
||||
>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<!-- <v-subheader v-if="editMode">{{ $t('general.add_link') }}</v-subheader> -->
|
||||
</v-col>
|
||||
</v-row>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
local() {
|
||||
return this.$store.state.learning.local
|
||||
},
|
||||
sharepoint_link: {
|
||||
get() {
|
||||
return this.local.sharepoint_link || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'sharepoint_link',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
support_link: {
|
||||
get() {
|
||||
return this.local.support_link || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'support_link',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
support_tickets_link: {
|
||||
get() {
|
||||
return this.local.support_tickets_link || ''
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'support_tickets_link',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-input__icon--prepend .v-icon {
|
||||
font-size: 15px !important;
|
||||
}
|
||||
.links >>> .v-input__icon--prepend-inner {
|
||||
margin: auto 12px;
|
||||
}
|
||||
.links >>> .v-input__icon--prepend-inner i {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: var(--v-txt-base) !important;
|
||||
}
|
||||
.links >>> .v-input__icon--prepend-inner .icon-sharepoint {
|
||||
color: dodgerblue !important;
|
||||
}
|
||||
|
||||
.links >>> .v-text-field__slot {
|
||||
border-left: 1px solid var(--v-lines-base) !important;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.links >>> .v-input__slot:hover .v-text-field__slot {
|
||||
border-color: var(--v-secAccent-base) !important;
|
||||
}
|
||||
.row{
|
||||
overflow: hidden;
|
||||
}
|
||||
.row >>> div:nth-child(3) .v-subheader {
|
||||
color: var(--v-tertiary-base) !important;
|
||||
}
|
||||
</style>
|
||||
859
components/Learning/ProductOverview/Notifications.vue
Normal file
859
components/Learning/ProductOverview/Notifications.vue
Normal file
@@ -0,0 +1,859 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.notifications')">
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="notifications"
|
||||
:options="options"
|
||||
hide-default-footer
|
||||
item-key="notification"
|
||||
flat
|
||||
v-if="hasNotifications"
|
||||
>
|
||||
<template v-slot:item.date="{ item }">{{
|
||||
formatDate(item.date)
|
||||
}}</template>
|
||||
|
||||
<template v-slot:item.sent="{ item }">
|
||||
<v-icon color="teal" class="icon-checkmark" v-if="item.sent"></v-icon>
|
||||
<v-icon color="red" class="icon-close" size="8" v-else></v-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-btn
|
||||
class="mx-4 white--text button-hover"
|
||||
style="height: 100%"
|
||||
:color="$vuetify.theme.dark ? 'info' : 'txt'"
|
||||
rounded
|
||||
depressed
|
||||
small
|
||||
@click="viewItem(item)"
|
||||
>{{ $t('general.view') }}</v-btn
|
||||
>
|
||||
|
||||
<v-menu
|
||||
offset-y
|
||||
v-if="
|
||||
editMode && ($store.getters.isAdmin || $store.getters.isOperator)
|
||||
"
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-hover v-slot:default="{ hover }">
|
||||
<v-btn
|
||||
:color="hover ? 'info' : ''"
|
||||
:outlined="hover"
|
||||
depressed
|
||||
fab
|
||||
small
|
||||
v-on="on"
|
||||
>
|
||||
<v-icon>icon-options</v-icon>
|
||||
</v-btn>
|
||||
</v-hover>
|
||||
</template>
|
||||
<v-list width="200">
|
||||
<v-list-item @click="editItem(item)">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-edit</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>
|
||||
{{ $t('general.edit') | capitalize }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-dialog max-width="740" persistent v-model="dialogDelete">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-list-item v-on="on">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-remove</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>
|
||||
{{ $t('general.delete') | capitalize }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-card class="primary pa-10" flat>
|
||||
<v-card-title class="headline">
|
||||
{{
|
||||
$t('learning.product_overview.delete_confirmation', {
|
||||
productName: item.subject,
|
||||
})
|
||||
}}
|
||||
</v-card-title>
|
||||
<v-card-actions>
|
||||
<div class="ma-4">
|
||||
<v-btn
|
||||
@click="deleteItem(item)"
|
||||
class="mx-2"
|
||||
color="accent"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.delete') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
@click="dialogDelete = false"
|
||||
class="mx-2"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</div>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<v-dialog
|
||||
v-model="dialogNotification"
|
||||
max-width="75%"
|
||||
v-if="$store.getters.isAdmin || $store.getters.isOperator"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn
|
||||
v-if="editMode"
|
||||
class="my-10 cta-secondary"
|
||||
block
|
||||
depressed
|
||||
min-height="60px"
|
||||
:disabled="isCreateMode"
|
||||
v-on="on"
|
||||
@click="notificationEditMode = true"
|
||||
>
|
||||
<v-icon x-small class="mx-4">icon-add</v-icon>
|
||||
{{ $t('learning.add_new_notification') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline">{{ formTitle }}</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.actions.date_time')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="8" class="d-flex">
|
||||
<v-menu
|
||||
ref="menuDate"
|
||||
v-model="menuDate"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`notification-date-${Math.random()}`"
|
||||
v-model="computedDateFormatted"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
readonly
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.date"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuDate = false">Cancel</v-btn>
|
||||
<v-btn text @click="$refs.menuDate.save(editedItem.date)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
<span class="mx-5 my-3 font-weight-bold">{{
|
||||
$t('learning.actions.at')
|
||||
}}</span>
|
||||
<v-menu
|
||||
ref="menuTime"
|
||||
v-model="menuTime"
|
||||
:close-on-content-click="false"
|
||||
:nudge-right="40"
|
||||
:return-value.sync="editedItem.time"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
max-width="290px"
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`notification-time-${Math.random()}`"
|
||||
v-model="editedItem.time"
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
readonly
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
></v-text-field>
|
||||
</template>
|
||||
|
||||
<v-time-picker
|
||||
v-if="menuTime"
|
||||
v-model="editedItem.time"
|
||||
full-width
|
||||
format="24hr"
|
||||
@click:minute="$refs.menuTime.save(editedItem.time)"
|
||||
></v-time-picker>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black"></v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.actions.mail_addresses')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="8" class="d-flex">
|
||||
<v-combobox
|
||||
v-model="editedItem.emails"
|
||||
hide-selected
|
||||
label="Add emails here"
|
||||
multiple
|
||||
chips
|
||||
solo
|
||||
:disabled="!editModeComputed"
|
||||
>
|
||||
<template
|
||||
v-slot:selection="{ attrs, item, parent, selected }"
|
||||
>
|
||||
<v-chip
|
||||
v-bind="attrs"
|
||||
:input-value="selected"
|
||||
small
|
||||
:close="editModeComputed"
|
||||
@click:close="parent.selectItem(item)"
|
||||
>
|
||||
<span class="pr-2">{{ item }}</span>
|
||||
</v-chip>
|
||||
</template>
|
||||
</v-combobox>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black"></v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.actions.users')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="8" class="d-flex users">
|
||||
<v-autocomplete
|
||||
v-model="editedItem.users"
|
||||
:items="users"
|
||||
chips
|
||||
color="blue-grey lighten-2"
|
||||
item-text="fullName"
|
||||
item-value="id"
|
||||
multiple
|
||||
hide-selected
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
>
|
||||
<template v-slot:selection="data">
|
||||
<v-chip
|
||||
v-bind="data.attrs"
|
||||
:input-value="data.id"
|
||||
:close="editModeComputed"
|
||||
@click="data.select"
|
||||
@click:close="removeUser(data.item.id)"
|
||||
>{{ data.item.fullName }}</v-chip
|
||||
>
|
||||
</template>
|
||||
<template v-slot:item="data">
|
||||
<template>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title
|
||||
v-html="data.item.fullName"
|
||||
></v-list-item-title>
|
||||
<!-- <v-list-item-subtitle
|
||||
v-html="data.item.group"
|
||||
></v-list-item-subtitle>-->
|
||||
</v-list-item-content>
|
||||
</template>
|
||||
</template>
|
||||
</v-autocomplete>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="12" md="2"></v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.actions.subject')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="8" class="d-flex">
|
||||
<v-text-field
|
||||
v-model="editedItem.subject"
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black"></v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.actions.message')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="8">
|
||||
<quill-editor
|
||||
class="quill primary"
|
||||
:options="editorOption"
|
||||
v-model="editedItem.message"
|
||||
style="width: 100%"
|
||||
v-if="editModeComputed"
|
||||
/>
|
||||
<span v-html="editedItem.message" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="2">
|
||||
<v-subheader class="txt--text font-weight-black"></v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider />
|
||||
<v-card-actions v-if="editModeComputed">
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
:disabled="loading"
|
||||
@click="save"
|
||||
>{{ $t('general.save') }}</v-btn
|
||||
>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="txt"
|
||||
depressed
|
||||
text
|
||||
:disabled="loading"
|
||||
@click="close"
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<p v-if="isCreateMode" class="text-center">
|
||||
Bij het aanmaken van een nieuw product kiest u eerst voor 'Opslaan' om
|
||||
deze functie te activeren.
|
||||
</p>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black in_the_picture"
|
||||
>In the picture</v-subheader
|
||||
>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9" class="mb-4 d-flex flex-column">
|
||||
<div class="pb-0 mb-0 d-flex">
|
||||
<v-switch
|
||||
:disabled="!editMode"
|
||||
inset
|
||||
class="toggle my-3"
|
||||
v-model="in_the_picture"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
:value="computedInThePicDateFormattedStart"
|
||||
readonly
|
||||
prepend-inner-icon="icon-events"
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:flat="!editMode"
|
||||
/>
|
||||
<span class="mx-5 my-3 font-weight-bold"> tot </span>
|
||||
<v-text-field
|
||||
:value="computedInThePicDateFormattedEnd"
|
||||
readonly
|
||||
:outlined="editMode"
|
||||
:solo="!editMode"
|
||||
:flat="!editMode"
|
||||
append-icon="icon-events"
|
||||
/>
|
||||
</div>
|
||||
<v-date-picker
|
||||
v-if="$store.getters.isSuperAdminOrAdmin"
|
||||
v-model="dates"
|
||||
no-title
|
||||
:disabled="!editMode"
|
||||
flat
|
||||
first-day-of-week="1"
|
||||
range
|
||||
full-width
|
||||
locale="nl-NL"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import 'quill/dist/quill.bubble.css'
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
quillEditor,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isCreateMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
users: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
picker: new Date(Date.now() - new Date().getTimezoneOffset() * 60000)
|
||||
.toISOString()
|
||||
.substr(0, 10),
|
||||
|
||||
options: {
|
||||
itemsPerPage: -1,
|
||||
},
|
||||
headers: [
|
||||
{ text: 'subject', value: 'subject' },
|
||||
{ text: 'date', value: 'date' },
|
||||
{ text: 'time', value: 'time' },
|
||||
{ text: 'sent', value: 'sent' },
|
||||
{ text: '', value: 'actions' },
|
||||
],
|
||||
loading: false,
|
||||
dialogNotification: false,
|
||||
dialogDelete: false,
|
||||
|
||||
editedIndex: -1,
|
||||
editedItem: {
|
||||
date: '',
|
||||
time: null,
|
||||
emails: [],
|
||||
users: [],
|
||||
subject: '',
|
||||
message: '',
|
||||
},
|
||||
defaultItem: {
|
||||
date: '',
|
||||
time: null,
|
||||
emails: [],
|
||||
users: [],
|
||||
subject: '',
|
||||
message: '',
|
||||
},
|
||||
content: 'Write here your content...',
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: [
|
||||
[{ size: ['small', false, 'large'] }],
|
||||
['bold', 'italic'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }],
|
||||
['link'],
|
||||
],
|
||||
},
|
||||
},
|
||||
notificationEditMode: false,
|
||||
autoUpdate: true,
|
||||
isUpdating: false,
|
||||
activator: null,
|
||||
attach: null,
|
||||
editing: null,
|
||||
index: -1,
|
||||
date: null,
|
||||
menu: false,
|
||||
menuStart: false,
|
||||
menuEnd: false,
|
||||
menuDate: false,
|
||||
menuTime: false,
|
||||
menu2: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
dates: [],
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
dialogNotification(val) {
|
||||
val || this.close()
|
||||
},
|
||||
dates(val) {
|
||||
// If the second date is earlier than the first, switch them
|
||||
if (val.length === 2 && val[1] < val[0]) this.dates.reverse()
|
||||
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'in_the_picture_start',
|
||||
value: val[0] || null,
|
||||
})
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'in_the_picture_end',
|
||||
value: val[1] || null,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
local() {
|
||||
return this.$store.getters.localProduct
|
||||
},
|
||||
notifications() {
|
||||
if (!this.local || !Array.isArray(this.local.notifications)) return []
|
||||
return this.local.notifications
|
||||
},
|
||||
hasNotifications() {
|
||||
return this.notifications.length > 0
|
||||
},
|
||||
formTitle() {
|
||||
return this.editedIndex === -1
|
||||
? 'Nieuwe notificatie'
|
||||
: 'Bewerken notificatie'
|
||||
},
|
||||
editModeComputed() {
|
||||
return this.notificationEditMode && this.editMode
|
||||
},
|
||||
computedDateFormatted() {
|
||||
return this.formatDate(this.editedItem.date)
|
||||
},
|
||||
computedInThePicDateFormattedStart() {
|
||||
return this.formatDate(this.in_the_picture_start)
|
||||
},
|
||||
computedInThePicDateFormattedEnd() {
|
||||
return this.formatDate(this.in_the_picture_end)
|
||||
},
|
||||
in_the_picture: {
|
||||
get() {
|
||||
return this.local.in_the_picture
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'in_the_picture',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
in_the_picture_start() {
|
||||
return this.local.in_the_picture_start
|
||||
},
|
||||
in_the_picture_end() {
|
||||
return this.local.in_the_picture_end
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
assignItemToEdited(item) {
|
||||
this.editedIndex = this.notifications.indexOf(item)
|
||||
this.editedItem = Object.assign({}, item)
|
||||
|
||||
if (typeof this.editedItem.users === 'string') {
|
||||
this.editedItem.users = JSON.parse(this.editedItem.users)
|
||||
}
|
||||
if (typeof this.editedItem.emails === 'string') {
|
||||
this.editedItem.emails = JSON.parse(this.editedItem.emails)
|
||||
}
|
||||
},
|
||||
formatDate(date) {
|
||||
if (!date) return null
|
||||
|
||||
const [year, month, day, time] = date.replace(' ', '-').split('-')
|
||||
return `${day}/${month}/${year}`
|
||||
},
|
||||
|
||||
viewItem(item) {
|
||||
this.editedIndex = this.notifications.indexOf(item)
|
||||
this.notificationEditMode = false
|
||||
this.assignItemToEdited(item)
|
||||
this.dialogNotification = true
|
||||
},
|
||||
|
||||
editItem(item) {
|
||||
if (!this.editMode) return
|
||||
this.notificationEditMode = true
|
||||
this.assignItemToEdited(item)
|
||||
this.dialogNotification = true
|
||||
},
|
||||
|
||||
async deleteItem(item) {
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
if (!item.id) {
|
||||
this.$notifier.showMessage({
|
||||
content: `No notificaion to delete selected`,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(
|
||||
`/learning-products/notifications/${item.id}`
|
||||
)
|
||||
|
||||
this.$store.commit('learning/DELETE_COURSE_NOTIFICATION_LOCAL', item)
|
||||
|
||||
this.dialogDelete = false
|
||||
this.dialogNotification = false
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Notification deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
} catch (error) {
|
||||
this.$nuxt.$loading.finish()
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to delete the selected notification`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async save() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
|
||||
// Edit mode
|
||||
if (this.editedIndex > -1) {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.editedItem.sent = 0
|
||||
|
||||
const response = await this.$axios.post(
|
||||
'/learning-products/notifications',
|
||||
this.editedItem
|
||||
)
|
||||
|
||||
this.$store.commit('learning/EDIT_COURSE_NOTIFICATION_LOCAL', {
|
||||
index: this.editedIndex,
|
||||
notification: response.data,
|
||||
})
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Notification stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogNotification = false
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the notification`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
// Create new mode
|
||||
} else {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
let data = { ...this.editedItem }
|
||||
data['emails'] = JSON.stringify(data['emails'])
|
||||
data['users'] = JSON.stringify(data['users'])
|
||||
|
||||
const response = await this.$axios.post(
|
||||
'/learning-products/notifications',
|
||||
data
|
||||
)
|
||||
|
||||
this.dialog = false
|
||||
|
||||
this.$store.commit(
|
||||
'learning/ADD_COURSE_NOTIFICATION_LOCAL',
|
||||
response.data
|
||||
)
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Notifican stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogAccreditation = false
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the notification`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
this.loading = false
|
||||
this.close()
|
||||
},
|
||||
close() {
|
||||
this.dialogNotification = false
|
||||
this.$nextTick(() => {
|
||||
this.editedItem = Object.assign({}, this.defaultItem)
|
||||
this.editedIndex = -1
|
||||
})
|
||||
},
|
||||
edit(index, item) {
|
||||
if (!this.editing) {
|
||||
this.editing = item
|
||||
this.index = index
|
||||
} else {
|
||||
this.editing = null
|
||||
this.index = -1
|
||||
}
|
||||
},
|
||||
|
||||
removeUser(userId) {
|
||||
const index = this.editedItem.users.indexOf(userId)
|
||||
|
||||
if (index >= 0) {
|
||||
let arrayUsers = [...this.editedItem.users]
|
||||
arrayUsers.splice(index, 1)
|
||||
this.editedItem.users = [...arrayUsers]
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-card >>> table,
|
||||
.v-card >>> .v-data-table-header tr,
|
||||
.v-card >>> .v-data-footer {
|
||||
background-color: var(--v-primary-base);
|
||||
}
|
||||
.v-card >>> .v-data-table-header th span {
|
||||
color: var(--v-tertiary-base);
|
||||
}
|
||||
.v-card >>> .text-start,
|
||||
.v-card >>> .v-icon,
|
||||
.v-dialog__content >>> .v-subheader,
|
||||
.v-dialog__content >>> i,
|
||||
.font-weight-bold {
|
||||
color: var(--v-txt-base);
|
||||
font-weight: bold;
|
||||
}
|
||||
.v-card >>> .in_the_picture {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.v-dialog__content >>> .v-dialog {
|
||||
border: 4px solid var(--v-secAccent-base);
|
||||
max-height: 68% !important;
|
||||
|
||||
/* box-shadow: inset 0px 0px 2px 2px var(--v-secAccent-base),
|
||||
inset 6px 6px 14px -14px var(--v-secAccent-base) !important; */
|
||||
}
|
||||
.v-dialog .v-card {
|
||||
background: var(--v-secondary-base);
|
||||
}
|
||||
|
||||
.v-dialog__content >>> .v-input__slot {
|
||||
background: var(--v-primary-base);
|
||||
border: 1px solid var(--v-lines-base);
|
||||
}
|
||||
|
||||
table tr .button-hover.v-btn {
|
||||
opacity: 0;
|
||||
}
|
||||
table tr:hover .button-hover.v-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
.v-autocomplete__content {
|
||||
top: 532px !important;
|
||||
left: 507px !important;
|
||||
}
|
||||
|
||||
.v-autocomplete__content >>> .v-list .v-list-item:first-child {
|
||||
pointer-events: auto !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
.v-autocomplete__content
|
||||
.v-list
|
||||
.v-list-item:first-child
|
||||
.v-list-item__content {
|
||||
border-bottom: 0px solid var(--v-search-base) !important;
|
||||
padding-bottom: unset !important;
|
||||
}
|
||||
.v-autocomplete__content .v-list {
|
||||
padding: 6px !important;
|
||||
}
|
||||
.v-autocomplete__content .v-list .v-list-item:first-child .v-list-item__title {
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
.v-text-field.v-text-field--solo >>> .v-input__append-inner {
|
||||
align-self: baseline;
|
||||
}
|
||||
.v-text-field.v-text-field--solo >>> .v-input__slot {
|
||||
padding: 8px 12px !important;
|
||||
}
|
||||
.v-text-field.v-text-field--solo >>> .v-input__icon--append {
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
168
components/Learning/ProductOverview/Organize.vue
Normal file
168
components/Learning/ProductOverview/Organize.vue
Normal file
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<accordion-card
|
||||
:title="$t('learning.product_overview.organize')"
|
||||
id="organize"
|
||||
>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.type') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="type"
|
||||
filterType="checkbox"
|
||||
:editMode="editMode"
|
||||
/>
|
||||
<!-- v-if="isFilterTypeEmpty" -->
|
||||
<small class="error--text">Het type is verplicht</small>
|
||||
<br />
|
||||
<br />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode">
|
||||
{{ $t('learning.more_options_selectable') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.product_type') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
class="producttype"
|
||||
filterTitle="product_type"
|
||||
filterType="mixed"
|
||||
:editMode="editMode"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.category') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="category"
|
||||
:editMode="editMode"
|
||||
filterType="mixed"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.theme') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="theme"
|
||||
:editMode="editMode"
|
||||
filterType="mixed"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.course') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="course"
|
||||
:editMode="editMode"
|
||||
filterType="mixed"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.audience') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="audience"
|
||||
:editMode="editMode"
|
||||
filterType="mixed"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode">
|
||||
{{ $t('learning.more_options_selectable') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.filters.quality_standards') | capitalize
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<universalFilterSelector
|
||||
filterTitle="quality_standards"
|
||||
:editMode="editMode"
|
||||
filterType="mixed"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader v-if="editMode">
|
||||
{{ $t('learning.more_options_selectable') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
import universalFilterSelector from '@/components/UniversalFilterSelector/UniversalFilterSelector'
|
||||
// import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
universalFilterSelector,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isFilterTypeEmpty() {
|
||||
return this.$store.getters.isFilterTypeEmpty
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#organize >>> .v-input__slot .v-select__slot {
|
||||
margin-left: -4px;
|
||||
}
|
||||
#organize >>> .producttype .v-input__slot .v-select__slot {
|
||||
margin-left: 0;
|
||||
}
|
||||
</style>
|
||||
304
components/Learning/ProductOverview/Texts.vue
Normal file
304
components/Learning/ProductOverview/Texts.vue
Normal file
@@ -0,0 +1,304 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.texts')">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.short_description')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="short_description"
|
||||
id="short_description"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'short_description' }"
|
||||
@focus="onEditorFocus($event, 'short_description')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'short_description')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<!-- @change="onEditorChange($event)" -->
|
||||
|
||||
<span v-html="short_description" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.learning_goals')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="learning_goals"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'learning_goals' }"
|
||||
@focus="onEditorFocus($event, 'learning_goals')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'learning_goals')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<span v-html="learning_goals" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.review')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="review"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'review' }"
|
||||
@focus="onEditorFocus($event, 'review')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'review')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<span v-html="review" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.certification')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="certification"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'certification' }"
|
||||
@focus="onEditorFocus($event, 'certification')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'certification')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<span v-html="certification" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.extra_information')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="extra_information"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'extra_information' }"
|
||||
@focus="onEditorFocus($event, 'extra_information')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'extra_information')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<span v-html="extra_information" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.product_overview.target_audience')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="target_audience"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'target_audience' }"
|
||||
@focus="onEditorFocus($event, 'target_audience')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'target_audience')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<span v-html="target_audience" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Kwaliteitsstandaarden
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" class="pl-6">
|
||||
<quill-editor
|
||||
v-model="quality_standards"
|
||||
:options="editorOption"
|
||||
class="quill"
|
||||
:class="{ focused: selectedEditor === 'quality_standards' }"
|
||||
@focus="onEditorFocus($event, 'quality_standards')"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event, 'quality_standards')"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<span v-html="quality_standards" v-else></span>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="3"> </v-col>
|
||||
</v-row>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import 'quill/dist/quill.bubble.css'
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
quillEditor,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedEditor: '',
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: [
|
||||
[{ size: ['small', false, 'large'] }],
|
||||
['bold', 'italic'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }],
|
||||
['link'],
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
local() {
|
||||
return this.$store.state.learning.local
|
||||
},
|
||||
|
||||
short_description: {
|
||||
get() {
|
||||
return this.local.short_description
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'short_description',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
learning_goals: {
|
||||
get() {
|
||||
return this.local.learning_goals
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'learning_goals',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
review: {
|
||||
get() {
|
||||
return this.local.review
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'review',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
certification: {
|
||||
get() {
|
||||
return this.local.certification
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'certification',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
extra_information: {
|
||||
get() {
|
||||
return this.local.extra_information
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'extra_information',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
target_audience: {
|
||||
get() {
|
||||
return this.local.target_audience
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'target_audience',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
quality_standards: {
|
||||
get() {
|
||||
return this.local.quality_standards
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/UPDATE_FIELD', {
|
||||
field: 'quality_standards',
|
||||
value,
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onEditorBlur(editor) {
|
||||
this.selectedEditor = ''
|
||||
// console.log('editor blur!', editor)
|
||||
},
|
||||
onEditorFocus(editor, nameEditor) {
|
||||
this.selectedEditor = nameEditor
|
||||
},
|
||||
onEditorReady(editor) {
|
||||
// console.log('editor ready!', editor)
|
||||
},
|
||||
onEditorChange(editor, nameEditor) {
|
||||
if (this.selectedEditor !== nameEditor) this.selectedEditor = nameEditor
|
||||
// console.log('editor change!', editor)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-subheader {
|
||||
display: unset;
|
||||
}
|
||||
</style>
|
||||
955
components/Learning/ProductOverview/Versions.vue
Normal file
955
components/Learning/ProductOverview/Versions.vue
Normal file
@@ -0,0 +1,955 @@
|
||||
<template>
|
||||
<accordion-card :title="$t('learning.product_overview.version')">
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="versions"
|
||||
:options="options"
|
||||
hide-default-footer
|
||||
item-key="version"
|
||||
v-if="hasVersions"
|
||||
flat
|
||||
>
|
||||
<template v-slot:item.made_by="{ item }">
|
||||
{{ getFilterItem('made_by', item).title }}
|
||||
</template>
|
||||
<template v-slot:item.dev_environment="{ item }">
|
||||
{{ getFilterItem('dev_environment', item).title }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.status="{ item }">
|
||||
<v-icon
|
||||
x-small
|
||||
class="mr-2"
|
||||
v-if="getFilterItem('status', item).color"
|
||||
:color="getFilterItem('status', item).color"
|
||||
>mdi-circle</v-icon
|
||||
>
|
||||
{{ getFilterItem('status', item).title }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.release_start="{ item }">
|
||||
{{ formatDate(item.release_start) }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.release_end="{ item }">
|
||||
{{ formatDate(item.release_end) }}
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-btn
|
||||
class="mx-4 white--text view"
|
||||
style="height: 100%"
|
||||
:color="$vuetify.theme.dark ? 'info' : 'txt'"
|
||||
rounded
|
||||
depressed
|
||||
small
|
||||
@click="viewItem(item)"
|
||||
>{{ $t('general.view') }}</v-btn
|
||||
>
|
||||
|
||||
<v-menu
|
||||
offset-y
|
||||
v-if="
|
||||
editMode && ($store.getters.isAdmin || $store.getters.isOperator)
|
||||
"
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-hover v-slot:default="{ hover }">
|
||||
<v-btn
|
||||
:color="hover ? 'info' : ''"
|
||||
:outlined="hover"
|
||||
depressed
|
||||
fab
|
||||
small
|
||||
v-on="on"
|
||||
>
|
||||
<v-icon>icon-options</v-icon>
|
||||
</v-btn>
|
||||
</v-hover>
|
||||
</template>
|
||||
<v-list width="200">
|
||||
<v-list-item @click="editItem(item)">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-edit</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>{{
|
||||
$t('general.edit') | capitalize
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-dialog max-width="740" persistent v-model="dialogDelete">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-list-item v-on="on">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-remove</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-subtitle>{{
|
||||
$t('general.delete') | capitalize
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-card class="primary pa-10" flat>
|
||||
<v-card-title class="headline">
|
||||
{{
|
||||
$t('learning.product_overview.delete_confirmation', {
|
||||
productName: item.version_number,
|
||||
})
|
||||
}}
|
||||
</v-card-title>
|
||||
<v-card-actions>
|
||||
<div class="ma-4">
|
||||
<v-btn
|
||||
@click="deleteItem(item)"
|
||||
class="mx-2"
|
||||
color="accent"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.delete') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
@click="dialogDelete = false"
|
||||
class="mx-2"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</div>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<v-dialog
|
||||
v-model="dialogVersion"
|
||||
max-width="75%"
|
||||
v-if="$store.getters.isAdmin || $store.getters.isOperator"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn
|
||||
v-if="editMode"
|
||||
class="cta-secondary my-10"
|
||||
block
|
||||
depressed
|
||||
min-height="60px"
|
||||
:disabled="isCreateMode"
|
||||
v-on="on"
|
||||
@click="resetVersionsFilters"
|
||||
>
|
||||
<v-icon x-small class="mx-4">icon-add</v-icon>
|
||||
|
||||
{{ $t('learning.add_new_version') }}</v-btn
|
||||
>
|
||||
</template>
|
||||
<v-form ref="form" v-model="valid" lazy-validation>
|
||||
<v-card ref="card">
|
||||
<v-card-title>
|
||||
<span class="headline">{{ formTitle }}</span>
|
||||
<!-- <input ref="input" /> -->
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.versions.version_number')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9">
|
||||
<v-text-field
|
||||
v-model="editedItem.version_number"
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
:rules="rules.version_number"
|
||||
required
|
||||
error
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row
|
||||
v-for="(filterTitle, i) in filterInputs"
|
||||
:key="`row-filter-${i}`"
|
||||
>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t(`learning.filters.${filterTitle}`)
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9">
|
||||
<universalFilterSelector
|
||||
:filterTitle="filterTitle"
|
||||
:editMode="editModeComputed"
|
||||
target="versions"
|
||||
:key="`universal-filter-version-${i}`"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
{{ $t('learning.versions.release_date.from') }}
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9" class="d-flex">
|
||||
<v-menu
|
||||
ref="menuStart"
|
||||
v-model="menuStart"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<!-- <input type="text" v-model="startData" /> -->
|
||||
|
||||
<v-text-field
|
||||
:name="`release-start-date-${Math.random()}`"
|
||||
v-model="computedDateFormattedStart"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
:rules="rules.release_start"
|
||||
required
|
||||
error
|
||||
readonly
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.release_start"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuStart = false">Cancel</v-btn>
|
||||
<v-btn
|
||||
text
|
||||
@click="$refs.menuStart.save(editedItem.release_start)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
<span class="mx-5 my-3 font-weight-bold">
|
||||
{{ $t('learning.versions.release_date.to') }}
|
||||
</span>
|
||||
<v-menu
|
||||
ref="menuEnd"
|
||||
v-model="menuEnd"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
min-width="290px"
|
||||
>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-text-field
|
||||
:name="`release-end-date-${Math.random()}`"
|
||||
v-model="computedDateFormattedEnd"
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
max-height="100px"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
clearable
|
||||
readonly
|
||||
>
|
||||
<template v-slot:append>
|
||||
<v-icon v-on="on">icon-events</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="editedItem.release_end"
|
||||
no-title
|
||||
scrollable
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
locale="nl-NL"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="menuEnd = false">Cancel</v-btn>
|
||||
<v-btn
|
||||
text
|
||||
@click="$refs.menuEnd.save(editedItem.release_end)"
|
||||
>OK</v-btn
|
||||
>
|
||||
</v-date-picker>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.versions.release_planning')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9">
|
||||
<quill-editor
|
||||
class="quill primary"
|
||||
:options="editorOption"
|
||||
v-model="editedItem.release_planning_description"
|
||||
v-if="editModeComputed"
|
||||
/>
|
||||
<span
|
||||
v-html="editedItem.release_planning_description"
|
||||
v-else
|
||||
></span>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="mb-10">
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
$t('learning.versions.technical_information')
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9">
|
||||
<quill-editor
|
||||
class="quill primary"
|
||||
v-model="editedItem.technical_information"
|
||||
:options="editorOption"
|
||||
v-if="editModeComputed"
|
||||
/>
|
||||
<div v-html="editedItem.technical_information" v-else></div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- Checklist Summary -->
|
||||
<v-row class="mb-10">
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">
|
||||
Checklist
|
||||
</v-subheader>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="9">
|
||||
<v-text-field
|
||||
v-model="checklist_summary"
|
||||
solo
|
||||
disabled
|
||||
flat
|
||||
max-height="100px"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- Checklist -->
|
||||
<v-row v-for="checklist in checklists" :key="checklist.id">
|
||||
<v-col cols="12" sm="12" md="3">
|
||||
<v-subheader class="txt--text font-weight-black">{{
|
||||
checklist.title
|
||||
}}</v-subheader>
|
||||
</v-col>
|
||||
<v-col
|
||||
cols="12"
|
||||
sm="12"
|
||||
md="9"
|
||||
class="d-flex flex-column justify-center"
|
||||
>
|
||||
<!-- -->
|
||||
<v-list
|
||||
:outlined="editModeComputed"
|
||||
:solo="!editModeComputed"
|
||||
:disabled="!editModeComputed"
|
||||
:flat="!editModeComputed"
|
||||
input-value="true"
|
||||
>
|
||||
<v-list-item-group v-model="checklistsSelected" multiple>
|
||||
<template>
|
||||
<v-list-item
|
||||
v-for="(item, i) in checklist.items"
|
||||
:key="`item-${i}`"
|
||||
:value="item.id"
|
||||
active-class="secondary"
|
||||
two-line
|
||||
>
|
||||
<template v-slot:default="{ active, toggle }">
|
||||
<v-list-item-action>
|
||||
<v-checkbox
|
||||
:input-value="active"
|
||||
:true-value="item.id"
|
||||
:click="toggle"
|
||||
on-icon="icon-selectionbox-checked"
|
||||
off-icon="icon-selectionbox"
|
||||
></v-checkbox>
|
||||
</v-list-item-action>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title
|
||||
v-text="item.title"
|
||||
></v-list-item-title>
|
||||
<v-list-item-subtitle
|
||||
v-if="item.subtitle"
|
||||
v-text="item.subtitle"
|
||||
></v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
|
||||
<v-list-item-action>
|
||||
{{ showChecklistInfo(item.id) }}
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-list-item-group>
|
||||
</v-list>
|
||||
<!-- -->
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider />
|
||||
<v-card-actions v-if="editModeComputed">
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="info"
|
||||
depressed
|
||||
rounded
|
||||
:disabled="loading"
|
||||
@click="validate"
|
||||
>{{ $t('general.save') }}</v-btn
|
||||
>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="ma-2 white--text"
|
||||
color="txt"
|
||||
depressed
|
||||
text
|
||||
:disabled="loading"
|
||||
@click="close"
|
||||
>{{ $t('general.cancel') }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-form>
|
||||
</v-dialog>
|
||||
|
||||
<p v-if="isCreateMode" class="text-center">
|
||||
Bij het aanmaken van een nieuw product kiest u eerst voor 'Opslaan' om
|
||||
deze functie te activeren.
|
||||
</p>
|
||||
</accordion-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Util from '@/util'
|
||||
import accordionCard from '@/components/UI/AccordionCard/AccordionCard'
|
||||
import universalFilterSelector from '@/components/UniversalFilterSelector/UniversalFilterSelector'
|
||||
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import 'quill/dist/quill.bubble.css'
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
accordionCard,
|
||||
quillEditor,
|
||||
universalFilterSelector,
|
||||
},
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isCreateMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
itemsPerPage: -1,
|
||||
},
|
||||
content: 'Write here your content...',
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: [
|
||||
[{ size: ['small', false, 'large'] }],
|
||||
['bold', 'italic'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }],
|
||||
['link'],
|
||||
],
|
||||
},
|
||||
},
|
||||
headers: [
|
||||
{ text: 'versienummer', value: 'version_number' },
|
||||
{ text: 'gemaakt door', value: 'made_by' },
|
||||
{ text: 'ontwikkelomgeving', value: 'dev_environment' },
|
||||
{ text: 'status', value: 'status' },
|
||||
{ text: 'beschikbaar van', value: 'release_start' },
|
||||
{ text: 'beschikbaar tot', value: 'release_end' },
|
||||
{ text: '', value: 'actions' },
|
||||
],
|
||||
rules: {
|
||||
version_number: [(v) => !!v || 'Het versienummer is verplicht.'],
|
||||
release_start: [
|
||||
(v) => !!v || 'De startdatum van de release is verplicht.',
|
||||
],
|
||||
},
|
||||
valid: true,
|
||||
loading: false,
|
||||
date: null,
|
||||
menuPlanning: false,
|
||||
menuStart: false,
|
||||
menuEnd: false,
|
||||
modal: false,
|
||||
menu2: false,
|
||||
filterInputs: ['status', 'made_by', 'dev_environment', 'format_version'],
|
||||
version: {},
|
||||
versionEditMode: false,
|
||||
dialogVersion: false,
|
||||
dialogDelete: false,
|
||||
editedIndex: -1,
|
||||
editedItem: {
|
||||
version_number: '',
|
||||
release_start: '',
|
||||
release_end: '',
|
||||
release_planning_description: '',
|
||||
technical_information: '',
|
||||
},
|
||||
defaultItem: {
|
||||
version_number: '',
|
||||
release_start: '',
|
||||
release_end: '',
|
||||
release_planning_description: '',
|
||||
technical_information: '',
|
||||
},
|
||||
// startData: null,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
remote() {
|
||||
return this.$store.state.learning.remote
|
||||
},
|
||||
local() {
|
||||
return this.$store.state.learning.local
|
||||
},
|
||||
versions() {
|
||||
if (!this.local || !Array.isArray(this.local.versions)) return []
|
||||
return this.local.versions
|
||||
},
|
||||
versionsFiltersSelected() {
|
||||
return this.$store.state.learning.versionsFiltersSelected
|
||||
},
|
||||
hasVersions() {
|
||||
if (!this.versions) return false
|
||||
return this.versions.length > 0
|
||||
},
|
||||
|
||||
hasTmpVersion() {
|
||||
return Util.isNotEmptyObj(this.version)
|
||||
},
|
||||
checklists() {
|
||||
return this.$store.state.learning.checklists || null
|
||||
},
|
||||
checklistsSelected: {
|
||||
get() {
|
||||
return this.$store.state.learning.checklistsSelected
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('learning/SELECT_CHECKLIST', value)
|
||||
},
|
||||
},
|
||||
canEdit() {
|
||||
return (
|
||||
this.$route.query.edit === null &&
|
||||
(this.$store.getters.isAdmin || this.$store.getters.isOperator)
|
||||
)
|
||||
},
|
||||
|
||||
formTitle() {
|
||||
return this.editedIndex === -1 ? 'Nieuwe versie' : 'Bewerken versie'
|
||||
},
|
||||
editModeComputed() {
|
||||
return this.versionEditMode && this.editMode
|
||||
},
|
||||
checklist_summary() {
|
||||
let totalChecklists = 0
|
||||
|
||||
this.checklists.forEach((category) => {
|
||||
totalChecklists += category.items.length
|
||||
})
|
||||
|
||||
return `${this.checklistsSelected.length} van ${totalChecklists} voltooid`
|
||||
},
|
||||
|
||||
// computedDateFormattedStart() {
|
||||
// return this.formatDate(this.editedItem.release_start)
|
||||
// },
|
||||
// computedDateFormattedEnd() {
|
||||
// return this.formatDate(this.editedItem.release_end)
|
||||
// },
|
||||
|
||||
computedDateFormattedStart: {
|
||||
get() {
|
||||
return this.formatDate(this.editedItem.release_start)
|
||||
},
|
||||
set(value) {
|
||||
this.editedItem.release_start = value
|
||||
// if (this.isValidDate(value)) {
|
||||
// this.editedItem.release_start = value
|
||||
// }
|
||||
},
|
||||
},
|
||||
|
||||
computedDateFormattedEnd: {
|
||||
get() {
|
||||
return this.formatDate(this.editedItem.release_end)
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.editedItem.release_end = value
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
dialogVersion(val) {
|
||||
val || this.close()
|
||||
},
|
||||
// startData(val) {
|
||||
// console.log(': val', val)
|
||||
// if (this.isValidDate(val)) {
|
||||
// this.editedItem.release_start = this.parseDate(val)
|
||||
// }
|
||||
// },
|
||||
},
|
||||
|
||||
methods: {
|
||||
validate() {
|
||||
if (!this.$refs.form.validate()) return
|
||||
this.save()
|
||||
},
|
||||
resetVersionsFilters() {
|
||||
this.versionEditMode = true
|
||||
this.$store.commit('learning/RESET_CHECKLIST_SELECTED')
|
||||
this.$store.commit('learning/RESET_VERSIONS_FILTERS')
|
||||
},
|
||||
|
||||
formatDate(date) {
|
||||
if (!date) return null
|
||||
|
||||
const [year, month, day, time] = date.replace(' ', '-').split('-')
|
||||
return `${day}/${month}/${year}`
|
||||
},
|
||||
|
||||
parseDate(date) {
|
||||
if (!date || !this.isValidDate(date)) return null
|
||||
const [day, month, year] = date.split('/')
|
||||
if (day && day.length < 2) return null
|
||||
if (month && month.length < 2) return null
|
||||
if (year && year.length < 4) return null
|
||||
return `${year}-${month}-${day}`
|
||||
},
|
||||
|
||||
isValidDate(date) {
|
||||
return new Date(date) !== 'Invalid Date' && !isNaN(new Date(date))
|
||||
},
|
||||
|
||||
showChecklistInfo(checklistId) {
|
||||
if (
|
||||
!this.editedItem ||
|
||||
!this.editedItem.checklists ||
|
||||
!this.editedItem.checklists.length > 0
|
||||
)
|
||||
return null
|
||||
|
||||
const checklistFound = this.editedItem.checklists.find(
|
||||
(checklist) => checklist.checklist_id === checklistId
|
||||
)
|
||||
if (!checklistFound) return null
|
||||
return `${checklistFound.created_at}, ${checklistFound.user.fullName}`
|
||||
},
|
||||
|
||||
setVersionFiltersAndChecklist(item) {
|
||||
// Iterate item.filters and set in store versionsFiltersSelected filter_name: filter_item_id
|
||||
item.filters.forEach(async (f) => {
|
||||
const filterItem = this.$store.getters.getFilterItemById(
|
||||
f.filter_item_id
|
||||
)
|
||||
|
||||
await this.$store.commit('learning/UPDATE_FILTERS', {
|
||||
filterId: filterItem.filter_id,
|
||||
target: 'versions',
|
||||
value: f.filter_item_id,
|
||||
})
|
||||
})
|
||||
|
||||
const arrayChecklistIdsSelected = []
|
||||
|
||||
item.checklists.forEach(async (checklist) => {
|
||||
arrayChecklistIdsSelected.push(checklist.checklist_id)
|
||||
this.$store.commit(
|
||||
'learning/SET_CHECKED_CHECKLISTS',
|
||||
arrayChecklistIdsSelected
|
||||
)
|
||||
})
|
||||
|
||||
this.editedIndex = this.versions.indexOf(item)
|
||||
this.editedItem = Object.assign({}, item)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
|
||||
getFilterItem(filterTitle, version) {
|
||||
const filter = this.$store.getters.getFilterByTitle(filterTitle)
|
||||
|
||||
const arrayTmp = []
|
||||
if (!version.filters) return {}
|
||||
version.filters.forEach((f) => {
|
||||
const filterItemTmp = this.$store.getters.getFilterItemById(
|
||||
f.filter_item_id
|
||||
)
|
||||
arrayTmp.push(filterItemTmp)
|
||||
})
|
||||
|
||||
const filterItem = arrayTmp.find((e) => e.filter_id === filter.id)
|
||||
return filterItem || {}
|
||||
},
|
||||
|
||||
viewItem(item) {
|
||||
this.versionEditMode = false
|
||||
this.setVersionFiltersAndChecklist(item)
|
||||
this.dialogVersion = true
|
||||
},
|
||||
|
||||
editItem(item) {
|
||||
if (!this.editMode) return
|
||||
this.versionEditMode = true
|
||||
this.setVersionFiltersAndChecklist(item)
|
||||
this.dialogVersion = true
|
||||
// this.$refs.input.focus()
|
||||
},
|
||||
|
||||
async deleteItem(item) {
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
if (!item.id) {
|
||||
this.$notifier.showMessage({
|
||||
content: `No version to delete selected`,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(`/versions/${item.id}`)
|
||||
|
||||
this.$store.commit('learning/DELETE_VERSION_LOCAL', item)
|
||||
|
||||
this.dialogDelete = false
|
||||
this.dialogVersion = false
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Version deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
} catch (error) {
|
||||
this.$nuxt.$loading.finish()
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to delete the selected version`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
close() {
|
||||
this.dialogVersion = false
|
||||
this.$nextTick(() => {
|
||||
this.editedItem = Object.assign({}, this.defaultItem)
|
||||
this.editedIndex = -1
|
||||
this.$refs.card.$el.scrollIntoView(true)
|
||||
})
|
||||
},
|
||||
|
||||
setFiltersSelectedInEditedItem() {
|
||||
let versionFiltersItemsIds = []
|
||||
|
||||
for (const [key, value] of Object.entries(this.versionsFiltersSelected)) {
|
||||
versionFiltersItemsIds.push(value)
|
||||
}
|
||||
|
||||
this.editedItem['filter_items'] = versionFiltersItemsIds
|
||||
},
|
||||
|
||||
setChecklistsSelectedInEditedItem() {
|
||||
this.editedItem['checklists_selected'] = [
|
||||
...this.$store.state.learning.checklistsSelected,
|
||||
]
|
||||
},
|
||||
|
||||
async save() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.card.$el.scrollIntoView(true)
|
||||
})
|
||||
this.loading = true
|
||||
this.$nextTick(() => this.$nuxt.$loading.start())
|
||||
|
||||
// Edit mode
|
||||
if (this.editedIndex > -1) {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.setFiltersSelectedInEditedItem()
|
||||
this.setChecklistsSelectedInEditedItem()
|
||||
|
||||
const response = await this.$axios.post('/versions', this.editedItem)
|
||||
|
||||
this.$store.commit('learning/EDIT_VERSION_LOCAL', {
|
||||
index: this.editedIndex,
|
||||
version: response.data,
|
||||
})
|
||||
|
||||
this.dialogVersion = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Version stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogVersion = false
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the version`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
// Create new mode
|
||||
} else {
|
||||
try {
|
||||
this.editedItem.learning_product_id = this.local.id
|
||||
|
||||
this.setFiltersSelectedInEditedItem()
|
||||
this.setChecklistsSelectedInEditedItem()
|
||||
|
||||
const response = await this.$axios.post('/versions', this.editedItem)
|
||||
|
||||
this.dialog = false
|
||||
|
||||
this.$store.commit('learning/ADD_VERSION_LOCAL', response.data)
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Version stored`,
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('save -> error', error)
|
||||
|
||||
this.dialogVersion = false
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to store the version`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
this.loading = false
|
||||
this.close()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.v-card >>> table,
|
||||
.v-card >>> .v-data-table-header tr,
|
||||
.v-card >>> .v-data-footer {
|
||||
background-color: var(--v-primary-base);
|
||||
}
|
||||
.v-card >>> .v-data-table-header th span {
|
||||
color: var(--v-tertiary-base);
|
||||
}
|
||||
.v-card >>> .text-start,
|
||||
.v-card >>> .v-icon,
|
||||
.v-dialog__content >>> .v-subheader,
|
||||
.v-dialog__content >>> i {
|
||||
color: var(--v-txt-base);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.v-card >>> p {
|
||||
margin: 0;
|
||||
color: var(--v-txt-base);
|
||||
}
|
||||
|
||||
.v-dialog .v-card {
|
||||
background: var(--v-secondary-base);
|
||||
}
|
||||
|
||||
table tr button.view {
|
||||
opacity: 0;
|
||||
}
|
||||
table tr:hover button.view {
|
||||
opacity: 1;
|
||||
}
|
||||
.v-dialog__content >>> .v-dialog {
|
||||
border: 4px solid var(--v-secAccent-base);
|
||||
max-height: 68%;
|
||||
/* box-shadow: inset 0px 0px 2px 2px var(--v-secAccent-base),
|
||||
inset 6px 6px 14px -14px var(--v-secAccent-base) !important; */
|
||||
}
|
||||
|
||||
.v-dialog__content >>> .v-input__slot {
|
||||
background: var(--v-primary-base);
|
||||
border: 1px solid var(--v-lines-base);
|
||||
}
|
||||
|
||||
.v-list-item >>> .v-input__slot {
|
||||
background: unset;
|
||||
border: none;
|
||||
}
|
||||
.v-list-item--active.secondary {
|
||||
background-color: var(--v-primary-base) !important;
|
||||
}
|
||||
.v-list-item--active::before {
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
.v-list {
|
||||
padding: 0;
|
||||
}
|
||||
.v-menu__content >>> .v-date-picker-table {
|
||||
height: 242px !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user