@paris-ias/list 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@paris-ias/list",
3
3
  "configKey": "list",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
@@ -23,17 +23,20 @@
23
23
 
24
24
  <v-col align-self="start" class="pl-md-4">
25
25
  <v-skeleton-loader v-if="loading" type="chip" class="mr-3" width="120" />
26
- <v-chip
27
- v-else
28
- class="mr-3"
29
- color="black"
30
- size="small"
31
- style="background-color: white; color: black"
32
- tile
33
- variant="outlined"
34
- >
35
- {{ $t("list.filters.events.category." + item.category) }}
36
- </v-chip>
26
+ <span v-else>
27
+ <v-chip
28
+ class="mr-3"
29
+ color="black"
30
+ size="small"
31
+ style="background-color: white; color: black"
32
+ tile
33
+ variant="outlined"
34
+ >
35
+ {{ $t("list.filters.events.category." + item.category) }}
36
+ </v-chip>
37
+ <!-- DISCIPLINES -->
38
+ <MiscMoleculesDisciplinesTags :disciplines="item.disciplines" inline />
39
+ </span>
37
40
  <v-skeleton-loader
38
41
  v-if="loading && smAndDown"
39
42
  type="text"
@@ -2,7 +2,7 @@
2
2
  <v-row>
3
3
  <template v-for="(filterItem, index) in Object.keys($stores[type].filters)">
4
4
  <v-col
5
- v-if="computeVisibility(filterItem)"
5
+ v-if="appAllowed(filterItem) && computeVisibility(filterItem)"
6
6
  :key="type + index + filterItem"
7
7
  cols="12"
8
8
  sm="6"
@@ -44,7 +44,7 @@
44
44
  <script setup>
45
45
  import { useDisplay } from "vuetify"
46
46
  import { capitalize } from "../../../composables/useUtils"
47
- import { useNuxtApp, resolveComponent, useI18n } from "#imports"
47
+ import { useNuxtApp, resolveComponent, useI18n, useAppConfig } from "#imports"
48
48
 
49
49
  const { smAndDown } = useDisplay()
50
50
  const i18n = useI18n()
@@ -52,6 +52,18 @@ const { locale, messages } = useI18n()
52
52
  const { $stores, $filters } = useNuxtApp()
53
53
  const props = defineProps(["type", "expanded"])
54
54
 
55
+ // Consuming app id. Filters may declare an `appId` array of the consumers
56
+ // allowed to render them; this is the id we match against. "all" is a wildcard.
57
+ const appId = useAppConfig().list?.appId ?? "iea"
58
+
59
+ // A filter is shown only on the consumers it opts into. No appId -> shown
60
+ // everywhere (backward compatible). "all" in the list matches any consumer.
61
+ const appAllowed = (filterKey) => {
62
+ const allowed = $stores[props.type].filters[filterKey].appId
63
+ if (!Array.isArray(allowed) || allowed.length === 0) return true
64
+ return allowed.includes("all") || allowed.includes(appId)
65
+ }
66
+
55
67
  const ComponentName = (name) => {
56
68
  return resolveComponent(
57
69
  "ListInputs" + capitalize($stores[props.type].filters[name].type),
@@ -76,6 +88,19 @@ const getItems = (name) => {
76
88
  .sort((a, b) => a.title.localeCompare(b.title))
77
89
  }
78
90
 
91
+ // Prefer the enum declared on the model filter (filters[name].items) over the
92
+ // values baked into filters.json. The model is the source of truth for enum
93
+ // options (e.g. publicationType), so filters.json never has to stay in sync.
94
+ const modelItems = $stores[props.type].filters[name].items
95
+ if (modelItems && typeof modelItems === "object") {
96
+ return Object.values(modelItems)
97
+ .filter((item) => item !== "label")
98
+ .map((item) => ({
99
+ title: i18n.t(`list.filters.${props.type}.${name}.${item}`),
100
+ value: item,
101
+ }))
102
+ }
103
+
79
104
  if ($filters?.[props.type]?.[name]) {
80
105
  return $filters[props.type][name]
81
106
  .filter((key) => key !== "label")
@@ -140,6 +165,16 @@ const computeVisibility = (filterKey) => {
140
165
 
141
166
  const checkRule = (rule) =>
142
167
  Object.entries(rule).every(([depKey, expected]) => {
168
+ // Reserved key: match against the active view modifier rather than a
169
+ // sibling filter's value. On routes like /resources/media the `type` is
170
+ // narrowed server-side via the modifier, so the modifier is what changes.
171
+ if (depKey === "modifier") {
172
+ const cur = $stores[props.type].modifier
173
+ return Array.isArray(expected)
174
+ ? expected.includes(cur)
175
+ : cur === expected
176
+ }
177
+
143
178
  const dep = filters?.[depKey]
144
179
  if (!dep) return false
145
180
  const cur = dep.value
@@ -117,6 +117,10 @@ const props = defineProps({
117
117
  /* console.log("start llocal loading from setup") */
118
118
  rootStore.setLoading(true, props.type)
119
119
 
120
+ // Mirror the route's fixed modifier into the store so the filter UI can branch
121
+ // its conditional visibility on it (the query still reads props.modifier directly).
122
+ rootStore.setModifier(props.type, props.modifier)
123
+
120
124
  // Initial route -> store (single source-of-truth on first load)
121
125
  rootStore.loadRouteQuery(props.type)
122
126
 
@@ -6,8 +6,11 @@
6
6
  />
7
7
  <div
8
8
  v-else-if="disciplines.length"
9
- class="d-flex flex-wrap"
10
- :class="justify === 'center' ? 'justify-center' : ''"
9
+ class="flex-wrap"
10
+ :class="[
11
+ inline ? 'd-inline-flex align-center' : 'd-flex',
12
+ justify === 'center' ? 'justify-center' : '',
13
+ ]"
11
14
  style="gap: 6px"
12
15
  >
13
16
  <v-chip
@@ -59,6 +62,13 @@ const props = defineProps({
59
62
  type: String,
60
63
  default: "start",
61
64
  },
65
+ // render as inline-flex so the chips flow on the same line as preceding
66
+ // content (e.g. the category chip in the events dense item) instead of
67
+ // forcing a block-level line break
68
+ inline: {
69
+ type: Boolean,
70
+ default: false,
71
+ },
62
72
  })
63
73
 
64
74
  // normalise to an array regardless of what the caller passes
@@ -41,6 +41,12 @@
41
41
  {{ $t(eventCategory) }}
42
42
  </v-chip>
43
43
  <MiscMoleculesChipContainer :items="item.tags || []" size="small" />
44
+ <MiscMoleculesDisciplinesTags
45
+ v-if="item.disciplines && item.disciplines.length"
46
+ :disciplines="item.disciplines"
47
+ inline
48
+ class="mt-2"
49
+ />
44
50
  </template>
45
51
  <div
46
52
  v-html="
@@ -46,11 +46,17 @@
46
46
  :items="item.tags || []"
47
47
  size="small"
48
48
  />
49
+ <MiscMoleculesDisciplinesTags
50
+ v-if="item.disciplines && item.disciplines.length"
51
+ :disciplines="item.disciplines"
52
+ inline
53
+ class="mt-2"
54
+ />
49
55
  </template>
50
56
  <v-skeleton-loader v-if="loading" type="heading" />
51
- <span
57
+ <div
52
58
  v-else
53
- class="text-h5 dense paragraph"
59
+ class="text-h5 dense paragraph mt-2"
54
60
  v-html="
55
61
  searchQuery.length
56
62
  ? highlightAndTruncate(300, item.name, searchQuery.split(' '))
@@ -37,6 +37,7 @@ export declare const useRootStore: import("pinia").StoreDefinition<"rootStore",
37
37
  loadRouteQuery(type: string): void;
38
38
  setFiltersCount(type: string): void;
39
39
  updateRouteQuery(type: string): void;
40
+ setModifier(type: string, modifier?: string): void;
40
41
  resetState(type: string, lang?: string): void;
41
42
  updateSort({ type, sortKey }: {
42
43
  type: string;
@@ -113,12 +113,19 @@ export const useRootStore = defineStore("rootStore", {
113
113
  };
114
114
  router.replace({ query: routeQuery });
115
115
  },
116
+ setModifier(type, modifier) {
117
+ const { $stores } = useNuxtApp();
118
+ if ($stores[type]) {
119
+ $stores[type].modifier = modifier;
120
+ }
121
+ },
116
122
  resetState(type, lang = "en") {
117
123
  const { $stores, $models } = useNuxtApp();
118
124
  const model = structuredClone($models[type]);
119
125
  $stores[type].filters = model?.filters;
120
126
  $stores[type].search = "";
121
127
  $stores[type].page = 1;
128
+ $stores[type].modifier = void 0;
122
129
  $stores[type].sortKey = null;
123
130
  },
124
131
  updateSort({ type, sortKey }) {
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "license": "AGPL-3.0-only",
3
3
  "main": "./dist/module.mjs",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "name": "@paris-ias/list",
6
6
  "repository": {
7
7
  "url": "git+https://github.com/IEA-Paris/list.git",
8
8
  "type": "git"
9
9
  },
10
10
  "dependencies": {
11
- "@paris-ias/trees": "^2.2.17"
11
+ "@paris-ias/trees": "^2.2.18"
12
12
  },
13
13
  "description": "Paris IAS List Module",
14
14
  "peerDependencies": {