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

Author: @daniboygg
pull/5636/head
Daniel 5 months ago committed by GitHub
parent ccdee28893
commit d30d34ac1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 78
      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>
<PrimeToolbar>
<template #start>
<PrimeButton
<BaseButton
v-if="handleBack"
:label="$t('Back')"
icon="mdi mdi-arrow-left"
class="p-button-outlined"
type="primary"
icon="back"
@click="backAction"
/>
@ -26,12 +26,12 @@
@click="editItem"
/>
<PrimeButton
<BaseButton
v-if="handleSubmit"
:loading="isLoading"
:title="$t('Submit')"
class="p-button-outlined"
icon="mdi mdi-content-save"
:is-loading="isLoading"
:label="$t('Submit')"
type="success"
icon="save"
@click="submitItem"
/>
@ -81,12 +81,14 @@
</template>
<script>
import PrimeToolbar from 'primevue/toolbar';
import PrimeButton from 'primevue/button';
import PrimeToolbar from "primevue/toolbar"
import PrimeButton from "primevue/button"
import BaseButton from "./basecomponents/BaseButton.vue"
export default {
name: 'Toolbar',
name: "Toolbar",
components: {
BaseButton,
PrimeToolbar,
PrimeButton,
},
@ -96,105 +98,105 @@ export default {
},
handleFilter: {
type: Function,
required: false
required: false,
},
handleList: {
type: Function,
required: false
required: false,
},
handleEdit: {
type: Function,
required: false
required: false,
},
handleBack: {
type: Function,
required: false
required: false,
},
handleSubmit: {
type: Function,
required: false
required: false,
},
handleReset: {
type: Function,
required: false
required: false,
},
handleDelete: {
type: Function,
required: false
required: false,
},
handleAdd: {
type: Function,
required: false
required: false,
},
handleSend: {
type: Function,
required: false
required: false,
},
handleAddDocument: {
type: Function,
required: false
required: false,
},
onSendFilter: {
type: Function,
required: false
required: false,
},
resetFilter: {
type: Function,
required: false
required: false,
},
handleUploadDocument: {
type: Function,
required: false
required: false,
},
title: {
type: String,
required: false
required: false,
},
isLoading: {
type: Boolean,
required: false,
default: () => false
}
default: () => false,
},
},
methods: {
backAction() {
if (this.handleBack) {
this.handleBack();
this.handleBack()
}
},
listItem() {
if (this.handleList) {
this.handleList();
this.handleList()
}
},
addItem() {
if (this.handleAdd) {
this.handleAdd();
this.handleAdd()
}
},
addDocument() {
if (this.addDocument) {
this.handleAddDocument();
this.handleAddDocument()
}
},
uploadDocument() {
if (this.uploadDocument) {
this.handleUploadDocument();
this.handleUploadDocument()
}
},
editItem() {
if (this.handleEdit) {
this.handleEdit();
this.handleEdit()
}
},
sendItem() {
if (this.handleSend) {
this.handleSend();
this.handleSend()
}
},
submitItem() {
if (this.handleSubmit) {
this.handleSubmit();
this.handleSubmit()
}
},
onHandleDelete() {
@ -208,9 +210,9 @@ export default {
},
resetItem() {
if (this.handleReset) {
this.handleReset();
}
this.handleReset()
}
},
},
}
};
</script>

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

@ -9,7 +9,11 @@
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)" />
</audio>
@ -22,62 +26,76 @@
@recorded-audio="processAudio($event)"
/>
<div v-if="audio" 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
v-if="audio"
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>
</template>
<script setup>
import { ref } from "vue";
import { useStore } from "vuex";
import { useI18n } from "vue-i18n";
import BaseInputText from "../basecomponents/BaseInputText.vue";
import AudioRecorder from "../AudioRecorder.vue";
import BaseButton from "../basecomponents/BaseButton.vue";
import { RESOURCE_LINK_PUBLISHED } from "../resource_links/visibility";
import { useCidReq } from "../../composables/cidReq";
import { ref } from "vue"
import { useI18n } from "vue-i18n"
import BaseInputText from "../basecomponents/BaseInputText.vue"
import AudioRecorder from "../AudioRecorder.vue"
import BaseButton from "../basecomponents/BaseButton.vue"
import { RESOURCE_LINK_PUBLISHED } from "../resource_links/visibility"
import { useCidReq } from "../../composables/cidReq"
import documentsService from "../../services/documents"
const { t } = useI18n();
const queryParams = useCidReq();
const store = useStore();
const { t } = useI18n()
const queryParams = useCidReq()
const props = defineProps({
parentResourceNodeId: {
type: String,
required: true,
},
});
})
const emit = defineEmits(["document-saved", "document-not-saved"]);
const emit = defineEmits(["document-saved", "document-not-saved"])
const recordName = ref("");
const recordError = ref("");
const audioRecorder = ref(null);
const showAudioRecorderButtons = ref(true);
const audio = ref();
const recordName = ref("")
const recordError = ref("")
const audioRecorder = ref(null)
const showAudioRecorderButtons = ref(true)
const audio = ref()
const processAudio = (recordedAudio) => {
audio.value = recordedAudio;
showAudioRecorderButtons.value = false;
};
audio.value = recordedAudio
showAudioRecorderButtons.value = false
}
const recordAudio = () => {
recordError.value = "";
audio.value = null;
showAudioRecorderButtons.value = true;
audioRecorder.value.record();
};
recordError.value = ""
audio.value = null
showAudioRecorderButtons.value = true
audioRecorder.value.record()
}
const saveAudio = () => {
const saveAudio = async () => {
if (recordName.value === "") {
recordError.value = t("It is necessary a file name before save recorded audio");
return;
recordError.value = t("It is necessary a file name before save recorded audio")
return
}
let fileName = recordName.value + ".wav";
let uploadFile = new File([audio.value], fileName);
let fileName = recordName.value + ".wav"
let uploadFile = new File([audio.value], fileName)
let data = {
title: fileName,
filetype: "file",
@ -89,10 +107,13 @@ const saveAudio = () => {
visibility: RESOURCE_LINK_PUBLISHED,
},
]),
};
store
.dispatch("documents/createWithFormData", data)
.then(() => emit("document-saved"))
.catch((error) => emit("document-not-saved", error));
};
}
try {
await documentsService.createWithFormData(data)
emit("document-saved")
} catch (error) {
emit("document-not-saved", error)
}
}
</script>

@ -1,5 +1,8 @@
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 = {}) {
const baseService = {
find(id, params) {
@ -63,6 +66,14 @@ export default function makeService(endpoint, extensions = {}) {
method: 'PUT',
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">
<DocumentsForm
ref="createForm"
:errors="violations"
:errors="errors"
:values="item"
/>
<Panel
@ -34,8 +34,6 @@
</template>
<script>
import { mapActions } from "vuex"
import { createHelpers } from "vuex-map-fields"
import DocumentsForm from "../../components/documents/FormNewDocument.vue"
import Loading from "../../components/Loading.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 Panel from "primevue/panel"
import TemplateList from "../../components/documents/TemplateList.vue"
import axios from "axios"
import documentsService from "../../services/documents"
const servicePrefix = "Documents"
const { mapFields } = createHelpers({
getterType: "documents/getField",
mutationType: "documents/updateField",
})
export default {
name: "DocumentsCreateFile",
servicePrefix,
@ -68,19 +61,19 @@ export default {
const finalTags = this.getCertificateTags()
return {
item: {
title: "",
contentFile: "",
newDocument: true, // Used in FormNewDocument.vue to show the editor
filetype: filetype,
parentResourceNodeId: null,
resourceLinkList: null,
contentFile: null,
},
templates: [],
isLoading: false,
errors: {},
finalTags,
}
},
computed: {
...mapFields(["error", "isLoading", "created", "violations"]),
},
created() {
this.item.parentResourceNodeId = this.$route.params.node
this.item.resourceLinkList = JSON.stringify([
@ -92,7 +85,6 @@ export default {
},
])
},
methods: {
handleBack() {
this.$router.back()
@ -100,17 +92,16 @@ export default {
addTemplateToEditor(templateContent) {
this.item.contentFile = templateContent
},
fetchTemplates() {
async fetchTemplates() {
this.errors = {}
const courseId = this.$route.query.cid
axios
.get(`/template/all-templates/${courseId}`)
.then((response) => {
this.templates = response.data
console.log("Templates fetched successfully:", this.templates)
})
.catch((error) => {
console.error("Error fetching templates:", error)
})
try {
let data = await documentsService.getTemplates(courseId)
this.templates = data
} catch (error) {
console.error(error)
this.errors = error.errors
}
},
getCertificateTags() {
let finalTags = ""
@ -144,7 +135,20 @@ export default {
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() {
this.fetchTemplates()

Loading…
Cancel
Save