Skip to content

Commit

Permalink
Add Editor Selector panel (#1055)
Browse files Browse the repository at this point in the history
* chore: refactor the Get Started page

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* feat: added Editor Selector component

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* chore: integrate Editor Selector with other components

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* feat: add editor definition form

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* fixup! feat: add editor definition form

* chore: rename editorId -> editorDefinition

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* feat: add doc link

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* fix: default editor and repo editor precedence

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* feat: selected card title is black

Signed-off-by: Oleksii Kurinnyi <[email protected]>

* fixup! feat: selected card title is black

---------

Signed-off-by: Oleksii Kurinnyi <[email protected]>
  • Loading branch information
akurinnoy authored Mar 6, 2024
1 parent 403df56 commit 49efdad
Show file tree
Hide file tree
Showing 85 changed files with 5,368 additions and 2,142 deletions.
8 changes: 4 additions & 4 deletions packages/dashboard-frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ module.exports = {
],
coverageThreshold: {
global: {
statements: 88,
branches: 85,
functions: 81,
lines: 88,
statements: 89,
branches: 86,
functions: 83,
lines: 89,
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class Navigation extends React.PureComponent<Props, State> {
if (activeLocation.pathname === ROUTE.HOME) {
const workspacesNumber = this.props.allWorkspaces.length;
if (workspacesNumber === 0) {
newLocation = buildGettingStartedLocation('quick-add');
newLocation = buildGettingStartedLocation();
} else {
newLocation = buildWorkspacesLocation();
}
Expand Down
19 changes: 5 additions & 14 deletions packages/dashboard-frontend/src/Routes/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import Routes from '..';

jest.mock('@/pages/GetStarted', () => {
return function GetStarted() {
return <span>Quick Add</span>;
return <span>Create Workspace</span>;
};
});
jest.mock('@/containers/WorkspacesList.tsx', () => {
Expand Down Expand Up @@ -62,30 +62,21 @@ describe('Routes', () => {
jest.clearAllMocks();
});

describe('Quick Add route', () => {
describe('Create Workspace route', () => {
it('should handle "/"', async () => {
const path = ROUTE.HOME;
render(getComponent(path));

await waitFor(() => expect(screen.queryByText('Quick Add')).toBeTruthy());
await waitFor(() => expect(screen.queryByText('Create Workspace')).toBeTruthy());

expect(screen.queryByTestId('fallback-spinner')).not.toBeInTheDocument();
});

it('should handle "/quick-add"', async () => {
it('should handle "/create-workspace"', async () => {
const location = buildGettingStartedLocation();
render(getComponent(location));

await waitFor(() => expect(screen.queryByText('Quick Add')).toBeTruthy());

expect(screen.queryByTestId('fallback-spinner')).not.toBeInTheDocument();
});

it('should handle "/create-workspace?tab=quick-add"', async () => {
const location = buildGettingStartedLocation('quick-add');
render(getComponent(location));

await waitFor(() => expect(screen.queryByText('Quick Add')).toBeTruthy());
await waitFor(() => expect(screen.queryByText('Create Workspace')).toBeTruthy());

expect(screen.queryByTestId('fallback-spinner')).not.toBeInTheDocument();
});
Expand Down
6 changes: 3 additions & 3 deletions packages/dashboard-frontend/src/Routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Redirect, Route, RouteComponentProps, Switch } from 'react-router';

import WorkspaceDetailsContainer from '@/containers/WorkspaceDetails';
import WorkspacesListContainer from '@/containers/WorkspacesList';
import CreateWorkspace from '@/pages/GetStarted';
import GetStarted from '@/pages/GetStarted';
import UserPreferences from '@/pages/UserPreferences';
import { buildFactoryLoaderPath } from '@/preload/main';
import { ROUTE } from '@/Routes/routes';
Expand All @@ -30,8 +30,8 @@ export interface RouteItem {
}

const items: RouteItem[] = [
{ to: ROUTE.GET_STARTED, component: CreateWorkspace },
{ to: ROUTE.HOME, component: CreateWorkspace },
{ to: ROUTE.GET_STARTED, component: GetStarted },
{ to: ROUTE.HOME, component: GetStarted },
{ to: ROUTE.WORKSPACES, component: WorkspacesListContainer },
{ to: ROUTE.WORKSPACE_DETAILS, component: WorkspaceDetailsContainer },
{ to: ROUTE.IDE_LOADER, component: LoaderContainer },
Expand Down
1 change: 0 additions & 1 deletion packages/dashboard-frontend/src/Routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
export enum ROUTE {
HOME = '/',
GET_STARTED = '/create-workspace',
GET_STARTED_TAB = '/create-workspace?tab=:tabId',
WORKSPACES = '/workspaces',
WORKSPACE_DETAILS = '/workspace/:namespace/:workspaceName',
WORKSPACE_DETAILS_TAB = '/workspace/:namespace/:workspaceName?tab=:tabId',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import React from 'react';

import { Props } from '@/components/EditorSelector/Definition/DefinitionField';

export class EditorDefinitionField extends React.PureComponent<Props> {
public render() {
const { onChange } = this.props;

return (
<div data-testid="editor-definition-field">
<button onClick={() => onChange('some/editor/id')}>Editor Definition Change</button>
Editor Definition Field
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EditorDefinitionField snapshot 1`] = `
<div
className="pf-c-form__group"
>
<div
className="pf-c-form__group-label"
>
<label
className="pf-c-form__label"
>
<span
className="pf-c-form__label-text"
>
Editor Definition
</span>
</label>
</div>
<div
className="pf-c-form__group-control"
>
<input
aria-invalid={false}
aria-label="Editor Definition"
className="pf-c-form-control"
data-ouia-component-id="OUIA-Generated-TextInputBase-1"
data-ouia-component-type="PF4/TextInput"
data-ouia-safe={true}
disabled={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder="Enter the link to a container editor definition URL or an editor id"
required={false}
type="text"
value=""
/>
<div
aria-live="polite"
className="pf-c-form__helper-text"
id="undefined-helper"
>
<span
className="pf-c-form__helper-text-icon"
>
<svg
aria-hidden={true}
aria-labelledby={null}
fill="currentColor"
height="1em"
role="img"
style={
{
"verticalAlign": "-0.125em",
}
}
viewBox="0 0 192 512"
width="1em"
>
<path
d="M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"
/>
</svg>
</span>
Default editor will be used if no definition is provided.
</div>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2018-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import userEvent from '@testing-library/user-event';
import React from 'react';

import { EditorDefinitionField } from '@/components/EditorSelector/Definition/DefinitionField';
import getComponentRenderer, { screen } from '@/services/__mocks__/getComponentRenderer';

const { createSnapshot, renderComponent } = getComponentRenderer(getComponent);

const mockOnChange = jest.fn();

describe('EditorDefinitionField', () => {
afterEach(() => {
jest.clearAllMocks();
});

test('snapshot', () => {
const snapshot = createSnapshot();
expect(snapshot.toJSON()).toMatchSnapshot();
});

test('helper text, definition change', () => {
renderComponent();

const helperText = 'Default editor will be used if no definition is provided.';

expect(screen.queryByText(helperText)).not.toBeNull();

const input = screen.getByRole('textbox');

const editorId = 'some/editor/id';
userEvent.paste(input, editorId);

expect(mockOnChange).toHaveBeenNthCalledWith(1, editorId);
expect(screen.queryByText(helperText)).toBeNull();

userEvent.clear(input);

expect(mockOnChange).toHaveBeenNthCalledWith(2, undefined);
expect(screen.queryByText(helperText)).not.toBeNull();
});
});

function getComponent() {
return <EditorDefinitionField onChange={mockOnChange} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import { FormGroup, TextInput } from '@patternfly/react-core';
import { InfoIcon } from '@patternfly/react-icons';
import React from 'react';

export type Props = {
onChange: (definition: string | undefined) => void;
};
export type State = {
definition: string;
};

export class EditorDefinitionField extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);

this.state = {
definition: '',
};
}

private handleChange(value: string) {
value = value.trim();
this.setState({ definition: value });
this.props.onChange(value !== '' ? value : undefined);
}

public render() {
const { definition } = this.state;

const helperText =
definition !== '' ? '' : 'Default editor will be used if no definition is provided.';

return (
<FormGroup label="Editor Definition" helperText={helperText} helperTextIcon={<InfoIcon />}>
<TextInput
aria-label="Editor Definition"
placeholder="Enter the link to a container editor definition URL or an editor id"
onChange={value => this.handleChange(value)}
value={definition}
/>
</FormGroup>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import React from 'react';

import { Props } from '@/components/EditorSelector/Definition/ImageField';

export class EditorImageField extends React.PureComponent<Props> {
public render() {
const { onChange } = this.props;

return (
<div data-testid="editor-image-field">
<button onClick={() => onChange('editor-image')}>Editor Image Change</button>
Editor Definition Field
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EditorDefinitionField snapshot 1`] = `
<div
className="pf-c-form__group"
>
<div
className="pf-c-form__group-label"
>
<label
className="pf-c-form__label"
>
<span
className="pf-c-form__label-text"
>
Editor Image
</span>
</label>
</div>
<div
className="pf-c-form__group-control"
>
<input
aria-invalid={false}
aria-label="Editor Image"
className="pf-c-form-control"
data-ouia-component-id="OUIA-Generated-TextInputBase-1"
data-ouia-component-type="PF4/TextInput"
data-ouia-safe={true}
disabled={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder="Enter an editor container image"
required={false}
type="text"
value=""
/>
</div>
</div>
`;
Loading

0 comments on commit 49efdad

Please sign in to comment.