-
Notifications
You must be signed in to change notification settings - Fork 2
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
Save / Restore selection and expansion state on extension load #1373
Conversation
deploymentName: string; | ||
configurationName: string; | ||
credentialName: string; | ||
}; |
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.
We store the selection state as an object within VSCode workspace storage
@@ -100,7 +109,7 @@ export class HomeViewProvider implements WebviewViewProvider { | |||
// are created within the webview this._context (i.e. inside media/main.js) | |||
case "initializing": | |||
// send back the data needed. | |||
await this.refreshAll(); | |||
await this.refreshAll(true); |
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.
refreshAll has been updated to understand if it needs to send the initial state of the selections along with the refreshed data or not. This will only occur in response to the initializing request from the Vue App.
true, | ||
); | ||
case "navigate": | ||
env.openExternal(Uri.parse(message.payload)); | ||
break; |
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.
the commands "expanded" and "collapsed" have been refaced into the "updateDeploymentButtonExpanded" command.
@@ -51,6 +51,7 @@ | |||
v-model="selectedDeployment" | |||
:options="deployments" | |||
:get-key="(d) => d.saveName" | |||
@update:modelValue="onUpdateModelValueSelectedDeployment" |
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.
We switch to triggering off of the actual update, coming from the component, which is only raised when the user performs an action and is not raised when we change the v-model value programatically.
updateCredentialsAndConfigurationForDeployment(); | ||
}); | ||
updateParentViewSelectionState(); | ||
}; |
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.
Switching from the watch of the v-model value, so we can perform our business logic only when the user initiates the change (in contrast to us setting the v-model value as part of the initialization).
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.
Very nice split.
@@ -261,7 +273,7 @@ const updateSelectedConfigurationByName = ( | |||
): boolean => { | |||
const previousSelectedConfig = selectedConfig.value; | |||
let selectedConfigTarget: Configuration | undefined = undefined; | |||
if (selectedConfig.value) { | |||
if (configurationName) { |
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.
This was a bug.
@@ -276,7 +288,7 @@ const updateSelectedConfigurationByName = ( | |||
const updateSelectedCredentialByName = (credentialName?: string): boolean => { | |||
const previousSelectedAccount = selectedAccount.value; | |||
let selectedCredentialTarget: Account | undefined = undefined; | |||
if (selectedAccount.value) { | |||
if (credentialName) { |
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.
another bug.
// Always cause the re-calculation even if selected deployment didn't change | ||
updateCredentialsAndConfigurationForDeployment(); | ||
if (payload.selectedDeploymentName) { | ||
updateSelectedDeploymentByName(payload.selectedDeploymentName); |
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.
So if we have a selected value, we'll set it by name and cascade any business changes.
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.
Really like that each of these utilize the updateSelectedDeploymentByName
function (and similar) so we already had the logic for handling if the name isn't found in the list.
selectedConfig.value?.configurationName, | ||
); | ||
if (payload.selectedConfigurationName) { | ||
updateSelectedConfigurationByName(payload.selectedConfigurationName); |
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.
same thought as above here.
break; | ||
} | ||
case "refresh_credential_data": { | ||
const payload = JSON.parse(event.data.payload); | ||
accounts.value = payload.credentials; | ||
updateSelectedCredentialByName(selectedAccount.value?.name); | ||
if (payload.selectedCredentialName) { | ||
updateSelectedCredentialByName(payload.selectedCredentialName); |
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.
and again.
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.
This is working wonderfully. I'm glad we waited until the object work was complete.
I had a couple small comments, but running through your instructions for review I didn't hit anything that made me think there was a bug.
updateCredentialsAndConfigurationForDeployment(); | ||
}); | ||
updateParentViewSelectionState(); | ||
}; |
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.
Very nice split.
// Always cause the re-calculation even if selected deployment didn't change | ||
updateCredentialsAndConfigurationForDeployment(); | ||
if (payload.selectedDeploymentName) { | ||
updateSelectedDeploymentByName(payload.selectedDeploymentName); |
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.
Really like that each of these utilize the updateSelectedDeploymentByName
function (and similar) so we already had the logic for handling if the name isn't found in the list.
Intent
Resolves #1229
Resolves #1271
We will be using VSCode's storage to remember the last section and expansion states of the home view. These will be restored upon extension reload.
Type of Change
Approach
The tough part of this implementation was to find a clean way to restore the last selections to reflect the last state, vs the other times which we'll update the selections w/ business logic. So we needed to make sure that the business logic updates to selected configuration (which are made to reflect the last config used to deploy) and the update to credential (which is made to makes sure the account selected matches the deployment URL - either by validating the currently selected one or by switching to the first in the filtered list), are only executed when the deployment choice is changed by the user, rather than programmatically. By doing this, it allows us to set all three select box values to what was last persisted.
So we will restore the settings upon initialization of the Home View WebViewView, and then we record the settings into VSCode storage each time they are changed (either the Home View Deploy button is collapsed or expanded, or any of the select choices are changed - either programmatically or by the user).
We are using workspace storage for these settings, so they are set on a per workspace basis as the name implies.
There is no API available to clear them, but I have used this technique to clear all workspace knowledge from VSCode:https://stackoverflow.com/a/71178197Automated Tests
Directions for Reviewers
You'll want to have multiple deployments, multiple configurations and multiple credentials with which you can use for validation. On the credentials, you can use the same API key across multiple accounts, so just duplicate up a few to the same server. You'll want to have credentials for two different servers, but also multiple credentials for at least one of them.
As I mentioned in the overview, the last used settings are restored when the Home View is initialized. This allows you to be able to test and reproduce this cycle by using the pallet command: "Developer: Reload Windows" each time you want to test if the values you currently have will be restored.
To start with, you should just verify that after making some changes to the select boxes, you can reload the window and then see that those same values are restored.
After that works, you'll want to verify that the business logic that occurs when a user selects a deployment (and then we automatically select the configuration last used for the deployment or to setup the pre-deployment, along with then making sure the account selected matches the deployment URL - either by validating the currently selected one or by switching to the first in the filtered list), is not being used to initially set the values upon reload.
To do this:
There are also some edge conditions in which changes of available selection options are taken into account. For example, if a user selects a particular configuration, closes that workspace or VSCode itself, and then removes the configuration file they had selected physically from the filesystem, the initialization process is smart enough to simply fall back to business rules. However, it should be mentioned that we have an outstanding issues which need to handle when there are no longer configurations or when there are no matching credentials available that could be used with a deployment (#1280), so please do not expect that those conditions are handled yet as part of this PR.
There are a good number of combinations here, but by going through these a few times, you can pretty much validate that the implementation matches the intentions.
If you have any question of results, please reach out. For the most part, the validation of this PR is to make sure the values last used is restored ignoring those business rules, and the actual business rule validation is part of a different PR already merged.
Checklist