Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
489 changes: 57 additions & 432 deletions electrostoreFRONT/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions electrostoreFRONT/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/vue-fontawesome": "^3.0.8",
"autoprefixer": "^10.4.20",
"lodash-es": "^4.17.23",
"pinia": "^2.2.8",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
Expand Down
5 changes: 2 additions & 3 deletions electrostoreFRONT/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const listNav = [
];

const containerClasses = computed(() => [
"px-4 pt-4 overflow-y-scroll fixed bottom-0 right-0 left-0 flex flex-col",
"px-4 pt-4 fixed bottom-0 right-0 left-0 flex flex-col",
reduceLeftSideBar.value && authStore.user && !isIframe.value ? "sm:ml-16" : "",
!reduceLeftSideBar.value && authStore.user && !isIframe.value ? "sm:ml-64" : "",
authStore.user && !isIframe.value ? "top-16" : "top-0",
Expand All @@ -40,7 +40,7 @@ const showAboutModal = ref(false);
<NavBar :list-nav="listNav" :load-page-find="modalFinderRef?.loadPageFind || (() => {})"
@update:reduce-left-side-bar="reduceLeftSideBar = $event" @show-about-modal="showAboutModal = true" />
</div>
<div :class="containerClasses">
<div id="view" :class="containerClasses">
<RouterView />
</div>
<ModalFinder ref="modalFinderRef" />
Expand All @@ -49,7 +49,6 @@ const showAboutModal = ref(false);
<div class="bg-white rounded-lg shadow-lg w-3/4 h-3/4 p-6" @click.stop>
</div>
</div>

</template>

<style>
Expand Down
70 changes: 50 additions & 20 deletions electrostoreFRONT/src/components/Commentaire.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
<div v-for="commentaire in storeData[0]"
:key="commentaire[meta.key]" class="flex flex-col border p-4 rounded-lg">
<div :class="{
'text-right': meta.canEdit && commentaire.id_user === storeData[2].id_user,
'text-left': meta.canEdit && commentaire.id_user !== storeData[2].id_user
'text-right': meta.canEdit && commentaire.id_user === storeUser.id_user,
'text-left': meta.canEdit && commentaire.id_user !== storeUser.id_user
}" class="text-sm text-gray-600">
<span class="font-semibold">
{{ storeData[1][commentaire.id_user].nom_user }} {{
Expand Down Expand Up @@ -60,12 +60,12 @@
</template>
<template v-else>
<div :class="{
'text-right': commentaire.id_user === storeData[2].id_user,
'text-left': commentaire.id_user !== storeData[2].id_user
'text-right': commentaire.id_user === storeUser.id_user,
'text-left': commentaire.id_user !== storeUser.id_user
}">
{{ commentaire[meta.contenu] }}
</div>
<div v-if="meta.canEdit && (commentaire.id_user === storeData[2].id_user || storeData[2].role_user === 1 || storeData[2].role_user === 2)"
<div v-if="meta.canEdit && (commentaire.id_user === storeUser.id_user || meta.roleRequired)"
class="flex justify-end space-x-2">
<button type="button" @click="commentaire.tmp = { ...commentaire }"
class="px-3 py-1 bg-yellow-400 text-white rounded-lg hover:bg-yellow-500">
Expand Down Expand Up @@ -111,8 +111,6 @@ export default {
// This should be an array containing:
// [0] - store with all commentaires
// [1] - store with all users
// [2] - current user session data
// [3] - store with configuration data
default: () => [],
},
storeFunction: {
Expand All @@ -125,6 +123,16 @@ export default {
delete: () => Promise.resolve(),
}),
},
storeUser: {
type: Object,
default: () => ({}),
// This should be an object containing the user session data
},
storeConfig: {
type: Object,
default: () => ({}),
// This should be an object containing the configuration store, used to get max length for validation
},
meta: {
type: Object,
required: true,
Expand All @@ -134,31 +142,35 @@ export default {
// - canEdit: boolean indicating if the user can edit comments
// - idRessource: identifier for the resource linked to the comment
// - link: URL for the resource linked to the comment
// - roleRequired: boolean indicating if a specific role is required to edit/delete all comments (not just the user's own comments)
default: () => ({
key: "id_commentaire",
contenu: "contenu_commentaire",
canEdit: false,
idRessource: "id_ressource",
link: "/ressource/",
roleRequired: false,
}),

},
loading: {
type: Boolean,
default: true,
// Indicates if the component is loading data
},
loadedCount: {
type: Number,
default: 0,
},
totalCount: {
type: Number,
default: 0,
},
fetchFunction: {
type: Function,
default: () => {},
default: () => {
return [0, false];
},
},
listFetchFunction: {
type: Array,
default: () => [],
// This should be an array of functions to refetch related lists when a comment is created, updated, or deleted
},
texteModalDelete: {
type: Object,
Expand All @@ -177,6 +189,9 @@ export default {
Field,
ModalDeleteConfirm: defineAsyncComponent(() => import("@/components/ModalDeleteConfirm.vue")),
},
async created() {
await this.refetchData();
},
setup() {
const { addNotification } = inject("useNotification");
return {
Expand All @@ -189,13 +204,16 @@ export default {
selectedCommentaire: null,
deleteModalShow: false,
createLoading: false,
nextOffset: 0,
hasMore: true,
isInitializing: true,
};
},
computed: {
schemaCommentaire() {
return Yup.object().shape({
[this.meta.contenu]: Yup.string()
.max(this.storeData[3].getConfigByKey("max_length_commentaire"), this.$t("components.VModalCommentaireMaxLength") + " " + this.storeData[3].getConfigByKey("max_length_commentaire") + this.$t("common.VAllCaracters"))
.max(this.storeConfig.getConfigByKey("max_length_commentaire"), this.$t("components.VModalCommentaireMaxLength") + " " + this.storeConfig.getConfigByKey("max_length_commentaire") + this.$t("common.VAllCaracters"))
.required(this.$t("components.VModalCommentaireRequired")),
});
},
Expand Down Expand Up @@ -250,17 +268,29 @@ export default {
this.deleteModalShow = false;
},
async loadNext(e) {
if (this.totalCount === 0) {
return;
}
if (this.loading) {
if (this.totalCount === 0 || this.loading || !this.hasMore) {
return;
}
if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight - 10) {
if (this.totalCount === this.loadedCount) {
if (this.totalCount === this.nextOffset) {
return;
}
await this.fetchFunction(this.loadedCount + 100, this.loadedCount);
[this.nextOffset, this.hasMore] = await this.fetchFunction(this.nextOffset, 100, this.meta?.expand || []);
}
},
async refetchData() {
// Reset l'état et refetch les données depuis le début
this.nextOffset = 0;
this.hasMore = true;
let intervalOffset = this.nextOffset;
[this.nextOffset, this.hasMore] = await this.fetchFunction(100, 0, this.meta?.expand || []);
await this.refetchListData(intervalOffset, this.nextOffset);
},
async refetchListData(minOffset, maxOffset) {
for (let index = 0; index < this.listFetchFunction.length; index++) {
if (this.listFetchFunction[index]) {
await this.listFetchFunction[index](minOffset, maxOffset);
}
}
},
},
Expand Down
47 changes: 31 additions & 16 deletions electrostoreFRONT/src/components/Filter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@change="$emit('updateText', $event.target.value)">
<option value=""></option>
<template v-if="options">
<option v-for="option in options" :key="option[0]" :value="option[0]">{{ option[1] }}
<option v-for="[index, option] in options" :key="index" :value="index" :selected="preset === index">{{ option }}
</option>
</template>
</select>
Expand Down Expand Up @@ -46,10 +46,10 @@
<div v-show="isOpen"
:ref="`filterList`"
class="absolute border max-h-48 overflow-y-auto bg-white left-0" style="width: calc(100% - 8px);">
<div v-for="option in filterOption" :key="option[0]"
@mousedown.prevent="selectOption(option)"
<div v-for="[index, option] in filterOption" :key="index"
@mousedown.prevent="selectOption(index, option)"
class="flex flex-col p-2 hover:bg-gray-100 cursor-pointer">
<span class="text-sm">{{ option[1] }}</span>
<span class="text-sm">{{ option }}</span>
</div>
</div>
</teleport>
Expand All @@ -58,9 +58,10 @@
<input
:id="`filter-input-${this.$.uid}`"
:type="type"
:placeholder="placeholder"
:value="preset"
class="border border-gray-300 rounded px-2 py-1"
:class="[classCss, label.length > 0 ? 'mr-2' : '']"
:placeholder="placeholder"
@input="$emit('updateText', $event.target.value)" />
</template>
</div>
Expand Down Expand Up @@ -93,49 +94,63 @@ export default {
// e.g., 'write here your text'
default: "",
},
preset: {
type: [String, Number],
required: false,
// This should be the value to preset the input with
default: "",
},
classCss: {
type: String,
required: false,
// This should be a CSS tailwind class for styling the input
default: "",
},
options: {
type: Array,
type: Object,
required: false,
// This should be an array of options for select input
// e.g., [['value1', 'Label 1'], ['value2', 'Label 2']]
// e.g., {[id]: 'Option 1', [id2]: 'Option 2'}
// translate the labels before passing
// to the component
default: () => [],
default: () => ({}),
},
},
data() {
return {
isOpen: false,
inputText: "",
inputText: this.preset,
};
},
emits: ["updateText"],
computed: {
filterOption() {
return Object.values(this.options).filter((element) => {
if (!this.options) {
return [];
}
return Object.entries(this.options).filter(([index, element]) => {
if (this.inputText !== "") {
return element[1].toLowerCase().includes(this.inputText.toLowerCase());
return element.toLowerCase().includes(this.inputText.toLowerCase());
}
return true;
});
},
},
methods: {
selectOption(option){
this.inputText = option[1];
selectOption(index, option){
this.inputText = option;
this.isOpen = false;
this.$emit("updateText", option[0]);
this.$emit("updateText", index);
this.$refs.filterInput.blur();
},
validateInput(){
let result = Object.values(this.options).find((option) => {
return option[1].toLowerCase() === this.inputText.toLowerCase();
if (!this.options) {
this.inputText = "";
this.$emit("updateText", "");
return;
}
let result = Object.entries(this.options).find(([index, option]) => {
return option.toLowerCase() === this.inputText.toLowerCase();
});
if (result) {
this.inputText = result[1];
Expand Down
Loading
Loading