Correctly announce loading state for arc cluster context loading (#15747)

* Correctly announce loading state for arc cluster context loading

* localize

* Fix compile

* Fix test
This commit is contained in:
Charles Gagnon
2021-06-17 10:28:12 -07:00
committed by GitHub
parent 7c3a7e2646
commit cae598d36c
6 changed files with 32 additions and 12 deletions

View File

@@ -191,7 +191,7 @@ export const noPodIssuesDetected = localize('arc.noPodIssuesDetected', "There ar
export const podIssuesDetected = localize('arc.podIssuesDetected', "The pods listed below are experiencing issues that may affect performance or availability.");
export const containerReady = localize('arc.containerReady', "Pod containers are ready.");
export const podScheduled = localize('arc.podScheduled', "Pod is schedulable.");
export const loadingClusterContextCompleted = localize('arc.loadingClusterContextCompleted', "Loading cluster contexts completed");
export function rangeSetting(min: string, max: string): string { return localize('arc.rangeSetting', "Value is expected to be in the range {0} - {1}", min, max); }
export function databaseCreated(name: string): string { return localize('arc.databaseCreated', "Database {0} created", name); }
export function deletingInstance(name: string): string { return localize('arc.deletingInstance', "Deleting instance '{0}'...", name); }
@@ -262,3 +262,5 @@ export const noCurrentContextFound = (configFile: string) => localize('noCurrent
export const noNameInContext = (configFile: string) => localize('noNameInContext', "No name field was found in a cluster context in the config file: {0}", configFile);
export const userCancelledError = localize('arc.userCancelledError', "User cancelled the dialog");
export const clusterContextConfigNoLongerValid = (configFile: string, clusterContext: string, error: any) => localize('clusterContextConfigNoLongerValid', "The cluster context information specified by config file: {0} and cluster context: {1} is no longer valid. Error is:\n\t{2}\n Do you want to update this information?", configFile, clusterContext, getErrorMessage(error));
export const invalidConfigPath = localize('arc.invalidConfigPath', "Invalid config path");
export const loadingClusterContextsError = (error: any): string => localize('arc.loadingClusterContextsError', "Error loading cluster contexts. {0}", getErrorMessage(error));

View File

@@ -18,7 +18,7 @@ const newFileUri = vscode.Uri.file(path.join('path', 'to', 'new', '.kube', 'conf
describe('filePicker', function (): void {
beforeEach(async () => {
const { modelBuilderMock } = createModelViewMock();
filePicker = new FilePicker(modelBuilderMock.object, initialPath, (_disposable) => { }, '');
filePicker = new FilePicker(modelBuilderMock.object, initialPath, (_disposable) => { }, '', '');
});
afterEach(() => {

View File

@@ -5,10 +5,10 @@
import * as azdata from 'azdata';
import * as should from 'should';
import { getErrorMessage } from '../../../common/utils';
import { RadioOptionsGroup, RadioOptionsInfo } from '../../../ui/components/radioOptionsGroup';
import { createModelViewMock } from '@microsoft/azdata-test/out/mocks/modelView/modelViewMock';
import { StubRadioButton } from '@microsoft/azdata-test/out/stubs/modelView/stubRadioButton';
import * as loc from '../../../localizedConstants';
const loadingError = new Error('Error loading options');
@@ -25,7 +25,7 @@ let radioOptionsGroup: RadioOptionsGroup;
describe('radioOptionsGroup', function (): void {
beforeEach(async () => {
const { modelBuilderMock } = createModelViewMock();
radioOptionsGroup = new RadioOptionsGroup(modelBuilderMock.object, (_disposable) => { });
radioOptionsGroup = new RadioOptionsGroup(modelBuilderMock.object, (_disposable) => { }, undefined, '', () => '');
await radioOptionsGroup.load(async () => radioOptionsInfo);
});
@@ -51,7 +51,7 @@ describe('radioOptionsGroup', function (): void {
radioOptionsGroup.items.length.should.equal(1, 'There is should be only one element in the divContainer when loading error happens');
const label = radioOptionsGroup.items[0] as azdata.TextComponent;
should(label.value).not.be.undefined();
label.value!.should.deepEqual(getErrorMessage(loadingError));
label.value!.should.deepEqual(loc.loadingClusterContextsError(loadingError));
should(label.CSSStyles).not.be.undefined();
should(label.CSSStyles!.color).not.be.undefined();
label.CSSStyles!.color.should.equal('Red');

View File

@@ -6,7 +6,7 @@ import * as azdata from 'azdata';
import * as path from 'path';
import * as vscode from 'vscode';
import * as loc from '../../localizedConstants';
import { promises as fs } from 'fs';
export interface RadioOptionsInfo {
values?: string[],
defaultValue: string
@@ -20,14 +20,24 @@ export class FilePicker {
modelBuilder: azdata.ModelBuilder,
initialPath: string,
onNewDisposableCreated: (disposable: vscode.Disposable) => void,
ariaLabel: string
ariaLabel: string,
validationErrorMessage: string
) {
const buttonWidth = 80;
this.filePathInputBox = modelBuilder.inputBox()
.withProperties<azdata.InputBoxProperties>({
value: initialPath,
ariaLabel: ariaLabel,
validationErrorMessage: validationErrorMessage,
width: 350
}).withValidation(async () => {
try {
await fs.stat(this.filePathInputBox.value || '');
} catch (err) {
console.log('Error checking config path ', err);
return false;
}
return true;
}).component();
this.filePickerButton = modelBuilder.button()

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { getErrorMessage } from '../../common/utils';
import * as loc from '../../localizedConstants';
export interface RadioOptionsInfo {
values?: string[],
@@ -20,7 +20,12 @@ export class RadioOptionsGroup {
private _onRadioOptionChanged: vscode.EventEmitter<string | undefined> = new vscode.EventEmitter<string | undefined>();
public onRadioOptionChanged: vscode.Event<string | undefined> = this._onRadioOptionChanged.event;
constructor(private _modelBuilder: azdata.ModelBuilder, private _onNewDisposableCreated: (disposable: vscode.Disposable) => void, private _groupName: string = `RadioOptionsGroup${RadioOptionsGroup.id++}`) {
constructor(private _modelBuilder: azdata.ModelBuilder,
private _onNewDisposableCreated: (disposable: vscode.Disposable) => void,
private _groupName: string = `RadioOptionsGroup${RadioOptionsGroup.id++}`,
private _loadingCompleteMessage: string,
private _loadingCompleteErrorMessage: (error: any) => string
) {
this._divContainer = this._modelBuilder.divContainer().withProperties<azdata.DivContainerProperties>({ clickable: false }).component();
this._loadingBuilder = this._modelBuilder.loadingComponent().withItem(this._divContainer);
}
@@ -59,10 +64,12 @@ export class RadioOptionsGroup {
}));
this._divContainer.addItem(radioOption);
});
this.component().loadingCompletedText = this._loadingCompleteMessage;
}
catch (e) {
const errorLabel = this._modelBuilder.text().withProperties({ value: getErrorMessage(e), CSSStyles: { 'color': 'Red' } }).component();
const errorLabel = this._modelBuilder.text().withProperties({ value: loc.loadingClusterContextsError(e), CSSStyles: { 'color': 'Red' } }).component();
this._divContainer.addItem(errorLabel);
this.component().loadingCompletedText = this._loadingCompleteErrorMessage(e);
}
this.component().loading = false;
}

View File

@@ -97,13 +97,14 @@ abstract class ControllerDialogBase extends InitializingComponent {
this.modelBuilder,
controllerInfo?.kubeConfigFilePath || getDefaultKubeConfigPath(),
(disposable) => this._toDispose.push(disposable),
loc.controllerKubeConfig
loc.controllerKubeConfig,
loc.invalidConfigPath
);
this.modelBuilder.inputBox()
.withProps({
value: controllerInfo?.kubeConfigFilePath || getDefaultKubeConfigPath()
}).component();
this.clusterContextRadioGroup = new RadioOptionsGroup(this.modelBuilder, (disposable) => this._toDispose.push(disposable));
this.clusterContextRadioGroup = new RadioOptionsGroup(this.modelBuilder, (disposable) => this._toDispose.push(disposable), undefined, loc.loadingClusterContextCompleted, loc.loadingClusterContextsError);
this.loadRadioGroup(controllerInfo?.kubeClusterContext);
this._toDispose.push(this.clusterContextRadioGroup.onRadioOptionChanged(newContext => this.updateNamespace(newContext)));
this._toDispose.push(this.kubeConfigInputBox.onTextChanged(() => this.loadRadioGroup(controllerInfo?.kubeClusterContext)));