Skip to content

Commit 38627a2

Browse files
new fixes
1 parent 018976c commit 38627a2

File tree

12 files changed

+270
-177
lines changed

12 files changed

+270
-177
lines changed

src/core/products/products/product-show/ProductShowController.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ const copySkuToClipboard = async (sku: string) => {
160160
<template v-if="!loading && result">
161161
<Card>
162162
<div class="grid xl:grid-cols-2 gap-8 mb-6">
163-
<div class="w-full bg-white shadow-[4px_6px_10px_-3px_#bfc9d4] rounded border border-[#e0e6ed] dark:border-[#1b2e4b] dark:bg-[#191e3a] dark:shadow-none">
163+
<div class="w-full bg-white shadow-[4px_6px_10px_-3px_#bfc9d4] rounded-lg border border-[#e0e6ed] dark:border-[#1b2e4b] dark:bg-[#191e3a] dark:shadow-none">
164164
<div class="p-5 flex items-center sm:items-center flex-col sm:flex-row">
165165
<Link v-if="getResultData(result, 'thumbnailUrl')" :path="{ name: 'products.products.show', params: { id: id }, query: { ...route.query, tab: 'media' } }">
166166
<div class="mb-5 w-20 h-20">

src/core/products/products/product-show/containers/product-inspector/ProductInspector.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ const refreshInspector = async () => {
230230
<ApolloSubscription :subscription="inspectorSubscription" :variables="{ pk: product.inspector?.id }">
231231
<template v-slot:default="{ loading, error, result }">
232232
<template v-if="!loading && result && refetchData(result)">
233-
<div class="p-2" :class="['shadow sm:rounded-lg relative', bgColorClass(color)]">
233+
<div class="p-2" :class="['shadow rounded-lg relative ', bgColorClass(color)]">
234234
<div class="px-4 py-4 sm:p-4 flex justify-between items-center">
235235
<h3 class="text-lg font-semibold leading-6 text-white">
236236
{{ getInspectorLabel(color) }}

src/core/products/products/product-show/containers/tabs/content/ProductContentView.vue

Lines changed: 114 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,36 @@ import ProductPreviewTrigger from "../shared/ProductPreviewTrigger.vue";
2323
const {t} = useI18n();
2424
const props = defineProps<{ product: Product }>();
2525
26-
const initialForm = ref({
26+
type ProductContentFormState = {
27+
name: string;
28+
subtitle: string;
29+
shortDescription: string;
30+
description: string;
31+
urlKey: string;
32+
};
33+
34+
const emptyHtml = '<p><br></p>';
35+
36+
const createEmptyFormState = (): ProductContentFormState => ({
2737
name: '',
2838
subtitle: '',
29-
shortDescription: '',
30-
description: '',
39+
shortDescription: emptyHtml,
40+
description: emptyHtml,
3141
urlKey: ''
3242
});
3343
34-
const form = reactive({...initialForm.value});
44+
const initialForm = ref(createEmptyFormState());
45+
const form = reactive(createEmptyFormState());
3546
const currentLanguage = ref(null);
3647
const currentSalesChannel = ref<'default' | string>('default');
3748
const mutation = ref(null);
3849
const translationId = ref(null);
39-
const oldLang = ref(currentLanguage.value);
40-
const oldChannel = ref(currentSalesChannel.value);
4150
const salesChannels = ref<any[]>([]);
4251
const fieldErrors = ref<Record<string, string>>({});
4352
const bulletPointsRef = ref<any>(null);
4453
const defaultLanguageCode = ref('en');
54+
const formRenderKey = ref(0);
55+
let latestFormRequestId = 0;
4556
4657
const currentChannelType = computed(() => {
4758
if (currentSalesChannel.value === 'default') return 'default';
@@ -51,6 +62,31 @@ const currentChannelType = computed(() => {
5162
5263
const fieldRules = computed(() => getContentFieldRules(currentChannelType.value));
5364
65+
const applyFormState = (nextState: ProductContentFormState) => {
66+
form.name = nextState.name;
67+
form.subtitle = nextState.subtitle;
68+
form.shortDescription = nextState.shortDescription;
69+
form.description = nextState.description;
70+
form.urlKey = nextState.urlKey;
71+
};
72+
73+
const resetFormState = () => {
74+
applyFormState(createEmptyFormState());
75+
fieldErrors.value = {};
76+
translationId.value = null;
77+
mutation.value = createProductTranslationMutation;
78+
bulletPointsRef.value = null;
79+
formRenderKey.value += 1;
80+
};
81+
82+
const mapTranslationToFormState = (translation: Partial<ProductContentFormState> | null | undefined): ProductContentFormState => ({
83+
name: translation?.name || '',
84+
subtitle: translation?.subtitle || '',
85+
shortDescription: translation?.shortDescription || emptyHtml,
86+
description: translation?.description || emptyHtml,
87+
urlKey: translation?.urlKey || '',
88+
});
89+
5490
5591
const handleLanguageOptionsLoaded = (rawData) => {
5692
if (!rawData?.languages?.length) {
@@ -84,6 +120,13 @@ onMounted(async () => {
84120
});
85121
86122
const setFormAndMutation = async (language, channel) => {
123+
if (!language) {
124+
return;
125+
}
126+
127+
const requestId = ++latestFormRequestId;
128+
resetFormState();
129+
87130
try {
88131
if (channel === 'default') {
89132
// Query where salesChannel is null (Default)
@@ -93,25 +136,16 @@ const setFormAndMutation = async (language, channel) => {
93136
fetchPolicy: 'network-only'
94137
});
95138
139+
if (requestId !== latestFormRequestId) {
140+
return;
141+
}
142+
96143
if (data && data.productTranslations.edges.length === 1) {
97144
const translation = data.productTranslations.edges[0].node;
98-
form.name = translation.name;
99-
form.subtitle = translation.subtitle;
100-
form.shortDescription = translation.shortDescription;
101-
form.description = translation.description;
102-
form.urlKey = translation.urlKey;
145+
applyFormState(mapTranslationToFormState(translation));
103146
translationId.value = translation.id;
104147
mutation.value = updateProductTranslationMutation;
105-
} else {
106-
form.name = '';
107-
form.subtitle = '';
108-
form.shortDescription = '<p><br></p>';
109-
form.description = '<p><br></p>';
110-
form.urlKey = '';
111-
translationId.value = null;
112-
mutation.value = createProductTranslationMutation;
113148
}
114-
115149
} else {
116150
// Query with specific salesChannelId
117151
const { data } = await apolloClient.query({
@@ -124,29 +158,29 @@ const setFormAndMutation = async (language, channel) => {
124158
fetchPolicy: 'network-only'
125159
});
126160
161+
if (requestId !== latestFormRequestId) {
162+
return;
163+
}
164+
127165
if (data && data.productTranslations.edges.length === 1) {
128166
const translation = data.productTranslations.edges[0].node;
129-
form.name = translation.name;
130-
form.subtitle = translation.subtitle;
131-
form.shortDescription = translation.shortDescription;
132-
form.description = translation.description;
133-
form.urlKey = translation.urlKey;
167+
applyFormState(mapTranslationToFormState(translation));
134168
translationId.value = translation.id;
135169
mutation.value = updateProductTranslationMutation;
136-
} else {
137-
form.name = '';
138-
form.subtitle = '';
139-
form.shortDescription = '<p><br></p>';
140-
form.description = '<p><br></p>';
141-
form.urlKey = '';
142-
translationId.value = null;
143-
mutation.value = createProductTranslationMutation;
144170
}
145171
}
146172
} catch (error) {
173+
if (requestId !== latestFormRequestId) {
174+
return;
175+
}
176+
147177
console.error("Error fetching translation:", error);
148178
}
149179
180+
if (requestId !== latestFormRequestId) {
181+
return;
182+
}
183+
150184
await nextTick();
151185
initialForm.value = { ...form };
152186
};
@@ -155,48 +189,38 @@ const setFormAndMutation = async (language, channel) => {
155189
watch(currentLanguage, async (newLanguage, oldLanguage) => {
156190
if (oldLanguage === null) {
157191
await setFormAndMutation(newLanguage, currentSalesChannel.value);
158-
oldLang.value = newLanguage;
159192
}
160193
});
161194
162-
watch(currentSalesChannel, async (newChannel, oldChannelVal) => {
163-
if (oldChannelVal === null) {
164-
await setFormAndMutation(currentLanguage.value, newChannel);
165-
oldChannel.value = newChannel;
166-
}
167-
});
168-
169-
watch(currentChannelType, (newType) => {
170-
if (!getContentFieldRules(newType).bulletPoints) {
195+
const handleLanguageSelection = async (newLanguage) => {
196+
if (newLanguage === currentLanguage.value) {
171197
return;
172198
}
173-
});
174-
175-
const handleLanguageSelection = async (newLanguage) => {
176199
177200
if (JSON.stringify(form) !== JSON.stringify(initialForm.value)) {
178201
const confirmChange = confirm(t('products.translation.confirmLanguageChange'));
179202
if (!confirmChange) {
180-
currentLanguage.value = oldLang.value;
181203
return;
182204
}
183205
}
184206
185-
oldLang.value = newLanguage;
207+
currentLanguage.value = newLanguage;
186208
await setFormAndMutation(newLanguage, currentSalesChannel.value);
187209
};
188210
189211
const handleSalesChannelSelection = async (newChannel) => {
212+
if (newChannel === currentSalesChannel.value) {
213+
return;
214+
}
190215
191216
if (JSON.stringify(form) !== JSON.stringify(initialForm.value)) {
192217
const confirmChange = confirm(t('products.products.messages.unsavedChanges'));
193218
if (!confirmChange) {
194-
currentSalesChannel.value = oldChannel.value;
195219
return;
196220
}
197221
}
198222
199-
oldChannel.value = newChannel;
223+
currentSalesChannel.value = newChannel;
200224
await setFormAndMutation(currentLanguage.value, newChannel);
201225
};
202226
@@ -278,49 +302,42 @@ const shortDescriptionToolbarOptions = [
278302

279303
<template>
280304

281-
<Flex end class="gap-2 flex-wrap">
282-
<FlexCell>
283-
<ProductPreviewTrigger
284-
:product="product"
285-
:sales-channel-id="currentSalesChannel"
286-
:sales-channels="salesChannels"
287-
:language-code="currentLanguage"
288-
/>
289-
</FlexCell>
290-
<FlexCell>
291-
<AdvancedContentGenerator
292-
:product-ids="[product.id]"
293-
:initial-sales-channel-ids="currentSalesChannel !== 'default' ? [currentSalesChannel] : []"
294-
:small="false"
295-
/>
296-
</FlexCell>
297-
<FlexCell>
298-
<ProductContentImportModal
299-
:product-ids="[product.id]"
300-
:current-language="currentLanguage"
301-
:current-sales-channel="currentSalesChannel"
302-
:sales-channels="salesChannels"
303-
@imported="handleImportCompleted"
304-
/>
305-
</FlexCell>
306-
<FlexCell>
307-
<ApolloMutation v-if="mutation" :mutation="mutation" :variables="getVariables()">
308-
<template v-slot="{ mutate, loading }">
309-
<Button :customClass="'btn btn-primary'" :disabled="loading" @click="handleSave(mutate)">
310-
{{ t('shared.button.save') }}
311-
</Button>
312-
</template>
313-
</ApolloMutation>
314-
</FlexCell>
315-
<FlexCell>
305+
<div class="flex flex-wrap items-center justify-end gap-2">
306+
<ProductPreviewTrigger
307+
:product="product"
308+
:sales-channel-id="currentSalesChannel"
309+
:sales-channels="salesChannels"
310+
:language-code="currentLanguage"
311+
/>
312+
<AdvancedContentGenerator
313+
:product-ids="[product.id]"
314+
:initial-sales-channel-ids="currentSalesChannel !== 'default' ? [currentSalesChannel] : []"
315+
:small="false"
316+
/>
317+
<ProductContentImportModal
318+
:product-ids="[product.id]"
319+
:current-language="currentLanguage"
320+
:current-sales-channel="currentSalesChannel"
321+
:sales-channels="salesChannels"
322+
btn-class="btn-outline-primary"
323+
@imported="handleImportCompleted"
324+
/>
325+
<ApolloMutation v-if="mutation" :mutation="mutation" :variables="getVariables()">
326+
<template v-slot="{ mutate, loading }">
327+
<Button :customClass="'btn btn-primary'" :disabled="loading" @click="handleSave(mutate)">
328+
{{ t('shared.button.save') }}
329+
</Button>
330+
</template>
331+
</ApolloMutation>
332+
<div class="shrink-0">
316333
<LanguageSelector
317-
v-model="currentLanguage"
334+
:model-value="currentLanguage"
318335
selector-class="w-full min-w-[12rem] sm:min-w-[14rem]"
319336
@loaded="handleLanguageOptionsLoaded"
320337
@update:modelValue="handleLanguageSelection"
321338
/>
322-
</FlexCell>
323-
</Flex>
339+
</div>
340+
</div>
324341

325342
<Flex v-if="currentSalesChannel !== 'default'" class=" mt-2 block lg:hidden">
326343
<FlexCell>
@@ -338,13 +355,17 @@ const shortDescriptionToolbarOptions = [
338355
mt-4
339356
grid gap-4
340357
grid-cols-1
341-
lg:grid-cols-[220px_minmax(0,1fr)]
342-
xl:grid-cols-[360px_minmax(0,1fr)]
343-
2xl:grid-cols-[420px_minmax(0,1fr)]
358+
lg:grid-cols-[200px_minmax(0,1fr)]
359+
xl:grid-cols-[280px_minmax(0,1fr)]
360+
2xl:grid-cols-[340px_minmax(0,1fr)]
344361
"
345362
>
346363
<div>
347-
<SalesChannelTabs v-model="currentSalesChannel" :channels="salesChannels" @update:modelValue="handleSalesChannelSelection" />
364+
<SalesChannelTabs
365+
:model-value="currentSalesChannel"
366+
:channels="salesChannels"
367+
@update:modelValue="handleSalesChannelSelection"
368+
/>
348369
</div>
349370

350371
<!-- Product Content Form -->
@@ -355,6 +376,7 @@ const shortDescriptionToolbarOptions = [
355376
>
356377
<div class="p-2 bg-white">
357378
<ProductContentForm
379+
:key="formRenderKey"
358380
:form="form"
359381
:field-errors="fieldErrors"
360382
:product-id="product.id"

src/core/products/products/product-show/containers/tabs/media/MediaView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ const handleCreateGallery = async () => {
122122
<template>
123123
<TabContentTemplate>
124124
<template #content>
125-
<div class="grid gap-6 lg:grid-cols-[220px_1fr] xl:grid-cols-[360px_1fr] 2xl:grid-cols-[420px_1fr]">
125+
<div class="grid gap-6 lg:grid-cols-[200px_1fr] xl:grid-cols-[280px_1fr] 2xl:grid-cols-[340px_1fr]">
126126
<SalesChannelTabs
127127
v-model="currentSalesChannel"
128128
:channels="salesChannels"

0 commit comments

Comments
 (0)