@shopware/cms-base-layer 1.4.0 → 1.5.0

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # shopware/frontends - cms-base
2
2
 
3
3
  [![](https://img.shields.io/npm/v/@shopware/cms-base-layer?color=blue&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTIiIHZpZXdCb3g9IjAgMCA0ODggNTUzIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNDM5LjA0MSAxMjkuNTkzTDI1OC43NjkgMzEuMzA3NkMyNDQuOTE1IDIzLjc1NDEgMjI4LjExNiAyNC4wMDkzIDIxNC40OTcgMzEuOTgwMkw0Ny4yNjkgMTI5Ljg1OEMzMy40NzYzIDEzNy45MzEgMjUgMTUyLjcxMyAyNSAxNjguNjk1VjM4OC40NjZDMjUgNDA0LjczMiAzMy43Nzg1IDQxOS43MzIgNDcuOTYwMiA0MjcuNjk5TDIxNS4xNzggNTIxLjYzNkMyMjguNDUxIDUyOS4wOTIgMjQ0LjU5MyA1MjkuMzMyIDI1OC4wODIgNTIyLjI3NEw0MzguMzY0IDQyNy45MzRDNDUzLjIwMSA0MjAuMTcgNDYyLjUgNDA0LjgwOSA0NjIuNSAzODguMDYzVjE2OS4xMDJDNDYyLjUgMTUyLjYzMiA0NTMuNTAyIDEzNy40NzcgNDM5LjA0MSAxMjkuNTkzWiIgc3Ryb2tlPSJ1cmwoI3BhaW50MF9saW5lYXJfMTUzXzY5MjY1KSIgc3Ryb2tlLXdpZHRoPSI1MCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzE1M182OTI2NSIgeDE9Ii0xNi4yOTg5IiB5MT0iMTY1LjM0OSIgeDI9IjI3Ni40MTIiIHkyPSItODkuMzIzNCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjMDA4NUZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0MwRTJGNSIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==)](https://npmjs.com/package/@shopware/cms-base-layer)
4
- [![](https://img.shields.io/github/package-json/v/shopware/frontends?color=blue&filename=packages%2Fcms-base%2Fpackage.json&label=cms-base%40monorepo&logo=github)](https://github.com/shopware/frontends/tree/main/packages/cms-base)
4
+ [![](https://img.shields.io/github/package-json/v/shopware/frontends?color=blue&filename=packages%2Fcms-base-layer%2Fpackage.json&label=cms-base%40monorepo&logo=github)](https://github.com/shopware/frontends/tree/main/packages/cms-base-layer)
5
5
  [![](https://img.shields.io/github/issues/shopware/frontends/cms-base?label=cms-base%20issues&logo=github)](https://github.com/shopware/frontends/issues?q=is%3Aopen+is%3Aissue+label%3Acms-base)
6
6
  [![](https://img.shields.io/github/license/shopware/frontends?color=blue)](#)
7
7
 
@@ -36,6 +36,9 @@ pnpm install -D @shopware/cms-base-layer
36
36
 
37
37
  # bun
38
38
  bun install -D @shopware/cms-base-layer
39
+
40
+ # deno
41
+ deno install --dev @shopware/cms-base-layer
39
42
  ```
40
43
 
41
44
  <!-- /automd -->
@@ -129,16 +132,21 @@ No additional packages needed to be installed.
129
132
 
130
133
  Full changelog for stable version is available [here](https://github.com/shopware/frontends/blob/main/packages/cms-base-layer/CHANGELOG.md)
131
134
 
132
- ### Latest changes: 1.4.0
135
+ ### Latest changes: 1.5.0
133
136
 
134
137
  ### Minor Changes
135
138
 
136
- - [#1602](https://github.com/shopware/frontends/pull/1602) [`bb7d1cb`](https://github.com/shopware/frontends/commit/bb7d1cbc4204ff1d48f77416f94f550bc235e5ed) Thanks [@patzick](https://github.com/patzick)! - Switch from `@shopware-pwa/helpers-next` to `@shopware/helpers` package.
137
-
138
- - [#1602](https://github.com/shopware/frontends/pull/1602) [`bb7d1cb`](https://github.com/shopware/frontends/commit/bb7d1cbc4204ff1d48f77416f94f550bc235e5ed) Thanks [@patzick](https://github.com/patzick)! - Switch from `@shopware-pwa/cms-base` to `@shopware/cms-base-layer` package.
139
+ - [#1727](https://github.com/shopware/frontends/pull/1727) [`94872b7`](https://github.com/shopware/frontends/commit/94872b7c6f6337ff8ce0bcfd9320e4178a4927f0) Thanks [@mdanilowicz](https://github.com/mdanilowicz)! - Added CmsBlockHtml to render html blocks.
140
+ Added CmsElementHtml to render html element.
139
141
 
140
142
  ### Patch Changes
141
143
 
142
- - Updated dependencies [[`bb7d1cb`](https://github.com/shopware/frontends/commit/bb7d1cbc4204ff1d48f77416f94f550bc235e5ed), [`bb7d1cb`](https://github.com/shopware/frontends/commit/bb7d1cbc4204ff1d48f77416f94f550bc235e5ed)]:
143
- - @shopware/composables@1.8.0
144
- - @shopware/helpers@1.4.0
144
+ - [#1843](https://github.com/shopware/frontends/pull/1843) [`1859893`](https://github.com/shopware/frontends/commit/1859893ec3fe1cdead4b1c39e34943d9a70deaa4) Thanks [@mdanilowicz](https://github.com/mdanilowicz)! - Enhance form error handling and fix TS errors
145
+
146
+ - [#1812](https://github.com/shopware/frontends/pull/1812) [`c28810d`](https://github.com/shopware/frontends/commit/c28810d0ca503b97c232438e200bbf5ba5dab403) Thanks [@patzick](https://github.com/patzick)! - Fix date formatting based on locale, previously always returned en-US format
147
+
148
+ - [#1857](https://github.com/shopware/frontends/pull/1857) [`e78d51e`](https://github.com/shopware/frontends/commit/e78d51e6af0726b12620d9f7e8f2c3150aa80cfa) Thanks [@mdanilowicz](https://github.com/mdanilowicz)! - Fix wrong `SharedPrice` component in `SwListingProductPrice.vue` file
149
+
150
+ - Updated dependencies [[`d016d6b`](https://github.com/shopware/frontends/commit/d016d6b845bff9a148405a74dae88d7fc81ec99c), [`c28810d`](https://github.com/shopware/frontends/commit/c28810d0ca503b97c232438e200bbf5ba5dab403), [`a7ff606`](https://github.com/shopware/frontends/commit/a7ff60681d1a164d5c9f2020c506262e96fad5dc), [`d016d6b`](https://github.com/shopware/frontends/commit/d016d6b845bff9a148405a74dae88d7fc81ec99c), [`bd70905`](https://github.com/shopware/frontends/commit/bd70905b8443fd57d8d8cb3cfc6501a9117dea49)]:
151
+ - @shopware/api-client@1.3.0
152
+ - @shopware/composables@1.9.0
@@ -115,9 +115,6 @@ const rules = computed(() => ({
115
115
  required,
116
116
  minLength: minLength(3),
117
117
  },
118
- salutationId: {
119
- required,
120
- },
121
118
  phone: {
122
119
  required,
123
120
  minLength: minLength(3),
@@ -176,18 +173,12 @@ const invokeSubmit = async () => {
176
173
  <template v-if="!formSent">
177
174
  <div class="grid grid-cols-12 gap-5">
178
175
  <div class="col-span-4">
179
- <label for="salutation">{{ translations.form.salutation }} *</label>
176
+ <label for="salutation">{{ translations.form.salutation }}</label>
180
177
  <select
181
178
  id="salutation"
182
179
  v-model="state.salutationId"
183
180
  name="salutation"
184
- class="appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-indigo-500 focus:z-10 sm:text-sm"
185
- :class="[
186
- $v.salutationId.$error
187
- ? 'border-red-600 focus:border-red-600'
188
- : 'border-gray-300 focus:border-indigo-500',
189
- ]"
190
- @blur="$v.salutationId.$touch()"
181
+ class="border-gray-300 focus:border-indigo-500 appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-indigo-500 focus:z-10 sm:text-sm"
191
182
  >
192
183
  <option disabled selected value="">
193
184
  {{ translations.form.salutationPlaceholder }}
@@ -200,12 +191,6 @@ const invokeSubmit = async () => {
200
191
  {{ salutation.displayName }}
201
192
  </option>
202
193
  </select>
203
- <span
204
- v-if="$v.salutationId.$error"
205
- class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
206
- >
207
- {{ $v.salutationId.$errors[0].$message }}
208
- </span>
209
194
  </div>
210
195
  <div class="col-span-4">
211
196
  <label for="first-name">{{ translations.form.firstName }} *</label>
@@ -228,7 +213,7 @@ const invokeSubmit = async () => {
228
213
  v-if="$v.firstName.$error"
229
214
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
230
215
  >
231
- {{ $v.firstName.$errors[0].$message }}
216
+ {{ $v.firstName.$errors[0]?.$message ?? '' }}
232
217
  </span>
233
218
  </div>
234
219
  <div class="col-span-4">
@@ -252,7 +237,7 @@ const invokeSubmit = async () => {
252
237
  v-if="$v.lastName.$error"
253
238
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
254
239
  >
255
- {{ $v.lastName.$errors[0].$message }}
240
+ {{ $v.lastName.$errors[0]?.$message ?? '' }}
256
241
  </span>
257
242
  </div>
258
243
  <div class="col-span-6">
@@ -276,7 +261,7 @@ const invokeSubmit = async () => {
276
261
  v-if="$v.email.$error"
277
262
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
278
263
  >
279
- {{ $v.email.$errors[0].$message }}
264
+ {{ $v.email.$errors[0]?.$message ?? '' }}
280
265
  </span>
281
266
  </div>
282
267
  <div class="col-span-6">
@@ -300,7 +285,7 @@ const invokeSubmit = async () => {
300
285
  v-if="$v.phone.$error"
301
286
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
302
287
  >
303
- {{ $v.phone.$errors[0].$message }}
288
+ {{ $v.phone.$errors[0]?.$message ?? '' }}
304
289
  </span>
305
290
  </div>
306
291
  <div class="col-span-12">
@@ -324,7 +309,7 @@ const invokeSubmit = async () => {
324
309
  v-if="$v.subject.$error"
325
310
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
326
311
  >
327
- {{ $v.subject.$errors[0].$message }}
312
+ {{ $v.subject.$errors[0]?.$message ?? '' }}
328
313
  </span>
329
314
  </div>
330
315
  <div class="col-span-12">
@@ -349,7 +334,7 @@ const invokeSubmit = async () => {
349
334
  v-if="$v.comment.$error"
350
335
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
351
336
  >
352
- {{ $v.comment.$errors[0].$message }}
337
+ {{ $v.comment.$errors[0]?.$message || '' }}
353
338
  </span>
354
339
  </div>
355
340
  <div class="col-span-12">
@@ -12,6 +12,7 @@ type Translations = {
12
12
  listing: {
13
13
  variantsFrom: string;
14
14
  previously: string;
15
+ from: string;
15
16
  to: string;
16
17
  };
17
18
  };
@@ -78,7 +79,7 @@ const {
78
79
  <template v-if="regulationPrice">
79
80
  <div class="flex gap-2 justify-end text-gray-500 text-3.5 mb-2">
80
81
  {{ translations.listing.previously }}
81
- <SharedPrice :value="regulationPrice" />
82
+ <SwSharedPrice :value="regulationPrice" />
82
83
  </div>
83
84
  </template>
84
85
  <template v-if="!regulationPrice">
@@ -79,7 +79,7 @@ const { newsletterSubscribe, newsletterUnsubscribe } = useNewsletter();
79
79
 
80
80
  const getFormTitle = computed(() => getConfigValue("title"));
81
81
  const state = reactive({
82
- option: subscriptionOptions[0].value,
82
+ option: subscriptionOptions[0]?.value ?? "",
83
83
  salutationId: "",
84
84
  firstName: "",
85
85
  lastName: "",
@@ -104,9 +104,6 @@ type Rules = {
104
104
  required: ValidationRuleWithoutParams;
105
105
  minLength: number;
106
106
  };
107
- salutationId: {
108
- required: ValidationRuleWithoutParams;
109
- };
110
107
  };
111
108
  const rules = computed(() => {
112
109
  let temp: Partial<Rules> = {
@@ -130,9 +127,6 @@ const rules = computed(() => {
130
127
  required,
131
128
  minLength: 3,
132
129
  },
133
- salutationId: {
134
- required,
135
- },
136
130
  };
137
131
  }
138
132
  return temp;
@@ -222,7 +216,7 @@ const invokeSubmit = async () => {
222
216
  v-if="$v.email?.$error"
223
217
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
224
218
  >
225
- {{ $v.email?.$errors[0].$message }}
219
+ {{ $v.email?.$errors[0]?.$message || '' }}
226
220
  </span>
227
221
  </div>
228
222
  <div v-if="state.option === 'subscribe'" class="col-span-4">
@@ -231,13 +225,7 @@ const invokeSubmit = async () => {
231
225
  id="salutation"
232
226
  v-model="state.salutationId"
233
227
  name="salutation"
234
- class="appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-indigo-500 focus:z-10 sm:text-sm"
235
- :class="[
236
- $v.salutationId?.$error
237
- ? 'border-red-600 focus:border-red-600'
238
- : 'border-gray-300 focus:border-indigo-500',
239
- ]"
240
- @blur="$v.salutationId?.$touch()"
228
+ class=" border-gray-300 focus:border-indigo-500appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-indigo-500 focus:z-10 sm:text-sm"
241
229
  >
242
230
  <option disabled selected value="">
243
231
  {{ translations.form.salutationPlaceholder }}
@@ -250,12 +238,6 @@ const invokeSubmit = async () => {
250
238
  {{ salutation.displayName }}
251
239
  </option>
252
240
  </select>
253
- <span
254
- v-if="$v.salutationId?.$error"
255
- class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
256
- >
257
- {{ $v.salutationId?.$errors[0].$message }}
258
- </span>
259
241
  </div>
260
242
  <div v-if="state.option === 'subscribe'" class="col-span-4">
261
243
  <label for="first-name">{{ translations.form.firstName }} *</label>
@@ -278,7 +260,7 @@ const invokeSubmit = async () => {
278
260
  v-if="$v.firstName?.$error"
279
261
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
280
262
  >
281
- {{ $v.firstName?.$errors[0].$message }}
263
+ {{ $v.firstName?.$errors[0]?.$message || '' }}
282
264
  </span>
283
265
  </div>
284
266
  <div v-if="state.option === 'subscribe'" class="col-span-4">
@@ -302,7 +284,7 @@ const invokeSubmit = async () => {
302
284
  v-if="$v.lastName?.$error"
303
285
  class="pt-1 text-sm text-red-600 focus:ring-brand-primary border-gray-300"
304
286
  >
305
- {{ $v.lastName?.$errors[0].$message }}
287
+ {{ $v.lastName?.$errors[0]?.$message || '' }}
306
288
  </span>
307
289
  </div>
308
290
  <div class="col-span-12">
@@ -51,7 +51,8 @@ const addToCartProxy = async () => {
51
51
  const errors = getErrorsCodes();
52
52
  for (const element of errors) {
53
53
  const { messageKey, params } = resolveCartError(element);
54
- pushError(getCmsTranslate(translations.errors[messageKey], params));
54
+ if (translations.errors[messageKey])
55
+ pushError(getCmsTranslate(translations.errors[messageKey], params));
55
56
  }
56
57
 
57
58
  if (!errors.length)
@@ -127,7 +127,8 @@ const addToCartProxy = async () => {
127
127
  const errors = getErrorsCodes();
128
128
  for (const element of errors) {
129
129
  const { messageKey, params } = resolveCartError(element);
130
- pushError(getCmsTranslate(translations.errors[messageKey], params));
130
+ if (translations.errors[messageKey])
131
+ pushError(getCmsTranslate(translations.errors[messageKey], params));
131
132
  }
132
133
 
133
134
  if (!errors.length)
@@ -235,11 +236,11 @@ const srcPath = computed(() => {
235
236
  :to="buildUrlPrefix(getProductRoute(product), getUrlPrefix())"
236
237
  data-testid="product-box-product-name-link"
237
238
  >
238
- <h5
239
+ <div
239
240
  class="text-xl font-semibold tracking-tight text-gray-900 dark:text-white min-h-60px"
240
241
  >
241
242
  {{ getProductName({ product }) }}
242
- </h5>
243
+ </div>
243
244
  </RouterLink>
244
245
 
245
246
  <SwListingProductPrice
@@ -1,7 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { defu } from "defu";
3
3
  import { computed, onMounted, ref, toRefs } from "vue";
4
- import { useCmsTranslations, useProductReviews } from "#imports";
4
+ import {
5
+ useCmsTranslations,
6
+ useProductReviews,
7
+ useShopwareContext,
8
+ } from "#imports";
5
9
  import type { Schemas } from "#shopware";
6
10
 
7
11
  const props = defineProps<{
@@ -12,12 +16,14 @@ const props = defineProps<{
12
16
  type Translations = {
13
17
  product: {
14
18
  noReviews: string;
19
+ reviewNotAccepted: string;
15
20
  };
16
21
  };
17
22
 
18
23
  let translations: Translations = {
19
24
  product: {
20
25
  noReviews: "No reviews yet.",
26
+ reviewNotAccepted: "Your review has not been approved yet",
21
27
  },
22
28
  };
23
29
 
@@ -42,15 +48,17 @@ const reviewsList = computed<Schemas["ProductReview"][]>(
42
48
 
43
49
  const format: Intl.DateTimeFormatOptions = {
44
50
  year: "numeric",
45
- month: "short",
51
+ month: "numeric",
46
52
  day: "numeric",
47
53
  hour: "numeric",
48
54
  minute: "numeric",
49
- hour12: true,
50
55
  };
51
56
 
52
- const formatDate = (date: string) =>
53
- new Date(date).toLocaleDateString("en-us", format);
57
+ const { browserLocale } = useShopwareContext();
58
+
59
+ const formatDate = (date: string) => {
60
+ return new Intl.DateTimeFormat(browserLocale, format).format(new Date(date));
61
+ };
54
62
  </script>
55
63
 
56
64
  <template>
@@ -70,6 +78,13 @@ const formatDate = (date: string) =>
70
78
  >
71
79
  <span>{{ formatDate(review.createdAt) }}</span>
72
80
  </div>
81
+ <div
82
+ v-if="!review.status"
83
+ class="mt-2 text-3 p-2 bg-[#d4f0f5] flex gap-2 items-center"
84
+ >
85
+ <div class="w-6 h-6 i-carbon-warning" />
86
+ {{ translations.product.reviewNotAccepted }}
87
+ </div>
73
88
  <div
74
89
  class="cms-block-product-description-reviews__reviews-rating inline-flex items-center mt-2"
75
90
  >
@@ -38,9 +38,11 @@ const { getConfigValue } = useCmsElementConfig({
38
38
  config: SliderElementConfig;
39
39
  });
40
40
 
41
- const slots = useSlots();
41
+ const slots = useSlots() as {
42
+ default?: () => { children: VNodeArrayChildren }[];
43
+ };
42
44
  const childrenRaw = computed(
43
- () => (slots?.default?.()[0].children as VNodeArrayChildren) ?? [],
45
+ () => (slots?.default?.()[0]?.children as VNodeArrayChildren) ?? [],
44
46
  );
45
47
  const slidesToScroll = computed(() =>
46
48
  props.slidesToScroll >= props.slidesToShow
@@ -184,7 +186,7 @@ function buildImageSliderTrackStyle(
184
186
  const childComponent =
185
187
  imageSliderTrack.value?.children[transformIndex + 1];
186
188
  // If image exist
187
- height = childComponent?.children[0].children[0].clientHeight
189
+ height = childComponent?.children[0]?.children[0]?.clientHeight
188
190
  ? `${childComponent.clientHeight}px`
189
191
  : "auto";
190
192
  }
@@ -1,13 +1,17 @@
1
1
  <script setup lang="ts">
2
2
  import { useCmsTranslations } from "@shopware/composables";
3
- import { getProductRoute } from "@shopware/helpers";
3
+ import { buildUrlPrefix, getProductRoute } from "@shopware/helpers";
4
4
  import { defu } from "defu";
5
5
  import { computed, ref, unref } from "vue";
6
6
  import type { ComputedRef } from "vue";
7
7
  import { useRouter } from "vue-router";
8
- import { useProductConfigurator } from "#imports";
8
+ import { useProductConfigurator, useUrlResolver } from "#imports";
9
9
  import type { Schemas } from "#shopware";
10
10
 
11
+ const { getUrlPrefix } = useUrlResolver();
12
+
13
+ const prefix = getUrlPrefix();
14
+
11
15
  const props = withDefaults(
12
16
  defineProps<{
13
17
  allowRedirect?: boolean;
@@ -52,11 +56,11 @@ const isOptionSelected = (optionId: string) =>
52
56
 
53
57
  const onHandleChange = async () => {
54
58
  isLoading.value = true;
55
- const variantFound = await findVariantForSelectedOptions(
56
- unref(selectedOptions),
59
+ const variantFound = await findVariantForSelectedOptions();
60
+ const selectedOptionsVariantPath = buildUrlPrefix(
61
+ getProductRoute(variantFound),
62
+ prefix,
57
63
  );
58
-
59
- const selectedOptionsVariantPath = getProductRoute(variantFound);
60
64
  if (props.allowRedirect && selectedOptionsVariantPath) {
61
65
  try {
62
66
  router.push(selectedOptionsVariantPath);
@@ -100,13 +104,13 @@ const onHandleChange = async () => {
100
104
  :class="{
101
105
  'border-3 border-indigo-600': isOptionSelected(option.id),
102
106
  }"
103
- @click="handleChange(optionGroup.name, option.id, onHandleChange)"
107
+ @click="handleChange(optionGroup.translated.name, option.id, onHandleChange)"
104
108
  >
105
109
  <p
106
110
  :id="`${option.id}-choice-label`"
107
111
  data-testid="product-variant-text"
108
112
  >
109
- {{ option.name }}
113
+ {{ option.translated.name }}
110
114
  </p>
111
115
  </label>
112
116
  </div>
@@ -0,0 +1 @@
1
+ Render a HTML section
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ import type { CmsBlockHtml } from "@shopware/composables";
3
+
4
+ defineProps<{
5
+ content: CmsBlockHtml;
6
+ }>();
7
+ </script>
8
+
9
+ <template>
10
+ <div>
11
+ <CmsGenericElement
12
+ v-for="slot in content.slots"
13
+ :key="slot.versionId"
14
+ :content="slot"
15
+ />
16
+ </div>
17
+ </template>
@@ -82,7 +82,7 @@ const toggleTab = (index: number) => {
82
82
  :autoplay="false"
83
83
  >
84
84
  <SwProductCard
85
- v-for="product of crossSellCollections[currentTabIndex].products"
85
+ v-for="product of crossSellCollections[currentTabIndex]?.products"
86
86
  :key="product.id"
87
87
  class="w-[300px]"
88
88
  :product="product"
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import type { CmsElementHtml } from "@shopware/composables";
3
+
4
+ import { getCmsLayoutConfiguration } from "@shopware/helpers";
5
+ import { h } from "vue";
6
+
7
+ const props = defineProps<{
8
+ content: CmsElementHtml;
9
+ }>();
10
+
11
+ const { cssClasses, layoutStyles } = getCmsLayoutConfiguration(props.content);
12
+
13
+ const HtmlComponent = () => {
14
+ return h("div", {
15
+ class: cssClasses,
16
+ style: layoutStyles,
17
+ innerHTML: props.content.data.content || "",
18
+ });
19
+ };
20
+ </script>
21
+
22
+ <template>
23
+ <HtmlComponent />
24
+ </template>
@@ -3,25 +3,32 @@ import type { CmsElementProductDescriptionReviews } from "@shopware/composables"
3
3
  import { useCmsTranslations } from "@shopware/composables";
4
4
  import { getProductName, getTranslatedProperty } from "@shopware/helpers";
5
5
  import { defu } from "defu";
6
- import { computed, ref } from "vue";
6
+ import { type Ref, computed, onMounted, ref } from "vue";
7
7
  import xss from "xss";
8
8
  import { useProduct } from "#imports";
9
+ import type { Schemas } from "#shopware";
9
10
 
10
11
  const props = defineProps<{
11
12
  content: CmsElementProductDescriptionReviews;
12
13
  }>();
13
14
 
14
15
  type Translations = {
15
- products: {
16
+ product: {
16
17
  description: string;
17
18
  reviews: string;
19
+ messages: {
20
+ reviewAdded: string;
21
+ };
18
22
  };
19
23
  };
20
24
 
21
25
  let translations: Translations = {
22
- products: {
26
+ product: {
23
27
  description: "Description",
24
28
  reviews: "Reviews",
29
+ messages: {
30
+ reviewAdded: "Thank you for submitting your review",
31
+ },
25
32
  },
26
33
  };
27
34
  translations = defu(useCmsTranslations(), translations) as Translations;
@@ -37,7 +44,13 @@ const toggleTabs = (tabNumber: number) => {
37
44
  currentTab.value = tabNumber;
38
45
  };
39
46
 
40
- const reviews = computed(() => props.content.data.reviews.elements);
47
+ const reviews: Ref<Schemas["ProductReview"][]> = ref([]);
48
+
49
+ onMounted(async () => {
50
+ if (props.content.data?.reviews?.elements) {
51
+ reviews.value = props.content.data.reviews.elements;
52
+ }
53
+ });
41
54
  </script>
42
55
 
43
56
  <template>
@@ -60,7 +73,7 @@ const reviews = computed(() => props.content.data.reviews.elements);
60
73
  @click="() => toggleTabs(1)"
61
74
  >
62
75
  <i class="fas fa-space-shuttle text-base mr-1" />
63
- {{ translations.products.description }}
76
+ {{ translations.product.description }}
64
77
  </a>
65
78
  </li>
66
79
  <li class="mr-2 text-center">
@@ -71,10 +84,11 @@ const reviews = computed(() => props.content.data.reviews.elements);
71
84
  ? 'text-secondary-500 bg-white'
72
85
  : 'text-white bg-secondary-500',
73
86
  ]"
87
+ data-testid="product-reviews-tab"
74
88
  @click="() => toggleTabs(2)"
75
89
  >
76
90
  <i class="fas fa-cog text-base mr-1" />
77
- {{ translations.products.reviews }}
91
+ {{ translations.product.reviews }} ({{ reviews.length }})
78
92
  </a>
79
93
  </li>
80
94
  </ul>
package/nuxt.config.ts CHANGED
@@ -17,5 +17,7 @@ export default defineNuxtConfig({
17
17
  build: {
18
18
  transpile: ["@shopware/cms-base-layer"],
19
19
  },
20
- telemetry: false,
20
+ telemetry: {
21
+ enabled: false,
22
+ },
21
23
  }) as NuxtConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware/cms-base-layer",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Vue CMS Nuxt Layer for Shopware",
5
5
  "author": "Shopware",
6
6
  "repository": {
@@ -29,32 +29,32 @@
29
29
  "nuxt.config.ts"
30
30
  ],
31
31
  "dependencies": {
32
- "@nuxt/kit": "3.14.1592",
33
- "@tresjs/cientos": "4.0.2",
34
- "@tresjs/core": "4.3.1",
32
+ "@nuxt/kit": "3.16.2",
33
+ "@tresjs/cientos": "4.3.0",
34
+ "@tresjs/core": "4.3.3",
35
35
  "@vuelidate/core": "2.0.3",
36
36
  "@vuelidate/validators": "2.0.4",
37
- "@vueuse/core": "11.2.0",
38
- "entities": "5.0.0",
37
+ "@vueuse/core": "13.1.0",
38
+ "entities": "6.0.0",
39
39
  "html-to-ast": "0.0.6",
40
- "three": "0.166.1",
40
+ "three": "0.173.0",
41
41
  "vue": "3.5.13",
42
42
  "xss": "1.0.15",
43
- "@shopware/composables": "1.8.0",
43
+ "@shopware/composables": "1.9.0",
44
44
  "@shopware/helpers": "1.4.0",
45
- "@shopware/api-client": "1.2.0"
45
+ "@shopware/api-client": "1.3.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@biomejs/biome": "1.8.3",
49
- "@nuxt/schema": "3.14.1592",
50
- "@types/three": "0.166.0",
51
- "@vitest/coverage-v8": "2.1.8",
52
- "nuxt": "3.14.1592",
53
- "typescript": "5.6.3",
49
+ "@nuxt/schema": "3.16.2",
50
+ "@types/three": "0.173.0",
51
+ "@vitest/coverage-v8": "3.1.1",
52
+ "nuxt": "3.16.2",
53
+ "typescript": "5.8.3",
54
54
  "unbuild": "2.0.0",
55
- "vitest": "2.1.8",
55
+ "vitest": "3.1.1",
56
56
  "vue-router": "4.5.0",
57
- "vue-tsc": "2.1.10",
57
+ "vue-tsc": "2.2.8",
58
58
  "tsconfig": "0.0.0"
59
59
  },
60
60
  "scripts": {