Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit adc5c1a

Browse files
authored
fix: Load template page chunks without blocking (coder#4689)
1 parent e853706 commit adc5c1a

File tree

3 files changed

+112
-104
lines changed

3 files changed

+112
-104
lines changed

site/src/components/TemplateLayout/TemplateLayout.tsx

+105-95
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"
99
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"
1010
import { DeleteButton } from "components/DropdownButton/ActionCtas"
1111
import { DropdownButton } from "components/DropdownButton/DropdownButton"
12-
import { Loader } from "components/Loader/Loader"
1312
import {
1413
PageHeader,
1514
PageHeaderSubtitle,
@@ -53,7 +52,7 @@ const useTemplateName = () => {
5352

5453
type TemplateLayoutContextValue = {
5554
context: TemplateContext
56-
permissions: Permissions
55+
permissions?: Permissions
5756
}
5857

5958
const TemplateLayoutContext = createContext<
@@ -97,23 +96,23 @@ export const TemplateLayout: FC<PropsWithChildren> = ({ children }) => {
9796
!templateDAUs ||
9897
!templatePermissions
9998

100-
if (isLoading) {
101-
return <Loader />
102-
}
103-
10499
if (templateState.matches("deleted")) {
105100
return <Navigate to="/templates" />
106101
}
107102

108-
const hasIcon = template.icon && template.icon !== ""
103+
const hasIcon = template && template.icon && template.icon !== ""
109104

110105
const createWorkspaceButton = (className?: string) => (
111106
<Link
112107
underline="none"
113108
component={RouterLink}
114-
to={`/templates/${template.name}/workspace`}
109+
to={`/templates/${templateName}/workspace`}
115110
>
116-
<Button className={className ?? ""} startIcon={<AddCircleOutline />}>
111+
<Button
112+
className={className ?? ""}
113+
startIcon={<AddCircleOutline />}
114+
disabled={isLoading}
115+
>
117116
{Language.createButton}
118117
</Button>
119118
</Link>
@@ -128,89 +127,98 @@ export const TemplateLayout: FC<PropsWithChildren> = ({ children }) => {
128127
<Margins>
129128
<PageHeader
130129
actions={
131-
<ChooseOne>
132-
<Cond condition={templatePermissions.canUpdateTemplate}>
133-
<Link
134-
underline="none"
135-
component={RouterLink}
136-
to={`/templates/${template.name}/settings`}
137-
>
138-
<Button variant="outlined" startIcon={<SettingsOutlined />}>
139-
{Language.settingsButton}
140-
</Button>
141-
</Link>
130+
isLoading ? undefined : (
131+
<ChooseOne>
132+
<Cond condition={templatePermissions.canUpdateTemplate}>
133+
<Link
134+
underline="none"
135+
component={RouterLink}
136+
to={`/templates/${template.name}/settings`}
137+
>
138+
<Button variant="outlined" startIcon={<SettingsOutlined />}>
139+
{Language.settingsButton}
140+
</Button>
141+
</Link>
142142

143-
<DropdownButton
144-
primaryAction={createWorkspaceButton(styles.actionButton)}
145-
secondaryActions={[
146-
{
147-
action: "delete",
148-
button: (
149-
<DeleteButton handleAction={handleDeleteTemplate} />
150-
),
151-
},
152-
]}
153-
canCancel={false}
154-
/>
155-
</Cond>
143+
<DropdownButton
144+
primaryAction={createWorkspaceButton(styles.actionButton)}
145+
secondaryActions={[
146+
{
147+
action: "delete",
148+
button: (
149+
<DeleteButton handleAction={handleDeleteTemplate} />
150+
),
151+
},
152+
]}
153+
canCancel={false}
154+
/>
155+
</Cond>
156156

157-
<Cond>{createWorkspaceButton()}</Cond>
158-
</ChooseOne>
157+
<Cond>{createWorkspaceButton()}</Cond>
158+
</ChooseOne>
159+
)
159160
}
160161
>
161162
<Stack direction="row" spacing={3} className={styles.pageTitle}>
162-
<div>
163-
{hasIcon ? (
164-
<div className={styles.iconWrapper}>
165-
<img src={template.icon} alt="" />
166-
</div>
167-
) : (
168-
<Avatar className={styles.avatar}>
169-
{firstLetter(template.name)}
170-
</Avatar>
171-
)}
172-
</div>
173-
<div>
174-
<PageHeaderTitle>{template.name}</PageHeaderTitle>
175-
<PageHeaderSubtitle condensed>
176-
{template.description === ""
177-
? Language.noDescription
178-
: template.description}
179-
</PageHeaderSubtitle>
180-
</div>
163+
{!isLoading && (
164+
<div>
165+
{hasIcon ? (
166+
<div className={styles.iconWrapper}>
167+
<img src={template.icon} alt="" />
168+
</div>
169+
) : (
170+
<Avatar className={styles.avatar}>
171+
{firstLetter(templateName)}
172+
</Avatar>
173+
)}
174+
</div>
175+
)}
176+
177+
{!isLoading && (
178+
<div>
179+
<PageHeaderTitle>{templateName}</PageHeaderTitle>
180+
<PageHeaderSubtitle condensed>
181+
{template.description === ""
182+
? Language.noDescription
183+
: template.description}
184+
</PageHeaderSubtitle>
185+
</div>
186+
)}
181187
</Stack>
182188
</PageHeader>
183189
</Margins>
184190

185-
<div className={styles.tabs}>
186-
<Margins>
187-
<Stack direction="row" spacing={0.25}>
188-
<NavLink
189-
end
190-
to={`/templates/${template.name}`}
191-
className={({ isActive }) =>
192-
combineClasses([
193-
styles.tabItem,
194-
isActive ? styles.tabItemActive : undefined,
195-
])
196-
}
197-
>
198-
Summary
199-
</NavLink>
200-
<NavLink
201-
to={`/templates/${template.name}/permissions`}
202-
className={({ isActive }) =>
203-
combineClasses([
204-
styles.tabItem,
205-
isActive ? styles.tabItemActive : undefined,
206-
])
207-
}
208-
>
209-
Permissions
210-
</NavLink>
211-
</Stack>
212-
</Margins>
213-
</div>
191+
{!isLoading && (
192+
<div className={styles.tabs}>
193+
<Margins>
194+
<Stack direction="row" spacing={0.25}>
195+
<NavLink
196+
end
197+
to={`/templates/${template.name}`}
198+
className={({ isActive }) =>
199+
combineClasses([
200+
styles.tabItem,
201+
isActive ? styles.tabItemActive : undefined,
202+
])
203+
}
204+
>
205+
Summary
206+
</NavLink>
207+
<NavLink
208+
to={`/templates/${template.name}/permissions`}
209+
className={({ isActive }) =>
210+
combineClasses([
211+
styles.tabItem,
212+
isActive ? styles.tabItemActive : undefined,
213+
])
214+
}
215+
>
216+
Permissions
217+
</NavLink>
218+
</Stack>
219+
</Margins>
220+
</div>
221+
)}
214222

215223
<Margins>
216224
<TemplateLayoutContext.Provider
@@ -220,18 +228,20 @@ export const TemplateLayout: FC<PropsWithChildren> = ({ children }) => {
220228
</TemplateLayoutContext.Provider>
221229
</Margins>
222230

223-
<DeleteDialog
224-
isOpen={templateState.matches("confirmingDelete")}
225-
confirmLoading={templateState.matches("deleting")}
226-
onConfirm={() => {
227-
templateSend("CONFIRM_DELETE")
228-
}}
229-
onCancel={() => {
230-
templateSend("CANCEL_DELETE")
231-
}}
232-
entity="template"
233-
name={template.name}
234-
/>
231+
{!isLoading && (
232+
<DeleteDialog
233+
isOpen={templateState.matches("confirmingDelete")}
234+
confirmLoading={templateState.matches("deleting")}
235+
onConfirm={() => {
236+
templateSend("CONFIRM_DELETE")
237+
}}
238+
onCancel={() => {
239+
templateSend("CANCEL_DELETE")
240+
}}
241+
entity="template"
242+
name={template.name}
243+
/>
244+
)}
235245
</>
236246
)
237247
}

site/src/pages/TemplatePage/TemplatePermissionsPage/TemplatePermissionsPage.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,22 @@ import { Helmet } from "react-helmet-async"
1313
import { pageTitle } from "util/page"
1414
import { templateACLMachine } from "xServices/template/templateACLXService"
1515
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"
16+
import { Loader } from "components/Loader/Loader"
1617

1718
export const TemplatePermissionsPage: FC<
1819
React.PropsWithChildren<unknown>
1920
> = () => {
2021
const organizationId = useOrganizationId()
2122
const { context } = useTemplateLayoutContext()
2223
const { template, permissions } = context
23-
if (!template || !permissions) {
24-
throw new Error(
25-
"This page should not be displayed until template or permissions being loaded.",
26-
)
27-
}
2824
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility()
2925
const [state, send] = useMachine(templateACLMachine, {
30-
context: { templateId: template.id },
26+
context: { templateId: template?.id },
3127
})
3228
const { templateACL, userToBeUpdated, groupToBeUpdated } = state.context
29+
if (!template || !permissions) {
30+
return <Loader />
31+
}
3332

3433
return (
3534
<>

site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPage.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { FC } from "react"
33
import { Helmet } from "react-helmet-async"
44
import { pageTitle } from "util/page"
55
import { TemplateSummaryPageView } from "./TemplateSummaryPageView"
6+
import { Loader } from "components/Loader/Loader"
67

78
export const TemplateSummaryPage: FC = () => {
89
const { context } = useTemplateLayoutContext()
@@ -16,9 +17,7 @@ export const TemplateSummaryPage: FC = () => {
1617
} = context
1718

1819
if (!template || !activeTemplateVersion || !templateResources) {
19-
throw new Error(
20-
"This page should not be displayed until template, activeTemplateVersion or templateResources being loaded.",
21-
)
20+
return <Loader />
2221
}
2322

2423
return (

0 commit comments

Comments
 (0)