Internal: Remove Vuex from some document components and change buttons for better consistency (#5432)

Author: @daniboygg
pull/5636/head
Daniel 1 year ago committed by GitHub
parent ccdee28893
commit d30d34ac1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 80
      assets/vue/components/Toolbar.vue
  2. 5
      assets/vue/components/basecomponents/BaseButton.vue
  3. 103
      assets/vue/components/documents/DocumentAudioRecorder.vue
  4. 11
      assets/vue/services/api.js
  5. 21
      assets/vue/services/documents.js
  6. 54
      assets/vue/views/documents/CreateFile.vue

@ -1,11 +1,11 @@
<template> <template>
<PrimeToolbar> <PrimeToolbar>
<template #start> <template #start>
<PrimeButton <BaseButton
v-if="handleBack" v-if="handleBack"
:label="$t('Back')" :label="$t('Back')"
icon="mdi mdi-arrow-left" type="primary"
class="p-button-outlined" icon="back"
@click="backAction" @click="backAction"
/> />
@ -26,12 +26,12 @@
@click="editItem" @click="editItem"
/> />
<PrimeButton <BaseButton
v-if="handleSubmit" v-if="handleSubmit"
:loading="isLoading" :is-loading="isLoading"
:title="$t('Submit')" :label="$t('Submit')"
class="p-button-outlined" type="success"
icon="mdi mdi-content-save" icon="save"
@click="submitItem" @click="submitItem"
/> />
@ -81,12 +81,14 @@
</template> </template>
<script> <script>
import PrimeToolbar from 'primevue/toolbar'; import PrimeToolbar from "primevue/toolbar"
import PrimeButton from 'primevue/button'; import PrimeButton from "primevue/button"
import BaseButton from "./basecomponents/BaseButton.vue"
export default { export default {
name: 'Toolbar', name: "Toolbar",
components: { components: {
BaseButton,
PrimeToolbar, PrimeToolbar,
PrimeButton, PrimeButton,
}, },
@ -96,105 +98,105 @@ export default {
}, },
handleFilter: { handleFilter: {
type: Function, type: Function,
required: false required: false,
}, },
handleList: { handleList: {
type: Function, type: Function,
required: false required: false,
}, },
handleEdit: { handleEdit: {
type: Function, type: Function,
required: false required: false,
}, },
handleBack: { handleBack: {
type: Function, type: Function,
required: false required: false,
}, },
handleSubmit: { handleSubmit: {
type: Function, type: Function,
required: false required: false,
}, },
handleReset: { handleReset: {
type: Function, type: Function,
required: false required: false,
}, },
handleDelete: { handleDelete: {
type: Function, type: Function,
required: false required: false,
}, },
handleAdd: { handleAdd: {
type: Function, type: Function,
required: false required: false,
}, },
handleSend: { handleSend: {
type: Function, type: Function,
required: false required: false,
}, },
handleAddDocument: { handleAddDocument: {
type: Function, type: Function,
required: false required: false,
}, },
onSendFilter: { onSendFilter: {
type: Function, type: Function,
required: false required: false,
}, },
resetFilter: { resetFilter: {
type: Function, type: Function,
required: false required: false,
}, },
handleUploadDocument: { handleUploadDocument: {
type: Function, type: Function,
required: false required: false,
}, },
title: { title: {
type: String, type: String,
required: false required: false,
}, },
isLoading: { isLoading: {
type: Boolean, type: Boolean,
required: false, required: false,
default: () => false default: () => false,
} },
}, },
methods: { methods: {
backAction() { backAction() {
if (this.handleBack) { if (this.handleBack) {
this.handleBack(); this.handleBack()
} }
}, },
listItem() { listItem() {
if (this.handleList) { if (this.handleList) {
this.handleList(); this.handleList()
} }
}, },
addItem() { addItem() {
if (this.handleAdd) { if (this.handleAdd) {
this.handleAdd(); this.handleAdd()
} }
}, },
addDocument() { addDocument() {
if (this.addDocument) { if (this.addDocument) {
this.handleAddDocument(); this.handleAddDocument()
} }
}, },
uploadDocument() { uploadDocument() {
if (this.uploadDocument) { if (this.uploadDocument) {
this.handleUploadDocument(); this.handleUploadDocument()
} }
}, },
editItem() { editItem() {
if (this.handleEdit) { if (this.handleEdit) {
this.handleEdit(); this.handleEdit()
} }
}, },
sendItem() { sendItem() {
if (this.handleSend) { if (this.handleSend) {
this.handleSend(); this.handleSend()
} }
}, },
submitItem() { submitItem() {
if (this.handleSubmit) { if (this.handleSubmit) {
this.handleSubmit(); this.handleSubmit()
} }
}, },
onHandleDelete() { onHandleDelete() {
@ -208,9 +210,9 @@ export default {
}, },
resetItem() { resetItem() {
if (this.handleReset) { if (this.handleReset) {
this.handleReset(); this.handleReset()
} }
} },
} },
}; }
</script> </script>

@ -13,6 +13,7 @@
:text="onlyIcon" :text="onlyIcon"
:title="onlyIcon ? label : undefined" :title="onlyIcon ? label : undefined"
:type="isSubmit ? 'submit' : 'button'" :type="isSubmit ? 'submit' : 'button'"
:loading="isLoading"
@click="$emit('click', $event)" @click="$emit('click', $event)"
/> />
</template> </template>
@ -62,6 +63,10 @@ const props = defineProps({
required: false, required: false,
default: false, default: false,
}, },
isLoading: {
type: Boolean,
default: false,
},
}) })
defineEmits(["click"]) defineEmits(["click"])

@ -9,7 +9,11 @@
class="max-w-full self-center mb-4 w-60" class="max-w-full self-center mb-4 w-60"
/> />
<audio v-if="audio" class="max-w-full self-center mb-4" controls> <audio
v-if="audio"
class="max-w-full self-center mb-4"
controls
>
<source :src="window.URL.createObjectURL(audio)" /> <source :src="window.URL.createObjectURL(audio)" />
</audio> </audio>
@ -22,62 +26,76 @@
@recorded-audio="processAudio($event)" @recorded-audio="processAudio($event)"
/> />
<div v-if="audio" class="flex"> <div
<BaseButton :label="t('Start recording')" class="mr-2" icon="restart" type="black" @click="recordAudio" /> v-if="audio"
<BaseButton :label="t('Save recorded audio')" class="mr-2" icon="send" type="success" @click="saveAudio" /> class="flex"
>
<BaseButton
:label="t('Start recording')"
class="mr-2"
icon="restart"
type="black"
@click="recordAudio"
/>
<BaseButton
:label="t('Save recorded audio')"
class="mr-2"
icon="send"
type="success"
@click="saveAudio"
/>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue"
import { useStore } from "vuex"; import { useI18n } from "vue-i18n"
import { useI18n } from "vue-i18n"; import BaseInputText from "../basecomponents/BaseInputText.vue"
import BaseInputText from "../basecomponents/BaseInputText.vue"; import AudioRecorder from "../AudioRecorder.vue"
import AudioRecorder from "../AudioRecorder.vue"; import BaseButton from "../basecomponents/BaseButton.vue"
import BaseButton from "../basecomponents/BaseButton.vue"; import { RESOURCE_LINK_PUBLISHED } from "../resource_links/visibility"
import { RESOURCE_LINK_PUBLISHED } from "../resource_links/visibility"; import { useCidReq } from "../../composables/cidReq"
import { useCidReq } from "../../composables/cidReq"; import documentsService from "../../services/documents"
const { t } = useI18n(); const { t } = useI18n()
const queryParams = useCidReq(); const queryParams = useCidReq()
const store = useStore();
const props = defineProps({ const props = defineProps({
parentResourceNodeId: { parentResourceNodeId: {
type: String, type: String,
required: true, required: true,
}, },
}); })
const emit = defineEmits(["document-saved", "document-not-saved"]); const emit = defineEmits(["document-saved", "document-not-saved"])
const recordName = ref(""); const recordName = ref("")
const recordError = ref(""); const recordError = ref("")
const audioRecorder = ref(null); const audioRecorder = ref(null)
const showAudioRecorderButtons = ref(true); const showAudioRecorderButtons = ref(true)
const audio = ref(); const audio = ref()
const processAudio = (recordedAudio) => { const processAudio = (recordedAudio) => {
audio.value = recordedAudio; audio.value = recordedAudio
showAudioRecorderButtons.value = false; showAudioRecorderButtons.value = false
}; }
const recordAudio = () => { const recordAudio = () => {
recordError.value = ""; recordError.value = ""
audio.value = null; audio.value = null
showAudioRecorderButtons.value = true; showAudioRecorderButtons.value = true
audioRecorder.value.record(); audioRecorder.value.record()
}; }
const saveAudio = () => { const saveAudio = async () => {
if (recordName.value === "") { if (recordName.value === "") {
recordError.value = t("It is necessary a file name before save recorded audio"); recordError.value = t("It is necessary a file name before save recorded audio")
return; return
} }
let fileName = recordName.value + ".wav"; let fileName = recordName.value + ".wav"
let uploadFile = new File([audio.value], fileName); let uploadFile = new File([audio.value], fileName)
let data = { let data = {
title: fileName, title: fileName,
filetype: "file", filetype: "file",
@ -89,10 +107,13 @@ const saveAudio = () => {
visibility: RESOURCE_LINK_PUBLISHED, visibility: RESOURCE_LINK_PUBLISHED,
}, },
]), ]),
}; }
store
.dispatch("documents/createWithFormData", data) try {
.then(() => emit("document-saved")) await documentsService.createWithFormData(data)
.catch((error) => emit("document-not-saved", error)); emit("document-saved")
}; } catch (error) {
emit("document-not-saved", error)
}
}
</script> </script>

@ -1,5 +1,8 @@
import fetch from '../utils/fetch'; import fetch from '../utils/fetch';
// As stated here https://github.com/chamilo/chamilo-lms/pull/5386#discussion_r1578471409
// this service should not be used and instead the assets/bue/config/api.js should be used instead
// take a look at assets/bue/services/socialService.js to have an example
export default function makeService(endpoint, extensions = {}) { export default function makeService(endpoint, extensions = {}) {
const baseService = { const baseService = {
find(id, params) { find(id, params) {
@ -63,6 +66,14 @@ export default function makeService(endpoint, extensions = {}) {
method: 'PUT', method: 'PUT',
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
},
handleError(error, errorsRef, violationsRef) {
if (error instanceof SubmissionError) {
violationsRef.value = error.errors
errorsRef.value = error.errors._error
return
}
errorsRef.value = error.message
} }
}; };

@ -1,3 +1,20 @@
import makeService from './api'; import makeService from "./api"
import baseService from "./baseService"
export default makeService('documents'); // we should refactor this to use methods in export default using baseService
// see assets/vue/services/api.js for reference
const oldService = makeService("documents")
export default {
...oldService,
/**
* Retrieves all document templates for a given course.
*
* @param {string} courseId - The ID of the course.
* @returns {Promise}
*/
getTemplates: async (courseId) => {
return baseService.get(`/template/all-templates/${courseId}`)
},
}

@ -15,7 +15,7 @@
<div class="documents-form-container"> <div class="documents-form-container">
<DocumentsForm <DocumentsForm
ref="createForm" ref="createForm"
:errors="violations" :errors="errors"
:values="item" :values="item"
/> />
<Panel <Panel
@ -34,8 +34,6 @@
</template> </template>
<script> <script>
import { mapActions } from "vuex"
import { createHelpers } from "vuex-map-fields"
import DocumentsForm from "../../components/documents/FormNewDocument.vue" import DocumentsForm from "../../components/documents/FormNewDocument.vue"
import Loading from "../../components/Loading.vue" import Loading from "../../components/Loading.vue"
import Toolbar from "../../components/Toolbar.vue" import Toolbar from "../../components/Toolbar.vue"
@ -43,15 +41,10 @@ import CreateMixin from "../../mixins/CreateMixin"
import { RESOURCE_LINK_PUBLISHED } from "../../components/resource_links/visibility" import { RESOURCE_LINK_PUBLISHED } from "../../components/resource_links/visibility"
import Panel from "primevue/panel" import Panel from "primevue/panel"
import TemplateList from "../../components/documents/TemplateList.vue" import TemplateList from "../../components/documents/TemplateList.vue"
import axios from "axios" import documentsService from "../../services/documents"
const servicePrefix = "Documents" const servicePrefix = "Documents"
const { mapFields } = createHelpers({
getterType: "documents/getField",
mutationType: "documents/updateField",
})
export default { export default {
name: "DocumentsCreateFile", name: "DocumentsCreateFile",
servicePrefix, servicePrefix,
@ -68,19 +61,19 @@ export default {
const finalTags = this.getCertificateTags() const finalTags = this.getCertificateTags()
return { return {
item: { item: {
title: "",
contentFile: "",
newDocument: true, // Used in FormNewDocument.vue to show the editor newDocument: true, // Used in FormNewDocument.vue to show the editor
filetype: filetype, filetype: filetype,
parentResourceNodeId: null, parentResourceNodeId: null,
resourceLinkList: null, resourceLinkList: null,
contentFile: null,
}, },
templates: [], templates: [],
isLoading: false,
errors: {},
finalTags, finalTags,
} }
}, },
computed: {
...mapFields(["error", "isLoading", "created", "violations"]),
},
created() { created() {
this.item.parentResourceNodeId = this.$route.params.node this.item.parentResourceNodeId = this.$route.params.node
this.item.resourceLinkList = JSON.stringify([ this.item.resourceLinkList = JSON.stringify([
@ -92,7 +85,6 @@ export default {
}, },
]) ])
}, },
methods: { methods: {
handleBack() { handleBack() {
this.$router.back() this.$router.back()
@ -100,17 +92,16 @@ export default {
addTemplateToEditor(templateContent) { addTemplateToEditor(templateContent) {
this.item.contentFile = templateContent this.item.contentFile = templateContent
}, },
fetchTemplates() { async fetchTemplates() {
this.errors = {}
const courseId = this.$route.query.cid const courseId = this.$route.query.cid
axios try {
.get(`/template/all-templates/${courseId}`) let data = await documentsService.getTemplates(courseId)
.then((response) => { this.templates = data
this.templates = response.data } catch (error) {
console.log("Templates fetched successfully:", this.templates) console.error(error)
}) this.errors = error.errors
.catch((error) => { }
console.error("Error fetching templates:", error)
})
}, },
getCertificateTags() { getCertificateTags() {
let finalTags = "" let finalTags = ""
@ -144,7 +135,20 @@ export default {
return finalTags return finalTags
}, },
...mapActions("documents", ["createWithFormData", "reset"]), async createWithFormData(payload) {
this.isLoading = true
this.errors = {}
try {
let response = await documentsService.createWithFormData(payload)
let data = await response.json()
console.log(data)
} catch (error) {
console.error(error)
this.errors = error.errors
} finally {
this.isLoading = false
}
},
}, },
mounted() { mounted() {
this.fetchTemplates() this.fetchTemplates()

Loading…
Cancel
Save