fix(ui-mode): display no projects error if bad config provided
This commit is contained in:
parent
25ef2f1344
commit
8b65df39d4
38
packages/trace-viewer/src/ui/shared/fullscreenModal.tsx
Normal file
38
packages/trace-viewer/src/ui/shared/fullscreenModal.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import './fullscreenModel.css';
|
||||||
|
|
||||||
|
export interface FullscreenModalProps {
|
||||||
|
onClose?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FullscreenModal: React.FC<
|
||||||
|
React.PropsWithChildren<FullscreenModalProps>
|
||||||
|
> = ({ onClose, children }) => {
|
||||||
|
const ref = React.useRef<HTMLDialogElement>(null);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
ref.current?.showModal();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<dialog ref={ref} className='fullscreen-modal'>
|
||||||
|
<div className='fullscreen-modal-content'>{children}</div>
|
||||||
|
</dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
29
packages/trace-viewer/src/ui/shared/fullscreenModel.css
Normal file
29
packages/trace-viewer/src/ui/shared/fullscreenModel.css
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.fullscreen-modal {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fullscreen-modal-content {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fullscreen-modal::backdrop {
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,7 @@ import { TestListView } from './uiModeTestListView';
|
||||||
import { TraceView } from './uiModeTraceView';
|
import { TraceView } from './uiModeTraceView';
|
||||||
import { SettingsView } from './settingsView';
|
import { SettingsView } from './settingsView';
|
||||||
import { DefaultSettingsView } from './defaultSettingsView';
|
import { DefaultSettingsView } from './defaultSettingsView';
|
||||||
|
import { FullscreenModal } from './shared/fullscreenModal';
|
||||||
|
|
||||||
let xtermSize = { cols: 80, rows: 24 };
|
let xtermSize = { cols: 80, rows: 24 };
|
||||||
const xtermDataSource: XtermDataSource = {
|
const xtermDataSource: XtermDataSource = {
|
||||||
|
|
@ -98,6 +99,7 @@ export const UIModeView: React.FC<{}> = ({
|
||||||
const [settingsVisible, setSettingsVisible] = React.useState(false);
|
const [settingsVisible, setSettingsVisible] = React.useState(false);
|
||||||
const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false);
|
const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false);
|
||||||
const [revealSource, setRevealSource] = React.useState(false);
|
const [revealSource, setRevealSource] = React.useState(false);
|
||||||
|
const [critcalError, setCriticalError] = React.useState<string | undefined>();
|
||||||
const onRevealSource = React.useCallback(() => setRevealSource(true), [setRevealSource]);
|
const onRevealSource = React.useCallback(() => setRevealSource(true), [setRevealSource]);
|
||||||
|
|
||||||
const showTestingOptions = false;
|
const showTestingOptions = false;
|
||||||
|
|
@ -114,6 +116,19 @@ export const UIModeView: React.FC<{}> = ({
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const configProjects = React.useMemo(() => {
|
||||||
|
if (!testModel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const { config } = testModel;
|
||||||
|
return config.configFile
|
||||||
|
? settings.getObject<string[] | undefined>(
|
||||||
|
config.configFile + ':projects',
|
||||||
|
undefined,
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
}, [testModel]);
|
||||||
|
|
||||||
// Load tests on startup.
|
// Load tests on startup.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
inputRef.current?.focus();
|
inputRef.current?.focus();
|
||||||
|
|
@ -214,8 +229,7 @@ export const UIModeView: React.FC<{}> = ({
|
||||||
if (!testModel)
|
if (!testModel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const { config, rootSuite } = testModel;
|
const { rootSuite } = testModel;
|
||||||
const selectedProjects = config.configFile ? settings.getObject<string[] | undefined>(config.configFile + ':projects', undefined) : undefined;
|
|
||||||
const newFilter = new Map(projectFilters);
|
const newFilter = new Map(projectFilters);
|
||||||
for (const projectName of newFilter.keys()) {
|
for (const projectName of newFilter.keys()) {
|
||||||
if (!rootSuite.suites.find(s => s.title === projectName))
|
if (!rootSuite.suites.find(s => s.title === projectName))
|
||||||
|
|
@ -223,13 +237,13 @@ export const UIModeView: React.FC<{}> = ({
|
||||||
}
|
}
|
||||||
for (const projectSuite of rootSuite.suites) {
|
for (const projectSuite of rootSuite.suites) {
|
||||||
if (!newFilter.has(projectSuite.title))
|
if (!newFilter.has(projectSuite.title))
|
||||||
newFilter.set(projectSuite.title, !!selectedProjects?.includes(projectSuite.title));
|
newFilter.set(projectSuite.title, !!configProjects?.includes(projectSuite.title));
|
||||||
}
|
}
|
||||||
if (!selectedProjects && newFilter.size && ![...newFilter.values()].includes(true))
|
if (!configProjects && newFilter.size && ![...newFilter.values()].includes(true))
|
||||||
newFilter.set(newFilter.entries().next().value![0], true);
|
newFilter.set(newFilter.entries().next().value![0], true);
|
||||||
if (projectFilters.size !== newFilter.size || [...projectFilters].some(([k, v]) => newFilter.get(k) !== v))
|
if (projectFilters.size !== newFilter.size || [...projectFilters].some(([k, v]) => newFilter.get(k) !== v))
|
||||||
setProjectFilters(newFilter);
|
setProjectFilters(newFilter);
|
||||||
}, [projectFilters, testModel]);
|
}, [projectFilters, configProjects, testModel]);
|
||||||
|
|
||||||
// Update progress.
|
// Update progress.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|
@ -239,6 +253,21 @@ export const UIModeView: React.FC<{}> = ({
|
||||||
setProgress(undefined);
|
setProgress(undefined);
|
||||||
}, [testModel, isRunningTest]);
|
}, [testModel, isRunningTest]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!testModel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (testModel.rootSuite.suites.length === 0) {
|
||||||
|
let prefix: string;
|
||||||
|
if (!configProjects || configProjects.length < 1)
|
||||||
|
prefix = 'No projects matched.';
|
||||||
|
else
|
||||||
|
prefix = `No projects matched. Available projects: ${configProjects.map(p => `"${p}"`).join(', ')}.`;
|
||||||
|
|
||||||
|
setCriticalError(`${prefix} Please check your configuration.`);
|
||||||
|
}
|
||||||
|
}, [testModel, configProjects]);
|
||||||
|
|
||||||
// Test tree is built from the model and filters.
|
// Test tree is built from the model and filters.
|
||||||
const { testTree } = React.useMemo(() => {
|
const { testTree } = React.useMemo(() => {
|
||||||
if (!testModel)
|
if (!testModel)
|
||||||
|
|
@ -398,6 +427,7 @@ export const UIModeView: React.FC<{}> = ({
|
||||||
}, [closeInstallDialog, testServerConnection]);
|
}, [closeInstallDialog, testServerConnection]);
|
||||||
|
|
||||||
return <div className='vbox ui-mode'>
|
return <div className='vbox ui-mode'>
|
||||||
|
{critcalError && <FullscreenModal>{critcalError}</FullscreenModal>}
|
||||||
{!hasBrowsers && <dialog ref={dialogRef}>
|
{!hasBrowsers && <dialog ref={dialogRef}>
|
||||||
<div className='title'><span className='codicon codicon-lightbulb'></span>Install browsers</div>
|
<div className='title'><span className='codicon codicon-lightbulb'></span>Install browsers</div>
|
||||||
<div className='body'>
|
<div className='body'>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue