-
Notifications
You must be signed in to change notification settings - Fork 68
Storage: show skeletons only when needed #1171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
837a880
d093d36
f535c4d
358e04a
30f8d7a
4583eaf
83eccdf
a143e22
5d231ca
bc2cd45
db04da1
da9ec7d
2f954fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,8 +97,10 @@ describe("when set as loading", () => { | |
| }); | ||
|
|
||
| it("renders a loading hint", () => { | ||
| installerRender(<InstallationDeviceField {...props} />); | ||
| screen.getByText("Waiting for information about selected device"); | ||
| const { container } = installerRender(<InstallationDeviceField {...props} />); | ||
|
|
||
| // a PF skeleton is displayed | ||
| expect(container.querySelector("div.pf-v5-c-skeleton")).toBeVisible(); | ||
|
||
| }); | ||
| }); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,8 @@ import { IDLE } from "~/client/status"; | |
|
|
||
| const initialState = { | ||
| loading: true, | ||
| // which UI item is being changed by user | ||
| changing: undefined, | ||
| availableDevices: [], | ||
| volumeTemplates: [], | ||
| encryptionMethods: [], | ||
|
|
@@ -52,7 +54,8 @@ const reducer = (state, action) => { | |
| } | ||
|
|
||
| case "STOP_LOADING" : { | ||
| return { ...state, loading: false }; | ||
| // reset the changing value after the refresh is finished | ||
| return { ...state, loading: false, changing: undefined }; | ||
| } | ||
|
|
||
| case "UPDATE_AVAILABLE_DEVICES": { | ||
|
|
@@ -76,8 +79,8 @@ const reducer = (state, action) => { | |
| } | ||
|
|
||
| case "UPDATE_SETTINGS": { | ||
| const { settings } = action.payload; | ||
| return { ...state, settings }; | ||
| const { settings, changing } = action.payload; | ||
| return { ...state, settings, changing }; | ||
| } | ||
|
|
||
| case "UPDATE_DEVICES": { | ||
|
|
@@ -96,6 +99,30 @@ const reducer = (state, action) => { | |
| } | ||
| }; | ||
|
|
||
| /** | ||
| * Which UI item is being changed by user | ||
| */ | ||
| export const CHANGING = Object.freeze({ | ||
| ENCRYPTION: Symbol("encryption"), | ||
| TARGET: Symbol("target"), | ||
| VOLUMES: Symbol("volumes"), | ||
| POLICY: Symbol("policy"), | ||
| BOOT: Symbol("boot"), | ||
| }); | ||
|
|
||
| // mapping of not affected values for settings components | ||
| // key: component name | ||
| // value: list of items which can be changed without affecting | ||
| // the state of the component | ||
| export const NOT_AFFECTED = { | ||
| // the EncryptionField shows the skeleton only during initial load, | ||
| // it does not depend on any changed item and does not show skeleton later. | ||
| // the ProposalResultSection is refreshed always | ||
| InstallationDeviceField: [CHANGING.ENCRYPTION, CHANGING.BOOT, CHANGING.POLICY, CHANGING.VOLUMES], | ||
| PartitionsField: [CHANGING.ENCRYPTION], | ||
|
||
| SpacePolicyField: [CHANGING.ENCRYPTION, CHANGING.BOOT, CHANGING.VOLUMES, CHANGING.TARGET], | ||
|
||
| }; | ||
|
|
||
| export default function ProposalPage() { | ||
| const { storage: client } = useInstallerClient(); | ||
| const { cancellablePromise } = useCancellablePromise(); | ||
|
|
@@ -208,10 +235,10 @@ export default function ProposalPage() { | |
| } | ||
| }, [client, load, state.settings]); | ||
|
|
||
| const changeSettings = async (settings) => { | ||
| const changeSettings = async (changing, settings) => { | ||
| const newSettings = { ...state.settings, ...settings }; | ||
|
|
||
| dispatch({ type: "UPDATE_SETTINGS", payload: { settings: newSettings } }); | ||
| dispatch({ type: "UPDATE_SETTINGS", payload: { settings: newSettings, changing } }); | ||
| calculate(newSettings).catch(console.error); | ||
| }; | ||
|
|
||
|
|
@@ -236,6 +263,7 @@ export default function ProposalPage() { | |
| settings={state.settings} | ||
| onChange={changeSettings} | ||
| isLoading={state.loading} | ||
| changing={state.changing} | ||
| /> | ||
| <ProposalResultSection | ||
| system={state.system} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, this skeleton here looks really weird.
As commented during the planning meeting of the card and again today during review, the goal of the skeletons is to "reserve space" in the UI for the future content, so things don't jump up and down as that content is loaded into its place.
In case of a pop-up that is going to load at once as soon the content arrives, that multi-line skeleton looks like some kind of render error. I expected the pop-up to open kind of blank but with some "loading" message and/or a spinner (I personally expected the same three circles we have when loading the whole UI).