This commit is contained in:
Matthieu Bessat 2020-07-22 10:00:12 +02:00
parent 90cd5ec582
commit e987cf6c69
15 changed files with 365 additions and 179 deletions

View file

@ -10,7 +10,7 @@
"dependencies": { "dependencies": {
"core-js": "^3.6.5", "core-js": "^3.6.5",
"register-service-worker": "^1.7.1", "register-service-worker": "^1.7.1",
"tiptap-vuetify": "^2.23.0", "tiptap-vuetify": "2.24.0",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-apitator": "0.0.17", "vue-apitator": "0.0.17",
"vue-class-component": "^7.2.3", "vue-class-component": "^7.2.3",

View file

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -9,13 +9,12 @@ Github: https://github.com/lefuturiste
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" type="image/png" href="/img/favicon.png" />
<title>Forum virtuel des associations</title> <title>Forum virtuel des associations</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons"/> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
<link rel="icon" href="/img/favicon.png" />
</head> </head>
<body> <body>
<noscript> <noscript>

View file

@ -17,6 +17,7 @@
:height="height" :height="height"
accept="image/jpeg,image/png" accept="image/jpeg,image/png"
prevent-white-space prevent-white-space
:initial-image="imageUrl"
:placeholder-font-size="22" :placeholder-font-size="22"
@file-size-exceed="handleFileSizeExceed" @file-size-exceed="handleFileSizeExceed"
@file-type-mismatch="handleFileTypeMismatch" @file-type-mismatch="handleFileTypeMismatch"
@ -95,6 +96,10 @@ export default {
type: Number, type: Number,
default: 500 default: 500
}, },
imageUrl: {
type: String,
default: ''
},
loading: { loading: {
type: Boolean, type: Boolean,
default: false default: false

View file

@ -43,6 +43,7 @@
</v-tabs> --> </v-tabs> -->
<div class="frame-container"> <div class="frame-container">
<iframe <iframe
v-if="enabled"
class="frame" class="frame"
:src="frameUrl"> :src="frameUrl">
</iframe> </iframe>
@ -77,15 +78,24 @@ export default {
} }
}, },
data: () => ({ data: () => ({
tab: 0 tab: 0,
additional: ''
}), }),
computed: { computed: {
frameUrl () { frameUrl () {
let path = ''
if (this.tab === 1) { if (this.tab === 1) {
return process.env.VUE_APP_BASE_URL + '/association/' + this.slug + '?version=' + this.version path = '/association/' + this.slug + '?version=' + this.version
} else { } else {
return process.env.VUE_APP_BASE_URL + '?only=' + this.id path = '?only=' + this.id
} }
return process.env.VUE_APP_BASE_URL + path + '&hash=' + this.additional
}
},
methods: {
reload () {
// add random data to force the frame to reload
this.additional = Date.now().toString()
} }
} }
} }

View file

@ -6,7 +6,7 @@
dark dark
flat flat
> >
<v-toolbar-title>{{ $store.state.delegate.adminName }}</v-toolbar-title> <v-toolbar-title>{{ $store.state.data.name }}</v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn <v-btn
outlined outlined
@ -233,6 +233,7 @@ export default {
} }
}, },
mounted () { mounted () {
this.$store.commit('SET_TITLE', "Modification de l'association")
this.selectRoute(this.$route) this.selectRoute(this.$route)
/** /**
* this is very ugly I kown * this is very ugly I kown
@ -375,6 +376,7 @@ export default {
this.$store.commit('VALIDATE_MAIN', isValid => { this.$store.commit('VALIDATE_MAIN', isValid => {
if (isValid) { if (isValid) {
this.publishModal = true this.publishModal = true
this.save()
} else { } else {
this.$store.commit('ADD_ALERT', { this.$store.commit('ADD_ALERT', {
color: 'error', color: 'error',

View file

@ -31,7 +31,8 @@ export default new Vuex.Store({
address: '', address: '',
person: '', person: '',
email: '', email: '',
phone: '' phone: '',
peoples: []
} }
}, },
delegate: { delegate: {
@ -42,7 +43,7 @@ export default new Vuex.Store({
}, },
debug: false, debug: false,
validateMain: false, validateMain: false,
validateMainCallback: (d: boolean) => false validateMainCallback: (d = false) => d
}, },
mutations: { mutations: {
SET_DEBUG (state, payload) { SET_DEBUG (state, payload) {

View file

@ -284,6 +284,7 @@
</v-card> </v-card>
</v-dialog> </v-dialog>
<Preview <Preview
ref="preview"
:enabled="approveModal" :enabled="approveModal"
:id="toApproveItem._id" :id="toApproveItem._id"
:slug="toApproveItem.slugs[0]" :slug="toApproveItem.slugs[0]"
@ -524,7 +525,8 @@ export default {
}, },
openExternal (item) { openExternal (item) {
window.open(process.env.VUE_APP_BASE_URL + '/association/' + item.slugs[item.slug.length - 1] + '?version=proposed', '_blank').focus() // '?version=proposed'
window.open(process.env.VUE_APP_BASE_URL + '/association/' + item.slugs[item.slugs.length - 1], '_blank').focus()
}, },
openPanel (item) { openPanel (item) {
@ -533,6 +535,7 @@ export default {
}, },
openApproveModal (item) { openApproveModal (item) {
this.$refs.preview.reload()
this.approveModal = true this.approveModal = true
this.toApproveItem = item this.toApproveItem = item
this.approved = false this.approved = false

View file

@ -42,6 +42,41 @@
outlined outlined
v-model="$store.state.data.contacts.instagram" v-model="$store.state.data.contacts.instagram"
:rules="rules.instagram" /> :rules="rules.instagram" />
<p>Contacts additionels</p>
<v-btn @click="addContact()">Ajouter un contact additionel</v-btn>
<v-row
v-for="(contact, index) in $store.state.data.contacts.peoples"
:key="index">
<v-col cols="12" sm="4" class="py-0">
<v-text-field
prepend-icon="person"
label="Nom du contact"
outlined
v-model="contact.name"
:rules="rules.person" />
</v-col>
<v-col cols="12" sm="4" class="py-0">
<v-text-field
label="Rôle"
outlined
v-model="contact.role"
:rules="rules.role" />
</v-col>
<v-col cols="12" sm="4" class="py-0">
<v-text-field
label="Email"
outlined
v-model="contact.email"
:rules="rules.email" />
</v-col>
<v-col cols="12" sm="4" class="py-0">
<v-text-field
label="N° de téléphone"
outlined
v-model="contact.phone"
:rules="rules.phone" />
</v-col>
</v-row>
</div> </div>
</template> </template>
@ -66,6 +101,15 @@ export default {
] ]
} }
}), }),
methods: {} methods: {
addContact () {
this.$store.state.contacts.peoples.push({
name: '',
email: '',
role: '',
phone: ''
})
}
}
} }
</script> </script>

View file

@ -1,12 +1,29 @@
<template> <template>
<div> <div>
<v-btn small @click="fill()" class="mb-2">Préremplir</v-btn> <!-- <v-btn small @click="fill()" class="mb-2">Préremplir</v-btn> -->
<div class="d-flex justify-center mb-3">
<v-btn v-if="advanced" small @click="advanced = false">
Mode simple
</v-btn>
<v-btn v-else small @click="advanced = true">
Mode avancé
</v-btn>
</div>
<tiptap-vuetify <tiptap-vuetify
v-if="!advanced"
v-model="$store.state.data.descriptionLong" v-model="$store.state.data.descriptionLong"
:extensions="tiptapExtensions" :extensions="tiptapExtensions"
placeholder="Décrivez ici votre association plus en détail (section présentation)" placeholder="Décrivez ici votre association plus en détail (section présentation)"
min-height="15em" min-height="15em"
/> />
<div v-else id="description-advanced-mode">
<v-textarea
outlined
auto-grow
label="Code html"
v-model="$store.state.data.descriptionLong">
</v-textarea>
</div>
</div> </div>
</template> </template>
@ -33,6 +50,7 @@ export default {
components: { TiptapVuetify }, components: { TiptapVuetify },
data: () => ({ data: () => ({
advanced: false,
tiptapExtensions: [ tiptapExtensions: [
History, History,
Blockquote, Blockquote,
@ -72,3 +90,9 @@ export default {
} }
} }
</script> </script>
<style>
#description-advanced-mode .v-text-field__details {
display: none;
}
</style>

View file

@ -1,34 +1,24 @@
<template> <template>
<div> <div>
<!-- COVER START --> <!-- COVER START -->
<div v-if="false" class="mb-3"> <div v-if="$store.state.data.cover !== undefined && $store.state.data.cover !== null" class="mb-3">
<div <div
class="cover-common cover-container" class="cover-common cover-container"
:style="coverStyle"> :style="coverStyle">
</div> </div>
<div class="cover-common cover-upper"> <div class="cover-common cover-upper">
<div> <div>
<v-btn <!-- <v-btn
@click="$refs.avatarEditor.toggle()" @click="$refs.avatarEditor.toggle()"
color="white" color="white">Changer la couverture</v-btn> -->
>Changer la couverture</v-btn>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-btn <v-btn
v-if="$store.state.data.cover !== null"
class="ml-3" class="ml-3"
@click="clearCover()" @click="clearCover()"
color="white" color="white"
v-bind="attrs"
v-on="on"
icon
outlined outlined
> >
<v-icon>clear</v-icon> <v-icon left>clear</v-icon> Supprimer la couverture
</v-btn> </v-btn>
</template>
<span>Supprimer la couverture</span>
</v-tooltip>
</div> </div>
</div> </div>
</div> </div>
@ -39,6 +29,7 @@
:width="960" :width="960"
:height="300" :height="300"
:modal-size="1000" :modal-size="1000"
:imageUrl="coverImage"
@submitted="handleAvatarEditorSubmitted" @submitted="handleAvatarEditorSubmitted"
/> />
<!-- COVER END --> <!-- COVER END -->
@ -137,7 +128,7 @@
small small
v-bind="attrs" v-bind="attrs"
v-on="on" v-on="on"
@click="shiftRightMedia(media)" @click="chooseAsCover(media)"
> >
<v-icon small>stars</v-icon> <v-icon small>stars</v-icon>
</v-btn> </v-btn>
@ -204,6 +195,7 @@
<v-btn color="primary" text @click="deleteMediaModal = false"> <v-btn color="primary" text @click="deleteMediaModal = false">
Fermer Fermer
</v-btn> </v-btn>
<v-spacer />
<v-btn color="error" text @click="deleteMedia()"> <v-btn color="error" text @click="deleteMedia()">
Supprimer Supprimer
</v-btn> </v-btn>
@ -226,7 +218,8 @@ export default {
files: [], files: [],
deleteMediaModal: false, deleteMediaModal: false,
mediaToDelete: {}, mediaToDelete: {},
uploadProgress: 0 uploadProgress: 0,
coverImage: ''
}), }),
computed: { computed: {
@ -358,11 +351,15 @@ export default {
}, },
clearCover () { clearCover () {
this.$store.commit('SET_DATA', { this.$store.commit('SET_DATA', {
cover: null cover: undefined
}) })
}, },
openMedia (item) { openMedia (item) {
window.open(item.location, '_blank').focus() window.open(item.location, '_blank').focus()
},
chooseAsCover (item) {
this.coverImage = item.location
this.$refs.avatarEditor.toggle()
} }
} }
} }

View file

@ -10,25 +10,20 @@
v-if="$store.state.data.pricing.length === 0" v-if="$store.state.data.pricing.length === 0"
class="mb-8 mt-8"> class="mb-8 mt-8">
<v-alert <v-alert
border="left" border="left" color="grey darken-2" outlined type="info"
color="grey darken-2"
outlined
type="info"
> >
Aucun tarifs ajoutée pour le moment Aucun tarifs ajoutée pour le moment
</v-alert> </v-alert>
</div> </div>
<v-row v-else class="justify-content: center"> <v-row v-else class="justify-center">
<v-col <v-col
v-for="pricing in $store.state.data.pricing" v-for="pricing in $store.state.data.pricing"
:key="pricing._id" :key="pricing._id"
cols="12" cols="12" sm="12" md="6" lg="4"
sm="12"
md="6"
lg="4"
> >
<v-card <v-card
class="mx-auto" class="mx-auto pricing-card"
:class="removeExampleData ? 'disabled' : ''"
max-width="400" max-width="400"
> >
<v-card-text> <v-card-text>
@ -43,18 +38,16 @@
<v-card-actions> <v-card-actions>
<v-spacer /> <v-spacer />
<v-btn <v-btn
icon outlined color="error"
:disabled="removeExampleData"
@click="openDeleteModal(pricing)" @click="openDeleteModal(pricing)"
icon
outlined
color="error"
> >
<v-icon small>delete</v-icon> <v-icon small>delete</v-icon>
</v-btn> </v-btn>
<v-btn <v-btn
icon outlined color="info"
:disabled="removeExampleData"
@click="openEditModal(pricing)" @click="openEditModal(pricing)"
icon
outlined
color="info"
> >
<v-icon small>edit</v-icon> <v-icon small>edit</v-icon>
</v-btn> </v-btn>
@ -83,9 +76,9 @@
label="Description/Sous Titre du tarif" label="Description/Sous Titre du tarif"
hint="Optionel" hint="Optionel"
/> />
<div class="d-flex justify-center"> <!-- <div class="d-flex justify-center">
<v-btn small @click="loadDummy()">Préremplir</v-btn> <v-btn small @click="loadDummy()">Préremplir</v-btn>
</div> </div> -->
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-btn @click="itemModal = false" text color="primary"> <v-btn @click="itemModal = false" text color="primary">
@ -132,11 +125,38 @@ export default {
item: {}, item: {},
toDelete: {}, toDelete: {},
deleteModal: false, deleteModal: false,
oldEdit: {} oldEdit: {},
removeExampleData: false,
exampleData: [
{
priceLabel: '12 €',
name: "Tarif d'exemple",
description: 'Dans cet onglet, vous pouvez spécifier différents tarifs ou réductions'
}
]
}), }),
computed: { computed: {
itemModalTitle () { return this.mode === 'add' ? 'Ajouter' : 'Editer' } itemModalTitle () { return this.mode === 'add' ? 'Ajouter' : 'Editer' }
}, },
created () {
if (this.$store.state.data.pricing.length === 0) {
this.removeExampleData = true
this.$store.commit('SET_DATA', {
pricing: this.exampleData
})
}
},
destroyed () {
if (this.removeExampleData) {
this.$store.commit('SET_DATA', {
pricing: []
})
}
},
methods: { methods: {
loadDummy () { loadDummy () {
this.item = JSON.parse('{"priceLabel":"3.14159 €","name":"Hippie","description":"Vomissures que ce juillets haleurs haleurs dont, roulant"}') this.item = JSON.parse('{"priceLabel":"3.14159 €","name":"Hippie","description":"Vomissures que ce juillets haleurs haleurs dont, roulant"}')
@ -148,6 +168,10 @@ export default {
}, },
save () { save () {
let pricing = this.$store.state.data.pricing let pricing = this.$store.state.data.pricing
if (this.removeExampleData) {
pricing = []
this.removeExampleData = false
}
if (this.mode === 'add') { if (this.mode === 'add') {
this.item._id = Date.now().toString() this.item._id = Date.now().toString()
pricing.push(this.item) pricing.push(this.item)
@ -177,3 +201,9 @@ export default {
} }
} }
</script> </script>
<style scoped>
.pricing-card.disabled {
opacity: .8;
}
</style>

View file

@ -21,8 +21,9 @@
<div v-else> <div v-else>
<div <div
class="schedule-item" class="schedule-item"
v-for="item in $store.state.data.schedule" v-for="(category, index) in $store.state.data.schedule"
:key="item.name" :key="index"
:class="removeExampleData ? 'disabled' : ''"
> >
<!-- <!--
cols="12" cols="12"
@ -34,52 +35,94 @@
<div class="schedule-content"> <div class="schedule-content">
<v-card-title class="flex-column justify-space-between"> <v-card-title class="flex-column justify-space-between">
<div class="schedule-title-container"> <div class="schedule-title-container">
<div class="subheading font-weight-bold">{{ item.name }}</div> <div class="subheading font-weight-bold"><span class="font-weight-light">N°{{ index + 1 }} - </span> {{ category.name }}</div>
<div class="text-body-1">{{ item.description }}</div> <div class="text-body-2 mt-3">{{ category.description }}</div>
</div> </div>
<div class="mt-5 schedule-actions"> <div class="mt-5 schedule-actions px-4">
<div class="mr-3"> <div class="d-flex justify-space-between" style="width: 100%">
<v-btn outlined icon small color="info" class="mr-2" @click="openEditCategoryModal(item)"> <v-btn
outlined icon small color="info" class="mr-1"
:disabled="removeExampleData"
@click="openEditCategoryModal(category)">
<v-icon small>edit</v-icon> <v-icon small>edit</v-icon>
</v-btn> </v-btn>
<v-btn outlined icon small color="error" @click="openDeleteCategoryModal(item)"> <v-btn
outlined icon small color="error" class="mr-1"
:disabled="removeExampleData"
@click="openDeleteCategoryModal(category)">
<v-icon small>delete</v-icon> <v-icon small>delete</v-icon>
</v-btn> </v-btn>
</div> <v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-btn <v-btn
@click="openAddWhenModal(item)" outlined icon small color="gray" class="mr-1"
outlined v-bind="attrs"
small v-on="on"
color="success"> :disabled="index === 0 || removeExampleData"
Ajouter un horaire @click="shiftCategoryUp(category)">
<v-icon small>keyboard_arrow_up</v-icon>
</v-btn> </v-btn>
</template>
<span>Décaler vers le haut</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-btn
outlined icon small color="gray" class="mr-1"
v-bind="attrs"
v-on="on"
:disabled="index === $store.state.data.schedule.length - 1 || removeExampleData"
@click="shiftCategoryDown(category)">
<v-icon small>keyboard_arrow_down</v-icon>
</v-btn>
</template>
<span>Décaler vers le bas</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-btn
outlined icon small color="success"
v-bind="attrs"
v-on="on"
:disabled="removeExampleData"
@click="openAddWhenModal(category)">
<v-icon small>add</v-icon>
</v-btn>
</template>
<span>Ajouter un crénau horaire</span>
</v-tooltip>
</div>
</div> </div>
</v-card-title> </v-card-title>
<div class="d-flex align-center schedule-days"> <div class="d-flex align-center schedule-days">
<v-list <v-list
v-if="Array.isArray(item.when) && item.when.length > 0" v-if="Array.isArray(category.when) && category.when.length > 0"
dense dense
class="schedule-list"> class="schedule-list">
<v-divider /> <v-divider />
<div <div v-for="(when, index) in category.when" :key="index">
v-for="when in item.when"
:key="when.day">
<v-list-item> <v-list-item>
<v-list-item-content> <v-list-item-content>
<div class="d-flex justify-space-between"> <div class="d-flex justify-space-between">
<div>{{ when.day }}</div> <div>{{ when.day }}</div>
<div>{{ when.from }} - {{ when.to }}</div> <div class="teal--text lighten-2">{{ when.from }} <span class="grey--text lighten-2">-</span> {{ when.to }}</div>
</div> </div>
</v-list-item-content> </v-list-item-content>
<v-list-item-action> <v-list-item-action>
<div class="d-flex justify-space-between"> <div class="d-flex justify-space-between">
<v-btn icon color="info" @click="openEditWhenModal(when)"> <v-btn
icon color="info"
:disabled="removeExampleData"
@click="openEditWhenModal(when, category)">
<v-icon small> <v-icon small>
edit edit
</v-icon> </v-icon>
</v-btn> </v-btn>
<v-btn icon color="error" @click="openDeleteWhenModal(when)"> <v-btn
icon color="error"
:disabled="removeExampleData"
@click="openDeleteWhenModal(when, category)">
<v-icon small>delete</v-icon> <v-icon small>delete</v-icon>
</v-btn> </v-btn>
</div> </div>
@ -88,8 +131,8 @@
<v-divider /> <v-divider />
</div> </div>
</v-list> </v-list>
<div v-else class="grey--text text--darken-1"> <div v-else class="grey--text text--darken-1 px-4 py-4 text-center">
Pas d'intervalles horaires pour cette catégorie pour l'instant Pas de crénaux horaires pour cette catégorie pour l'instant
</div> </div>
</div> </div>
</div> </div>
@ -148,10 +191,10 @@
</v-card> </v-card>
</v-dialog> </v-dialog>
<v-dialog <v-dialog
max-width="500px" max-width="700px"
v-model="whenModal"> v-model="whenModal">
<v-card> <v-card>
<v-card-title v-text="modalTitle + ' un intervalle horaire'" /> <v-card-title v-text="modalTitle + ' un crénau horaire'" />
<v-card-text> <v-card-text>
<v-select <v-select
prepend-icon="event" prepend-icon="event"
@ -159,7 +202,31 @@
:items="days" :items="days"
label="Sélectionnez un jour" label="Sélectionnez un jour"
></v-select> ></v-select>
<v-menu <v-row>
<v-col cols="12" sm="6" class="py-0">
<v-text-field
v-model="when.from"
label="Heure de début"
prepend-icon="schedule"
></v-text-field>
<v-time-picker
v-model="formattedFrom"
format="24hr"
:max="formattedTo" />
</v-col>
<v-col cols="12" sm="6" class="py-0">
<v-text-field
v-model="when.to"
label="Heure de fin"
prepend-icon="schedule"
></v-text-field>
<v-time-picker
v-model="formattedTo"
format="24hr"
:min="formattedFrom" />
</v-col>
</v-row>
<!-- <v-menu
ref="fromMenu" ref="fromMenu"
v-model="fromMenu" v-model="fromMenu"
:close-on-content-click="false" :close-on-content-click="false"
@ -183,8 +250,8 @@
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn text color="primary" @click="$refs.fromMenu.save(when.from)">OK</v-btn> <v-btn text color="primary" @click="$refs.fromMenu.save(when.from)">OK</v-btn>
</v-time-picker> </v-time-picker>
</v-menu> </v-menu> -->
<v-menu <!-- <v-menu
ref="toMenu" ref="toMenu"
v-model="toMenu" v-model="toMenu"
:close-on-content-click="false" :close-on-content-click="false"
@ -203,18 +270,10 @@
v-on="on" v-on="on"
></v-text-field> ></v-text-field>
</template> </template>
<v-time-picker v-model="when.to" format="24hr"> </v-menu> -->
<v-btn text color="primary" @click="toMenu = false">Fermer</v-btn>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
@click="$refs.toMenu.save(when.to)">OK</v-btn>
</v-time-picker>
</v-menu>
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-btn @click="categoryModal = false" text color="primary"> <v-btn @click="whenModal = false" text color="primary">
Fermer Fermer
</v-btn> </v-btn>
<v-spacer /> <v-spacer />
@ -222,7 +281,7 @@
@click="saveWhen()" @click="saveWhen()"
text text
color="success" color="success"
:disabled="when.day.length < 4 || when.to.length !== 5 || when.from.length !== 5"> :disabled="when.day.length < 4 || when.to === null || when.from === null || when.to.length !== 5 || when.from.length !== 5">
Valider Valider
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
@ -233,7 +292,7 @@
v-model="deleteWhenModal"> v-model="deleteWhenModal">
<v-card> <v-card>
<v-card-title> <v-card-title>
Voulez vous vraiment supprimer cette intervalle horaire ? Voulez vous vraiment supprimer ce crénau horaire ?
</v-card-title> </v-card-title>
<v-card-actions> <v-card-actions>
<v-btn @click="deleteWhenModal = false" text color="primary"> <v-btn @click="deleteWhenModal = false" text color="primary">
@ -252,105 +311,76 @@
<script> <script>
export default { export default {
data: () => ({ data: () => ({
scheduleData: [ removeExampleData: false,
exampleData: [
{ {
name: 'Création de robot super cool', name: "Catégorie d'horaire d'exemple",
description: 'Clita duo sanctus sed rebum elitr dolores et lorem stet', description: `
Dans cet onglet vous pouvez renseigner les différents crénaux horaires que votre association propose.
Chaque crénau horaire est rangé dans une "catégorie horaire".
Une catégorie horaire peut par exemple regrouper les différents crénaux proposés pour une tranche d'age spécifique.
`,
when: [ when: [
{ { day: 'Lundi', from: '13:45', to: '14:25' },
day: 'Lundi', { day: 'Mardi', from: '10:30', to: '11:00' },
from: '13:45', { day: 'Mecredi', from: '09:00', to: '10:00' }
to: '14:25'
},
{
day: 'Mardi',
from: '10:30',
to: '11:00'
},
{
day: 'Mecredi',
from: '09:00',
to: '10:00'
}
]
},
{
name: 'Introduction à la programmation',
description: 'Clita duo sanctus sed rebum elitr dolores et lorem stetEt ipsum sit et invidunt invidunt tempor lorem consetetur amet, takimata elitr sanctus nonumy at amet ut ut. Justo et stet sanctus no at at, sit ut sit vero rebum ipsum aliquyam vero. Ea at diam vero vero magna kasd ipsum. Diam ipsum amet consetetur sadipscing amet, sed lorem dolor.',
when: [
{
day: 'Lundi',
from: '13:45',
to: '14:25'
},
{
day: 'Mardi',
from: '10:30',
to: '11:00'
},
{
day: 'Mecredi',
from: '09:00',
to: '10:00'
}
]
},
{
name: 'Ldsldsllds',
description: 'Clita duo sanctus sed rebum elitr dolores et lorem stetEt ipsum sit et invidunt invidunt tempor lorem consetetur amet, takimata elitr sanctus nonumy at amet ut ut. Justo et stet sanctus no at at, sit ut sit vero rebum ipsum aliquyam vero. Ea at diam vero vero magna kasd ipsum. Diam ipsum amet consetetur sadipscing amet, sed lorem dolor.',
when: [
{
day: 'Lundi',
from: '13:45',
to: '14:25'
},
{
day: 'Mardi',
from: '10:30',
to: '11:00'
},
{
day: 'Mecredi',
from: '09:00',
to: '10:00'
}
] ]
} }
], ],
mode: '', mode: '',
categoryModal: false, categoryModal: false,
category: { category: { name: '', description: '' },
name: '',
description: ''
},
deleteCategoryModal: false, deleteCategoryModal: false,
toDeleteCategory: {}, toDeleteCategory: {},
oldEditCategory: {}, oldEditCategory: {},
whenModal: false, whenModal: false,
when: { when: { day: '', from: '', to: '' },
day: '',
from: '',
to: ''
},
deleteWhenModal: false, deleteWhenModal: false,
toDeleteWhen: {}, toDeleteWhen: {},
oldEditWhen: {}, oldEditWhen: {},
fromMenu: false, fromMenu: false,
toMenu: false, toMenu: false,
days: [ days: ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'],
'Lundi', formattedFrom: null,
'Mardi', formattedTo: null
'Mercredi',
'Jeudi',
'Vendredi',
'Samedi'
]
}), }),
created () {
if (this.$store.state.data.schedule.length === 0) {
this.removeExampleData = true
this.$store.commit('SET_DATA', {
schedule: this.exampleData
})
}
},
destroyed () {
if (this.removeExampleData) {
this.$store.commit('SET_DATA', {
schedule: []
})
}
},
computed: { computed: {
modalTitle () { return this.mode === 'add' ? 'Ajouter' : 'Editer' } modalTitle () { return this.mode === 'add' ? 'Ajouter' : 'Editer' }
}, },
watch: {
'when.from' () { this.formattedFrom = /^[0-9]{1,2}:[0-9]{1,2}$/gm.test(this.when.from) ? this.when.from : null },
'when.to' () { this.formattedTo = /^[0-9]{1,2}:[0-9]{1,2}$/gm.test(this.when.to) ? this.when.to : null },
'formattedTo' (val) {
if (val !== this.when.to) {
this.when.to = val
}
},
'formattedFrom' (val) {
if (val !== this.when.from) {
this.when.from = val
}
}
},
methods: { methods: {
openAddCategoryModal () { openAddCategoryModal () {
this.mode = 'add' this.mode = 'add'
@ -368,6 +398,10 @@ export default {
}, },
saveCategory () { saveCategory () {
let schedule = this.$store.state.data.schedule let schedule = this.$store.state.data.schedule
if (this.removeExampleData) {
schedule = []
this.removeExampleData = false
}
if (this.mode === 'add') { if (this.mode === 'add') {
this.category._id = Date.now().toString() this.category._id = Date.now().toString()
schedule.push(this.category) schedule.push(this.category)
@ -388,21 +422,51 @@ export default {
this.$store.commit('SET_DATA', { schedule }) this.$store.commit('SET_DATA', { schedule })
this.deleteCategoryModal = false this.deleteCategoryModal = false
}, },
shiftCategoryUp (item) {
const original = this.$store.state.data.schedule
const index = original.indexOf(item)
if (index === 0) { return }
this.$store.commit('SET_DATA', {
schedule: original.map((m, i) => {
if (i === index - 1) { return original[index] }
if (i === index) { return original[index - 1] }
return m
})
})
},
shiftCategoryDown (item) {
const original = this.$store.state.data.schedule
const index = original.indexOf(item)
if (index === original.length - 1) { return }
this.$store.commit('SET_DATA', {
schedule: original.map((m, i) => {
if (i === index + 1) { return original[index] }
if (i === index) { return original[index + 1] }
return m
})
})
},
openAddWhenModal (parent) { openAddWhenModal (parent) {
this.mode = 'add' this.mode = 'add'
this.whenParent = parent this.whenParent = parent
this.whenModal = true this.whenModal = true
this.when = {
day: '',
from: '',
to: ''
}
}, },
openEditWhenModal (item) { openEditWhenModal (item, parent) {
this.when = item this.when = item
this.oldEditWhen = item this.oldEditWhen = item
this.mode = 'edit' this.mode = 'edit'
this.whenModal = true this.whenModal = true
this.whenParent = parent
}, },
openDeleteWhenModal (item) { openDeleteWhenModal (item, parent) {
this.deleteWhenModal = true this.deleteWhenModal = true
this.toDeleteWhen = item this.toDeleteWhen = item
this.whenParent = parent
}, },
saveWhen () { saveWhen () {
let schedule = this.$store.state.data.schedule let schedule = this.$store.state.data.schedule
@ -415,6 +479,8 @@ export default {
} }
i.when.push(this.when) i.when.push(this.when)
} }
// sort all days
i.when = i.when.sort((a, b) => this.days.indexOf(a.day) >= this.days.indexOf(b.day) ? 1 : -1)
return i return i
}) })
} else { } else {
@ -422,6 +488,8 @@ export default {
if (this.whenParent._id === i._id) { if (this.whenParent._id === i._id) {
i.when = i.when.map(w => w._id === this.when._id ? this.when : w) i.when = i.when.map(w => w._id === this.when._id ? this.when : w)
} }
// sort all days
i.when = i.when.sort((a, b) => this.days.indexOf(a.day) >= this.days.indexOf(b.day) ? 1 : -1)
return i return i
}) })
} }
@ -464,6 +532,9 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.schedule-item.disabled {
opacity: .8;
}
@media (max-width: 900px) { @media (max-width: 900px) {
.schedule-content { .schedule-content {
grid-template-columns: 1fr; grid-template-columns: 1fr;

View file

@ -8627,10 +8627,10 @@ tiptap-utils@^1.10.1:
prosemirror-tables "^1.1.0" prosemirror-tables "^1.1.0"
prosemirror-utils "^0.9.6" prosemirror-utils "^0.9.6"
tiptap-vuetify@^2.23.0: tiptap-vuetify@2.24.0:
version "2.23.0" version "2.24.0"
resolved "https://registry.yarnpkg.com/tiptap-vuetify/-/tiptap-vuetify-2.23.0.tgz#dc6ad26bd029a6392ae86cc5eb9d4b173a211ac6" resolved "https://registry.yarnpkg.com/tiptap-vuetify/-/tiptap-vuetify-2.24.0.tgz#0bfff0d5ffd13f1dfb5c42c2e70fe17b2812913b"
integrity sha512-Yr6ra2XYAxmF2wM+EALaAyTpiqtql3TPa651+aVAGKlkP3Vr3Ydm6+rtTA/GAlspX3IPq/x61DG4NDrKdMnZMQ== integrity sha512-9GDXYr/wux8i2vVCOpigmDZDaBfjqO9OCxctWlH6zwNKr4enN0jfIySd6CDHN7E5eY7Vn61etkfQ4sRVGvH80g==
dependencies: dependencies:
popper.js "^1.16.1" popper.js "^1.16.1"
tiptap "^1.16.2" tiptap "^1.16.2"