Skip to content

Commit f632b7b

Browse files
authored
Fix pending state when quickly switching from one page to another (baserow#4804)
1 parent 7a2a8fc commit f632b7b

2 files changed

Lines changed: 157 additions & 120 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<template>
2+
<div class="page-editor">
3+
<PageHeader />
4+
<div class="layout__col-2-2 page-editor__content">
5+
<div :style="{ width: `calc(100% - ${panelWidth}px)` }">
6+
<PagePreview />
7+
</div>
8+
<div
9+
class="page-editor__side-panel"
10+
:style="{ width: `${panelWidth}px` }"
11+
>
12+
<PageSidePanels />
13+
</div>
14+
</div>
15+
</div>
16+
</template>
17+
18+
<script setup>
19+
import { ref, computed, watch, provide } from 'vue'
20+
import PageHeader from '@baserow/modules/builder/components/page/header/PageHeader'
21+
import PagePreview from '@baserow/modules/builder/components/page/PagePreview'
22+
import PageSidePanels from '@baserow/modules/builder/components/page/PageSidePanels'
23+
import { DataProviderType } from '@baserow/modules/core/dataProviderTypes'
24+
import ApplicationBuilderFormulaInput from '@baserow/modules/builder/components/ApplicationBuilderFormulaInput'
25+
import _ from 'lodash'
26+
27+
const props = defineProps({
28+
workspace: {
29+
type: Object,
30+
required: true,
31+
},
32+
builder: {
33+
type: Object,
34+
required: true,
35+
},
36+
page: {
37+
type: Object,
38+
required: true,
39+
},
40+
})
41+
42+
const mode = 'editing'
43+
const { $store, $registry } = useNuxtApp()
44+
45+
const panelWidth = ref(360)
46+
47+
const applicationContext = computed(() => ({
48+
workspace: props.workspace,
49+
builder: props.builder,
50+
mode,
51+
}))
52+
53+
const sharedPage = computed(() =>
54+
$store.getters['page/getSharedPage'](props.builder)
55+
)
56+
57+
const dataSources = computed(() => {
58+
return $store.getters['dataSource/getPageDataSources'](props.page)
59+
})
60+
61+
const sharedDataSources = computed(() => {
62+
return $store.getters['dataSource/getPageDataSources'](sharedPage.value)
63+
})
64+
65+
const dispatchContext = computed(() => {
66+
return DataProviderType.getAllDataSourceDispatchContext(
67+
$registry.getAll('builderDataProvider'),
68+
{ ...applicationContext.value, page: props.page }
69+
)
70+
})
71+
72+
const applicationDispatchContext = computed(() => {
73+
return DataProviderType.getAllDataSourceDispatchContext(
74+
$registry.getAll('builderDataProvider'),
75+
{ builder: props.builder, mode }
76+
)
77+
})
78+
79+
provide('workspace', props.workspace)
80+
provide('builder', props.builder)
81+
provide('currentPage', props.page)
82+
provide('mode', mode)
83+
provide('formulaComponent', ApplicationBuilderFormulaInput)
84+
provide('applicationContext', applicationContext)
85+
86+
// Watchers
87+
watch(
88+
dataSources,
89+
() => {
90+
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
91+
page: props.page,
92+
data: dispatchContext.value,
93+
mode,
94+
})
95+
},
96+
{ deep: true }
97+
)
98+
99+
watch(
100+
sharedDataSources,
101+
() => {
102+
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
103+
page: sharedPage.value,
104+
data: dispatchContext.value,
105+
})
106+
},
107+
{ deep: true }
108+
)
109+
110+
watch(
111+
dispatchContext,
112+
(newDispatchContext, oldDispatchContext) => {
113+
if (!_.isEqual(newDispatchContext, oldDispatchContext)) {
114+
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
115+
page: props.page,
116+
data: newDispatchContext,
117+
mode,
118+
})
119+
}
120+
},
121+
{ deep: true }
122+
)
123+
124+
watch(
125+
applicationDispatchContext,
126+
(newDispatchContext, oldDispatchContext) => {
127+
if (!_.isEqual(newDispatchContext, oldDispatchContext)) {
128+
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
129+
page: sharedPage.value,
130+
data: newDispatchContext,
131+
})
132+
}
133+
},
134+
{ deep: true }
135+
)
136+
</script>

web-frontend/modules/builder/pages/pageEditor.vue

Lines changed: 21 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,21 @@
11
<template>
2-
<!-- TODO MIG add a skeleton loader while the page is loading. -->
3-
<div v-if="builder && currentPage && sharedPage" class="page-editor">
4-
<PageHeader />
5-
<div class="layout__col-2-2 page-editor__content">
6-
<div :style="{ width: `calc(100% - ${panelWidth}px)` }">
7-
<PagePreview />
8-
</div>
9-
<div
10-
class="page-editor__side-panel"
11-
:style="{ width: `${panelWidth}px` }"
12-
>
13-
<PageSidePanels />
14-
</div>
15-
</div>
16-
</div>
2+
<PageEditorContent
3+
v-if="!pending"
4+
:workspace="workspace"
5+
:builder="builder"
6+
:page="currentPage"
7+
/>
178
</template>
189

1910
<script setup>
2011
import { useHead, useAsyncData } from '#imports'
21-
import { ref, computed, watch, provide } from 'vue'
12+
import { computed } from 'vue'
2213
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'
2314
import { StoreItemLookupError } from '@baserow/modules/core/errors'
24-
import PageHeader from '@baserow/modules/builder/components/page/header/PageHeader'
25-
import PagePreview from '@baserow/modules/builder/components/page/PagePreview'
26-
import PageSidePanels from '@baserow/modules/builder/components/page/PageSidePanels'
2715
import { DataProviderType } from '@baserow/modules/core/dataProviderTypes'
2816
import { BuilderApplicationType } from '@baserow/modules/builder/applicationTypes'
29-
import ApplicationBuilderFormulaInput from '@baserow/modules/builder/components/ApplicationBuilderFormulaInput'
3017
import _ from 'lodash'
18+
import PageEditorContent from '@baserow/modules/builder/components/PageEditorContent.vue'
3119
3220
definePageMeta({
3321
layout: 'app',
@@ -45,21 +33,16 @@ const route = useRoute()
4533
const { t } = useI18n()
4634
const { $store, $registry, $i18n } = useNuxtApp()
4735
48-
const panelWidth = ref(360)
49-
50-
// Provide values for child components
51-
const applicationContext = computed(() => ({
52-
workspace: workspace.value,
53-
builder: builder.value,
54-
mode,
55-
}))
56-
5736
useHead(() => ({
5837
title: t('pageEditor.title'),
5938
}))
6039
6140
// Load page data
62-
const { data: pageData, error: pageError } = await useAsyncData(
41+
const {
42+
data: pageData,
43+
error: pageError,
44+
pending,
45+
} = await useAsyncData(
6346
() => `page-editor-${route.params.builderId}-${route.params.pageId}`,
6447
async () => {
6548
// The objects are selected by the middleware
@@ -122,98 +105,16 @@ const { data: pageData, error: pageError } = await useAsyncData(
122105
123106
if (pageError.value) {
124107
// If we have an error we want to display it.
125-
throw pageError.value
108+
if (pageError.value.statusCode === 404) {
109+
showError(pageError.value)
110+
} else {
111+
throw pageError.value
112+
}
126113
}
127114
128-
const workspace = computed(() => pageData.value?.workspace ?? null)
129-
const builder = computed(() => pageData.value?.builder ?? null)
130-
const currentPage = computed(() => pageData.value?.page ?? null)
131-
const sharedPage = computed(() => pageData.value?.sharedPage ?? null)
132-
133-
// Computed properties
134-
const dataSources = computed(() => {
135-
if (!currentPage.value) return []
136-
return $store.getters['dataSource/getPageDataSources'](currentPage.value)
137-
})
138-
139-
const sharedDataSources = computed(() => {
140-
if (!sharedPage.value) return []
141-
return $store.getters['dataSource/getPageDataSources'](sharedPage.value)
142-
})
143-
144-
const dispatchContext = computed(() => {
145-
if (!currentPage.value || !applicationContext.value) return {}
146-
return DataProviderType.getAllDataSourceDispatchContext(
147-
$registry.getAll('builderDataProvider'),
148-
{ ...applicationContext.value, page: currentPage.value }
149-
)
150-
})
151-
152-
const applicationDispatchContext = computed(() => {
153-
if (!builder.value) return {}
154-
return DataProviderType.getAllDataSourceDispatchContext(
155-
$registry.getAll('builderDataProvider'),
156-
{ builder: builder.value, mode }
157-
)
158-
})
159-
160-
provide('workspace', workspace)
161-
provide('builder', builder)
162-
provide('currentPage', currentPage)
163-
provide('mode', mode)
164-
provide('formulaComponent', ApplicationBuilderFormulaInput)
165-
provide('applicationContext', applicationContext)
166-
167-
// Watchers
168-
watch(
169-
dataSources,
170-
() => {
171-
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
172-
page: currentPage.value,
173-
data: dispatchContext.value,
174-
mode,
175-
})
176-
},
177-
{ deep: true }
178-
)
179-
180-
watch(
181-
sharedDataSources,
182-
() => {
183-
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
184-
page: sharedPage.value,
185-
data: dispatchContext.value,
186-
})
187-
},
188-
{ deep: true }
189-
)
190-
191-
watch(
192-
dispatchContext,
193-
(newDispatchContext, oldDispatchContext) => {
194-
if (!_.isEqual(newDispatchContext, oldDispatchContext)) {
195-
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
196-
page: currentPage.value,
197-
data: newDispatchContext,
198-
mode,
199-
})
200-
}
201-
},
202-
{ deep: true }
203-
)
204-
205-
watch(
206-
applicationDispatchContext,
207-
(newDispatchContext, oldDispatchContext) => {
208-
if (!_.isEqual(newDispatchContext, oldDispatchContext)) {
209-
$store.dispatch('dataSourceContent/debouncedFetchPageDataSourceContent', {
210-
page: sharedPage.value,
211-
data: newDispatchContext,
212-
})
213-
}
214-
},
215-
{ deep: true }
216-
)
115+
const workspace = computed(() => pageData.value.workspace)
116+
const builder = computed(() => pageData.value.builder)
117+
const currentPage = computed(() => pageData.value.page)
217118
218119
// Navigation guards
219120
onBeforeRouteUpdate((to, from) => {

0 commit comments

Comments
 (0)