@rocketsearch/vue-uappi 0.1.1 → 0.1.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/README.md +3 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/runtime/components/RocketLanding.vue +57 -0
- package/runtime/components/RocketShowcase.vue +8 -2
- package/runtime/rocket.js +11 -7
package/README.md
CHANGED
|
@@ -27,4 +27,7 @@ optimizeDeps: { exclude: ['@rocketsearch/vue-uappi'] }
|
|
|
27
27
|
Use os componentes em PascalCase (`<RocketSearch>`, `<RocketShowcase position="top">`): o tema pode ter
|
|
28
28
|
`isCustomElement` para tags com hífen.
|
|
29
29
|
|
|
30
|
+
Landing page ("Personalizado" no painel): `<RocketLanding>` mostra todas as vitrines da landing, na ordem do
|
|
31
|
+
painel. O identificador vem do nome da rota (`/black-friday` → `black-friday`) ou de `custom-key="..."`.
|
|
32
|
+
|
|
30
33
|
Documentação completa: https://api.rocketsearch.com.br/sdk/uappi/docs.html
|
package/index.js
CHANGED
|
@@ -109,6 +109,7 @@ export default {
|
|
|
109
109
|
app.component('RocketBanner', defineAsyncComponent(() => import('./runtime/components/RocketBanner.vue')));
|
|
110
110
|
app.component('RocketSearch', defineAsyncComponent(() => import('./runtime/components/RocketSearch.vue')));
|
|
111
111
|
app.component('RocketShowcase', defineAsyncComponent(() => import('./runtime/components/RocketShowcase.vue')));
|
|
112
|
+
app.component('RocketLanding', defineAsyncComponent(() => import('./runtime/components/RocketLanding.vue')));
|
|
112
113
|
|
|
113
114
|
// Conexão fria + preflight CORS era o grosso da latência do storefront, não a busca.
|
|
114
115
|
const preconnect = document.createElement('link');
|
package/package.json
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<RocketShowcase
|
|
3
|
+
v-for="showcase in showcases"
|
|
4
|
+
:key="showcase.id"
|
|
5
|
+
page-type="custom"
|
|
6
|
+
:custom-key="key"
|
|
7
|
+
:showcase-id="showcase.id"
|
|
8
|
+
:position="(showcase.placement && showcase.placement.position) || 'middle'"
|
|
9
|
+
:media-size="mediaSize"
|
|
10
|
+
>
|
|
11
|
+
<template v-if="$slots.default" #default="scope">
|
|
12
|
+
<slot v-bind="scope" />
|
|
13
|
+
</template>
|
|
14
|
+
<template v-if="$slots.product" #product="scope">
|
|
15
|
+
<slot name="product" v-bind="scope" />
|
|
16
|
+
</template>
|
|
17
|
+
</RocketShowcase>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
import RocketShowcase from './RocketShowcase.vue';
|
|
22
|
+
|
|
23
|
+
// Landing page ("Personalizado" no painel): todas as vitrines da landing, empilhadas pela ordem
|
|
24
|
+
// do painel (a API já responde por display_order). Sem elemento próprio: as vitrines entram
|
|
25
|
+
// direto no container do tema e herdam o espaçamento dele.
|
|
26
|
+
export default {
|
|
27
|
+
name: 'RocketLanding',
|
|
28
|
+
components: { RocketShowcase },
|
|
29
|
+
inheritAttrs: false,
|
|
30
|
+
props: {
|
|
31
|
+
// Identificador da landing no painel; sem ele, o nome da rota (/black-friday -> black-friday).
|
|
32
|
+
customKey: { type: String, default: '' },
|
|
33
|
+
mediaSize: { type: String, default: 'medium' }
|
|
34
|
+
},
|
|
35
|
+
data () {
|
|
36
|
+
return { showcases: [] };
|
|
37
|
+
},
|
|
38
|
+
computed: {
|
|
39
|
+
key () {
|
|
40
|
+
if (this.customKey) return this.customKey;
|
|
41
|
+
const path = (this.$route && this.$route.path) || location.pathname;
|
|
42
|
+
return path.split('/').filter(Boolean).pop() || '';
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
watch: {
|
|
46
|
+
key: 'load'
|
|
47
|
+
},
|
|
48
|
+
mounted () {
|
|
49
|
+
this.load();
|
|
50
|
+
},
|
|
51
|
+
methods: {
|
|
52
|
+
async load () {
|
|
53
|
+
this.showcases = this.key ? await this.$rocket.getPageShowcases('custom', this.key) : [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
</script>
|
|
@@ -69,6 +69,10 @@ export default {
|
|
|
69
69
|
position: { type: String, required: true },
|
|
70
70
|
// Força o pageType; sem ele vem da página atual (currentPageData do tema).
|
|
71
71
|
pageType: { type: String, default: '' },
|
|
72
|
+
// Landing (page-type="custom"): identificador cadastrado no painel em "Personalizado".
|
|
73
|
+
customKey: { type: String, default: '' },
|
|
74
|
+
// Vitrine específica (a landing tem várias na mesma posição); sem ele, a primeira da posição.
|
|
75
|
+
showcaseId: { type: [String, Number], default: null },
|
|
72
76
|
mediaSize: { type: String, default: 'medium' }
|
|
73
77
|
},
|
|
74
78
|
data () {
|
|
@@ -117,8 +121,10 @@ export default {
|
|
|
117
121
|
if (this.started) return;
|
|
118
122
|
this.started = true;
|
|
119
123
|
try {
|
|
120
|
-
const showcases = await this.$rocket.getPageShowcases(this.pageType || undefined);
|
|
121
|
-
const showcase = showcases.find(s =>
|
|
124
|
+
const showcases = await this.$rocket.getPageShowcases(this.pageType || undefined, this.customKey || undefined);
|
|
125
|
+
const showcase = showcases.find(s => this.showcaseId != null
|
|
126
|
+
? String(s.id) === String(this.showcaseId)
|
|
127
|
+
: ((s.placement && s.placement.position) || s.position) === this.position);
|
|
122
128
|
if (!showcase) return;
|
|
123
129
|
// Banner autônomo: render direto, sem produtos, skeleton nem impressão de vitrine
|
|
124
130
|
// (o RocketBannerItem mede o criativo).
|
package/runtime/rocket.js
CHANGED
|
@@ -122,7 +122,7 @@ export function createRocket (config) {
|
|
|
122
122
|
|
|
123
123
|
rocket.setPage = function (next) {
|
|
124
124
|
page = Object.assign({ section: null, productId: null, categoryId: null, product: null }, next);
|
|
125
|
-
pageShowcases =
|
|
125
|
+
pageShowcases = {};
|
|
126
126
|
};
|
|
127
127
|
rocket.getPage = () => page;
|
|
128
128
|
|
|
@@ -294,13 +294,15 @@ export function createRocket (config) {
|
|
|
294
294
|
return res.json();
|
|
295
295
|
};
|
|
296
296
|
|
|
297
|
-
|
|
297
|
+
// customKey: identificador da landing (pageType=custom); sem ele a API responde 400.
|
|
298
|
+
rocket.getShowcasesByContext = async function (type, customKey) {
|
|
298
299
|
const pageType = resolvePageType(type);
|
|
299
300
|
if (!pageType) return [];
|
|
300
301
|
const sessionId = await getSessionIdWithTimeout();
|
|
301
302
|
const params = { storeId: config.storeId, pageType, page: pageType, sessionId };
|
|
302
303
|
if (pageType === 'product' && page.productId) params.productId = page.productId;
|
|
303
304
|
if (pageType === 'category' && page.categoryId) params.categoryId = page.categoryId;
|
|
305
|
+
if (pageType === 'custom') params.customKey = customKey;
|
|
304
306
|
|
|
305
307
|
const res = await fetch(config.apiUrl + '/showcases/context?' + query(params), { headers: headers() });
|
|
306
308
|
const showcases = await res.json();
|
|
@@ -317,11 +319,13 @@ export function createRocket (config) {
|
|
|
317
319
|
};
|
|
318
320
|
|
|
319
321
|
// Uma chamada por página, repartida entre os slots (<RocketShowcase position>) — na Linx
|
|
320
|
-
// era o fetchShowCases único distribuindo por data-rocket-showcase-position.
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
322
|
+
// era o fetchShowCases único distribuindo por data-rocket-showcase-position. Por pageType +
|
|
323
|
+
// customKey: a landing e o contexto da página são chamadas distintas. Zera no setPage.
|
|
324
|
+
let pageShowcases = {};
|
|
325
|
+
rocket.getPageShowcases = function (type, customKey) {
|
|
326
|
+
const key = (type || '') + '|' + (customKey || '');
|
|
327
|
+
if (!pageShowcases[key]) pageShowcases[key] = rocket.getShowcasesByContext(type, customKey).catch(() => []);
|
|
328
|
+
return pageShowcases[key];
|
|
325
329
|
};
|
|
326
330
|
|
|
327
331
|
// Só banners (DTO banner-native). Gated pela flag `banners`: loja sem ela recebe [].
|