From 760fd43f8768b102464545a07e2aea7b1e630b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bult=C3=A9?= Date: Thu, 6 Jun 2024 08:19:56 +0200 Subject: [PATCH 01/17] chore: migrate ecosphere extras --- src/components/HomeThemes.vue | 5 +- .../ecospheres/components/BouquetCard.vue | 13 ++-- .../ecospheres/components/BouquetList.vue | 44 +++-------- .../datasets/DatasetAddToBouquetModal.vue | 7 +- .../components/forms/bouquet/BouquetForm.vue | 21 +++--- src/custom/ecospheres/utils/bouquet.ts | 75 ++++++++++--------- .../views/bouquets/BouquetDetailView.vue | 12 +-- .../views/bouquets/BouquetFormView.vue | 12 ++- src/model/topic.ts | 11 ++- src/views/datasets/DatasetsListView.vue | 2 +- 10 files changed, 85 insertions(+), 117 deletions(-) diff --git a/src/components/HomeThemes.vue b/src/components/HomeThemes.vue index a15899ce6..5ff3cfd0a 100644 --- a/src/components/HomeThemes.vue +++ b/src/components/HomeThemes.vue @@ -15,10 +15,7 @@ const getCustomBoxShadow = (color: string) => { const getThemeDescription = (theme: Theme) => { const nbBouquets = topicStore.data.filter((topic) => { - return ( - !topic.private && - topic.extras['ecospheres:informations'][0].theme === theme.name - ) + return !topic.private && topic.extras.ecospheres.theme === theme.name }).length switch (nbBouquets) { case 0: diff --git a/src/custom/ecospheres/components/BouquetCard.vue b/src/custom/ecospheres/components/BouquetCard.vue index 08aaaef73..f583edca2 100644 --- a/src/custom/ecospheres/components/BouquetCard.vue +++ b/src/custom/ecospheres/components/BouquetCard.vue @@ -1,4 +1,5 @@ diff --git a/src/custom/ecospheres/utils/bouquet.ts b/src/custom/ecospheres/utils/bouquet.ts index 6c661ca35..511434ad5 100644 --- a/src/custom/ecospheres/utils/bouquet.ts +++ b/src/custom/ecospheres/utils/bouquet.ts @@ -4,10 +4,10 @@ import type { BreadcrumbItem } from '@/model/breadcrumb' import { Availability, type Topic, - type EcospheresTopicExtras, type TopicExtras, type TopicPostData, - type DatasetProperties + type DatasetProperties, + type EcospheresTopicExtras } from '@/model/topic' import { useTopicStore } from '@/store/TopicStore' import { useUserStore } from '@/store/UserStore' @@ -18,7 +18,7 @@ export const isAvailable = (availability: Availability): boolean => { ) } -export const updateExtras = ( +export const updateEcospheresExtras = ( topic: Topic, data: Partial ): TopicExtras => { @@ -41,22 +41,21 @@ export const cloneTopic = (topic: Topic): TopicPostData => { private: true, datasets: [], reuses: [], + spatial: undefined, owner: useUserStore().data ?? null, - extras: { - ...updateExtras(topic, { cloned_from: topic.id }), - // FIXME: move to updateExtras logic when extras are migrated to new schema - 'ecospheres:datasets_properties': topic.extras[ - 'ecospheres:datasets_properties' - ].map((dp) => { - return { - ...dp, - id: null, - uri: null, - availability: Availability.NOT_AVAILABLE + extras: updateEcospheresExtras(topic, { + cloned_from: topic.id, + datasets_properties: topic.extras.ecospheres.datasets_properties.map( + (dp) => { + return { + ...dp, + id: null, + uri: null, + availability: Availability.NOT_AVAILABLE + } } - }) - }, - spatial: undefined + ) + }) } } @@ -100,25 +99,29 @@ export function useExtras(topic: Ref): { const datasetsProperties: Ref = ref([]) const clonedFrom = ref(null) - watch(topic, () => { - theme.value = topic.value?.extras['ecospheres:informations'][0].theme - subtheme.value = topic.value?.extras['ecospheres:informations'][0].subtheme - datasetsProperties.value = - topic.value?.extras['ecospheres:datasets_properties'] ?? [] - if (topic.value?.extras?.ecospheres?.cloned_from != null) { - useTopicStore() - .load(topic.value?.extras.ecospheres.cloned_from, { toasted: false }) - .then((res) => { - clonedFrom.value = res - }) - .catch((err) => { - console.error('Failed fetching cloned_from', err.response?.data) - clonedFrom.value = null - }) - } else { - clonedFrom.value = null - } - }) + watch( + topic, + () => { + theme.value = topic.value?.extras.ecospheres.theme + subtheme.value = topic.value?.extras.ecospheres.subtheme + datasetsProperties.value = + topic.value?.extras.ecospheres.datasets_properties ?? [] + if (topic.value?.extras.ecospheres.cloned_from != null) { + useTopicStore() + .load(topic.value?.extras.ecospheres.cloned_from, { toasted: false }) + .then((res) => { + clonedFrom.value = res + }) + .catch((err) => { + console.error('Failed fetching cloned_from', err.response?.data) + clonedFrom.value = null + }) + } else { + clonedFrom.value = null + } + }, + { immediate: true } + ) return { theme, subtheme, datasetsProperties, clonedFrom } } diff --git a/src/custom/ecospheres/views/bouquets/BouquetDetailView.vue b/src/custom/ecospheres/views/bouquets/BouquetDetailView.vue index c958a847c..504355001 100644 --- a/src/custom/ecospheres/views/bouquets/BouquetDetailView.vue +++ b/src/custom/ecospheres/views/bouquets/BouquetDetailView.vue @@ -17,7 +17,8 @@ import config from '@/config' import BouquetDatasetList from '@/custom/ecospheres/components/BouquetDatasetList.vue' import { useBreadcrumbLinksForTopic, - useExtras + useExtras, + updateEcospheresExtras } from '@/custom/ecospheres/utils/bouquet' import { type Topic } from '@/model/topic' import { useTopicStore } from '@/store/TopicStore' @@ -81,17 +82,16 @@ const onUpdateDatasets = () => { const loader = useLoading().show() store .update(topic.value.id, { - // send the tags or they will be erased + // send the tags or payload will be rejected tags: topic.value.tags, datasets: datasetsProperties.value .filter((d) => d.id !== null && d.remoteDeleted !== true) .map((d) => d.id), - extras: { - ...topic.value.extras, - 'ecospheres:datasets_properties': datasetsProperties.value.map( + extras: updateEcospheresExtras(topic.value, { + datasets_properties: datasetsProperties.value.map( ({ remoteDeleted, ...data }) => data ) - } + }) }) .finally(() => loader.hide()) } diff --git a/src/custom/ecospheres/views/bouquets/BouquetFormView.vue b/src/custom/ecospheres/views/bouquets/BouquetFormView.vue index 315acbd5f..99748933b 100644 --- a/src/custom/ecospheres/views/bouquets/BouquetFormView.vue +++ b/src/custom/ecospheres/views/bouquets/BouquetFormView.vue @@ -29,13 +29,11 @@ const topic: Ref> = ref({ tags: [config.universe.name], spatial: routeQuery.geozone ? { zones: [routeQuery.geozone] } : undefined, extras: { - 'ecospheres:informations': [ - { - theme: routeQuery.theme || NoOptionSelected, - subtheme: routeQuery.subtheme || NoOptionSelected - } - ], - 'ecospheres:datasets_properties': [] + ecospheres: { + theme: routeQuery.theme || NoOptionSelected, + subtheme: routeQuery.subtheme || NoOptionSelected, + datasets_properties: [] + } } }) const errorMsg = ref('') diff --git a/src/model/topic.ts b/src/model/topic.ts index 576dd67b9..8225daacc 100644 --- a/src/model/topic.ts +++ b/src/model/topic.ts @@ -20,16 +20,15 @@ export interface DatasetProperties { } export interface EcospheresTopicExtras { + theme: string + subtheme: string + datasets_properties: DatasetProperties[] cloned_from?: string } export interface TopicExtras { - ['ecospheres:informations']: Array<{ - theme: string - subtheme: string - }> - ['ecospheres:datasets_properties']: DatasetProperties[] - ecospheres?: EcospheresTopicExtras + ecospheres: EcospheresTopicExtras + [key: string]: any } export type Topic = Owned & { diff --git a/src/views/datasets/DatasetsListView.vue b/src/views/datasets/DatasetsListView.vue index 4d8d079e2..f401fb9f1 100644 --- a/src/views/datasets/DatasetsListView.vue +++ b/src/views/datasets/DatasetsListView.vue @@ -241,7 +241,7 @@ onMounted(() => { :style="zIndex(index)" :dataset="d" :dataset-url="getDatasetPage(d.id)" - :organization-url="getOrganizationPage(d.organization.id)" + :organization-url="getOrganizationPage(d.organization?.id)" /> From acbf7dc0de18f985c0ba6c7ad106bd3053be507c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bult=C3=A9?= Date: Thu, 6 Jun 2024 15:47:43 +0200 Subject: [PATCH 02/17] feat(bouquet): revamp bouquet card --- configs/ecospheres/config.yaml | 1 + .../ecospheres/components/BouquetCard.vue | 119 ++++++++++++------ .../ecospheres/components/BouquetList.vue | 16 +-- .../views/bouquets/BouquetDetailView.vue | 2 +- src/icons.js | 4 +- 5 files changed, 96 insertions(+), 46 deletions(-) diff --git a/configs/ecospheres/config.yaml b/configs/ecospheres/config.yaml index 39bd49316..d618ec84f 100644 --- a/configs/ecospheres/config.yaml +++ b/configs/ecospheres/config.yaml @@ -135,6 +135,7 @@ themes: - name: Aménagements des villes - name: Produire color: 1E929E + textColor: FFFFFF subthemes: - name: Nucléaire - name: Tertiaire (incluant les bâtiments publics de l'État et des collectivités, hors logement) diff --git a/src/custom/ecospheres/components/BouquetCard.vue b/src/custom/ecospheres/components/BouquetCard.vue index 08aaaef73..7ce98fed8 100644 --- a/src/custom/ecospheres/components/BouquetCard.vue +++ b/src/custom/ecospheres/components/BouquetCard.vue @@ -1,9 +1,18 @@ - + diff --git a/src/custom/ecospheres/components/BouquetList.vue b/src/custom/ecospheres/components/BouquetList.vue index 35b2877f0..427b35d1c 100644 --- a/src/custom/ecospheres/components/BouquetList.vue +++ b/src/custom/ecospheres/components/BouquetList.vue @@ -102,7 +102,7 @@ onMounted(() => { - +
+ +
, default: null + }, + query: { + type: String, + default: '' } }) const bouquets: ComputedRef = computed(() => { - const allTopics = topicStore.sorted + return topicStore.sorted .filter((bouquet) => { return !props.showDrafts ? !bouquet.private : true }) @@ -45,27 +49,18 @@ const bouquets: ComputedRef = computed(() => { bouquet.spatial.zones.includes(props.geozone) ) }) - if (props.themeName === NoOptionSelected) { - return allTopics - } - const relevantTopics: Topic[] = [] - if (props.subthemeName !== NoOptionSelected) { - for (const topic of allTopics) { - if ( - isRelevant(topic, 'subtheme', props.subthemeName) && - isRelevant(topic, 'theme', props.themeName) - ) { - relevantTopics.push(topic) - } - } - } else if (props.themeName !== NoOptionSelected) { - for (const topic of allTopics) { - if (isRelevant(topic, 'theme', props.themeName)) { - relevantTopics.push(topic) - } - } - } - return relevantTopics + .filter((bouquet) => { + if (props.themeName === NoOptionSelected) return true + return isRelevant(bouquet, 'theme', props.themeName) + }) + .filter((bouquet) => { + if (props.subthemeName === NoOptionSelected) return true + return isRelevant(bouquet, 'subtheme', props.subthemeName) + }) + .filter((bouquet) => { + if (props.query === '') return true + return bouquet.name.toLowerCase().includes(props.query.toLowerCase()) + }) }) const numberOfResultMsg: ComputedRef = computed(() => { @@ -93,6 +88,12 @@ const goToCreate = () => { router.push({ name: 'bouquet_add', query: route.query }) } +const clearFilters = () => { + const query: LocationQueryRaw = {} + if (route.query.drafts) query.drafts = route.query.drafts + router.push({ name: 'bouquets', hash: '#main', query }) +} + onMounted(() => { const loader = useLoading().show() topicStore.loadTopicsForUniverse().then(() => loader.hide()) @@ -123,14 +124,42 @@ onMounted(() => {
-

Il n'y a pas encore de bouquet sur ce thème

-

- N'hésitez pas à contribuer en - en créant un -

+
+
+ +
+
+
+

+ Aucun résultat ne correspond à votre recherche +

+

+ Essayez de réinitialiser les filtres pour agrandir votre champ de + recherche.
+ Vous pouvez aussi contribuer en créant un bouquet. +

+
+
+ + +
+
+
diff --git a/src/custom/ecospheres/components/BouquetSearch.vue b/src/custom/ecospheres/components/BouquetSearch.vue index db130e206..b03f927c6 100644 --- a/src/custom/ecospheres/components/BouquetSearch.vue +++ b/src/custom/ecospheres/components/BouquetSearch.vue @@ -1,6 +1,6 @@ @@ -93,7 +114,7 @@ watchEffect(() => {
diff --git a/src/custom/ecospheres/routes.ts b/src/custom/ecospheres/routes.ts index 168d96ce5..e3266bc59 100644 --- a/src/custom/ecospheres/routes.ts +++ b/src/custom/ecospheres/routes.ts @@ -15,7 +15,14 @@ export const routes = [ component: async () => await import( '@/custom/ecospheres/views/bouquets/BouquetsListView.vue' - ) + ), + props: (route: RouteLocationNormalizedLoaded) => ({ + query: route.query.q, + subtheme: route.query.subtheme, + theme: route.query.theme, + geozone: route.query.geozone, + drafts: route.query.drafts + }) }, { path: ':bid', diff --git a/src/custom/ecospheres/views/bouquets/BouquetsListView.vue b/src/custom/ecospheres/views/bouquets/BouquetsListView.vue index 9e3a08d7b..142bd8147 100644 --- a/src/custom/ecospheres/views/bouquets/BouquetsListView.vue +++ b/src/custom/ecospheres/views/bouquets/BouquetsListView.vue @@ -1,5 +1,5 @@