Skip to content
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

Convert che-server workspaces into devworkspaces #441

Merged
merged 20 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2d00f2a
refactor: rename convertWorkspace => constructWorkspace
akurinnoy Dec 24, 2021
0e36f47
feat: mark che-workspaces as deprecated
akurinnoy Dec 28, 2021
9beb3f3
feat: kebab menu actions for deprecated workspaces
akurinnoy Jan 5, 2022
a50a923
feat: actions dropdown actions for deprecated workspace
akurinnoy Jan 5, 2022
357f060
feat: devfile editor in readonly mode for deprecated workspaces
akurinnoy Jan 5, 2022
d051f17
feat: old workspaces conversion action
akurinnoy Jan 11, 2022
cc4d9ae
feat: on conversion's done, redirect to new workspace page
akurinnoy Jan 13, 2022
b9a78b6
feat: add link to the original workspace page
akurinnoy Jan 14, 2022
1459cf4
refact: move conversion functionality into WorkspaceConversionButton …
akurinnoy Jan 17, 2022
49616b1
fix: number of workspaces in the navbar
akurinnoy Jan 18, 2022
6b707bd
feat: show warning with migration instruction
akurinnoy Jan 19, 2022
22201bb
fix(workspace page): hide devfile editor buttons in readonly mode
akurinnoy Jan 19, 2022
c5eb70a
code cleanup
akurinnoy Jan 20, 2022
4b2250e
chore: bump *-devworkspace-handler versions
akurinnoy Jan 20, 2022
9e95eb8
fix: 'Show Original Devfile' path
akurinnoy Jan 20, 2022
d7a3e30
fix: progress-indicator componen
akurinnoy Jan 24, 2022
bcb430a
refact: Conversion button
akurinnoy Jan 24, 2022
aa846b4
refact: extract WorkspaceInlineAlerts component
akurinnoy Jan 24, 2022
4c435f9
chore: updated dependencies list
akurinnoy Jan 25, 2022
1651f28
test: filter workspaces
akurinnoy Jan 25, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .deps/EXCLUDED/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ This file contains a manual contribution to .deps/dev.md and it's needed because
| Packages | Resolved CQs |
| --- | --- |
| `keycloak-js@10.0.2` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/keycloak-js/10.0.2) |
| `x-is-string@0.1.0` | [CQ22418](https://dev.eclipse.org/ipzilla/show_bug.cgi?id=22418) |
| `postcss-syntax@0.36.2` | [CQ22418](https://dev.eclipse.org/ipzilla/show_bug.cgi?id=22418) |
| `x-is-string@0.1.0` | [CQ22418](https://dev.eclipse.org/ipzilla/show_bug.cgi?id=22418) |
2 changes: 1 addition & 1 deletion .deps/EXCLUDED/prod.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This file lists dependencies that do not need CQs or auto-detection does not wor
| `@eclipse-che/common@7.43.0-next` | N/A |
| `@eclipse-che/dashboard-backend@7.43.0-next` | N/A |
| `@eclipse-che/dashboard-frontend@7.43.0-next` | N/A |
| `fastify-swagger@4.11.0` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/fastify-swagger/4.11.0) |
| `fsevents@2.3.2` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/fsevents/2.3.2) |
| `jsdom@16.7.0` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/jsdom/16.7.0) |
| `node-notifier@8.0.2` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/node-notifier/8.0.2) |
| `fastify-swagger@4.11.0` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/fastify-swagger/4.11.0) |
6 changes: 3 additions & 3 deletions .deps/prod.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
| [`@babel/runtime@7.15.4`](https://github.com/babel/babel.git) | MIT | clearlydefined |
| [`@devfile/api@2.2.0-alpha-1633545768`](https://github.com/devfile/api.git) | EPL-2.0 | clearlydefined |
| `@eclipse-che/api@7.36.0` | EPL-2.0 | clearlydefined |
| [`@eclipse-che/che-code-devworkspace-handler@1.64.0-dev-7ba5d3e`](git+https://github.com/che-incubator/che-code.git) | EPL-2.0 | clearlydefined |
| [`@eclipse-che/che-theia-devworkspace-handler@0.0.1-1639587602`](git+https://github.com/eclipse-che/che-theia.git) | EPL-2.0 | clearlydefined |
| [`@eclipse-che/che-code-devworkspace-handler@1.64.0-dev-210b722`](git+https://github.com/che-incubator/che-code.git) | EPL-2.0 | clearlydefined |
| [`@eclipse-che/che-theia-devworkspace-handler@0.0.1-1642670698`](git+https://github.com/eclipse-che/che-theia.git) | EPL-2.0 | clearlydefined |
| [`@eclipse-che/common@7.43.0-next`](https://github.com/eclipse-che/che-dashboard) | EPL-2.0 | N/A |
| [`@eclipse-che/dashboard-backend@7.43.0-next`](https://github.com/eclipse-che/che-dashboard) | EPL-2.0 | N/A |
| [`@eclipse-che/dashboard-frontend@7.43.0-next`](git://github.com/eclipse/che-dashboard.git) | EPL-2.0 | N/A |
| [`@eclipse-che/devfile-converter@0.0.1-437a239`](git+https://github.com/che-incubator/devfile-converter.git) | EPL-2.0 | clearlydefined |
| [`@eclipse-che/devfile-converter@0.0.1-14c62ee`](git+https://github.com/che-incubator/devfile-converter.git) | EPL-2.0 | clearlydefined |
| [`@eclipse-che/workspace-client@0.0.1-1632305737`](https://github.com/eclipse/che-workspace-client) | EPL-2.0 | clearlydefined |
| [`@fastify/ajv-compiler@1.1.0`](git+https://github.com/fastify/ajv-compiler.git) | MIT | clearlydefined |
| [`@hapi/address@2.1.4`](git://github.com/hapijs/address) | BSD-3-Clause | clearlydefined |
Expand Down
4 changes: 2 additions & 2 deletions packages/dashboard-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
"test:watch": "yarn test --watch"
},
"dependencies": {
"@eclipse-che/che-code-devworkspace-handler": "1.64.0-dev-7ba5d3e",
"@eclipse-che/che-theia-devworkspace-handler": "0.0.1-1639587602",
"@eclipse-che/che-code-devworkspace-handler": "1.64.0-dev-210b722",
"@eclipse-che/che-theia-devworkspace-handler": "0.0.1-1642670698",
"@eclipse-che/devfile-converter": "0.0.1-14c62ee",
"@eclipse-che/workspace-client": "0.0.1-1632305737",
"@patternfly/react-core": "4.120.0",
Expand Down
13 changes: 10 additions & 3 deletions packages/dashboard-frontend/src/Layout/Navigation/MainList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,22 @@ import { NavigationItemObject } from '.';
import { ROUTE } from '../../route.enum';
import { AppState } from '../../store';
import { connect, ConnectedProps } from 'react-redux';
import { selectAllWorkspacesNumber } from '../../store/Workspaces/selectors';
import { selectAllWorkspaces } from '../../store/Workspaces/selectors';

type Props = MappedProps & {
activePath: string;
};

export class NavigationMainList extends React.PureComponent<Props> {
private get items(): NavigationItemObject[] {
const { allWorkspacesNumber } = this.props;
const { allWorkspaces } = this.props;

const allWorkspacesNumber = allWorkspaces.filter(workspace => {
if (workspace.isDevWorkspace) {
return true;
}
return (workspace.ref as che.Workspace).attributes?.converted === undefined;
akurinnoy marked this conversation as resolved.
Show resolved Hide resolved
}).length;

return [
{ to: ROUTE.GET_STARTED, label: 'Create Workspace' },
Expand All @@ -45,7 +52,7 @@ export class NavigationMainList extends React.PureComponent<Props> {
}

const mapStateToProps = (state: AppState) => ({
allWorkspacesNumber: selectAllWorkspacesNumber(state),
allWorkspaces: selectAllWorkspaces(state),
});

const connector = connect(mapStateToProps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,7 @@ class NavigationItemWorkspaceActions extends React.PureComponent<Props, State> {
createAction(WorkspaceAction.START_DEBUG_AND_OPEN_LOGS),
createAction(WorkspaceAction.START_IN_BACKGROUND),
);
} else if (
status !== WorkspaceStatus.STOPPING &&
status !== DevWorkspaceStatus.TERMINATING &&
status !== DevWorkspaceStatus.FAILED
) {
} else if (status !== WorkspaceStatus.STOPPING && status !== DevWorkspaceStatus.TERMINATING) {
dropdownItems.push(createAction(WorkspaceAction.STOP_WORKSPACE));
}
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,29 @@
*/

import React from 'react';
import { render, screen } from '@testing-library/react';
import { render, RenderResult, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import { Nav } from '@patternfly/react-core';

import NavigationMainList from '../MainList';
import { FakeStoreBuilder } from '../../../store/__mocks__/storeBuilder';
import { Provider } from 'react-redux';
import { createFakeCheWorkspace } from '../../../store/__mocks__/workspace';
import { DevWorkspaceBuilder } from '../../../store/__mocks__/devWorkspaceBuilder';
import { Store } from 'redux';
import { CheWorkspaceBuilder } from '../../../store/__mocks__/cheWorkspaceBuilder';

describe('Navigation Main List', () => {
it('should have correct number of main navigation items', () => {
render(buildElement());
const store = new FakeStoreBuilder().build();
renderComponent(store);

const navLinks = screen.getAllByRole('link');
expect(navLinks.length).toEqual(2);
});

it('should have correct navigation item labels', () => {
render(buildElement());
const store = new FakeStoreBuilder().build();
renderComponent(store);

const navLinks = screen.getAllByRole('link');

Expand All @@ -38,20 +42,63 @@ describe('Navigation Main List', () => {
});

it('should have correct navigation item workspaces quantity', () => {
let workspaces = [0, 1, 2, 3, 4].map(i => createFakeCheWorkspace('works-' + i, 'works-' + i));
const { rerender } = render(buildElement(workspaces));
let workspaces = [0, 1, 2, 3, 4].map(i =>
new DevWorkspaceBuilder()
.withId('wksp-' + i)
.withName('wksp-' + i)
.build(),
);
let store = new FakeStoreBuilder().withDevWorkspaces({ workspaces }).build();
const { rerender } = renderComponent(store);

expect(screen.queryByRole('link', { name: 'Workspaces (5)' })).toBeInTheDocument();

workspaces = [0, 1, 2].map(i => createFakeCheWorkspace('works-' + i, 'works-' + i));
rerender(buildElement(workspaces));
workspaces = [0, 1, 2].map(i =>
new DevWorkspaceBuilder()
.withId('wksp-' + i)
.withName('wksp-' + i)
.build(),
);
store = new FakeStoreBuilder().withDevWorkspaces({ workspaces }).build();
rerender(buildElement(store));

expect(screen.queryByRole('link', { name: 'Workspaces (3)' })).toBeInTheDocument();
});

describe('with deprecated workspaces', () => {
it('should count all workspaces but converted', () => {
const cheworkspaces = [
new CheWorkspaceBuilder().withId('wksp-1').withName('wksp-1').build(),
new CheWorkspaceBuilder()
.withId('wksp-2')
.withName('wksp-2')
.withAttributes({
converted: new Date().toISOString(),
} as che.WorkspaceAttributes)
.build(),
];
const devworkspaces = [0, 1].map(i =>
new DevWorkspaceBuilder()
.withId('devwksp-' + i)
.withName('wksp-' + i)
.build(),
);
const store = new FakeStoreBuilder()
.withCheWorkspaces({ workspaces: cheworkspaces })
.withDevWorkspaces({ workspaces: devworkspaces })
.build();
renderComponent(store);

expect(screen.queryByRole('link', { name: 'Workspaces (3)' })).toBeInTheDocument();
});
});
});

function buildElement(workspaces: che.Workspace[] = []): JSX.Element {
const store = new FakeStoreBuilder().withCheWorkspaces({ workspaces }).build();
function renderComponent(store: Store): RenderResult {
return render(buildElement(store));
}

function buildElement(store: Store): React.ReactElement {
return (
<Provider store={store}>
<MemoryRouter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jest.mock('../../../components/Workspace/Indicator', () => {

describe('Navigation Item', () => {
const item: NavigationRecentItemObject = {
status: '',
status: WorkspaceStatus.STOPPED,
label: 'workspace',
to: '/namespace/workspace',
isDevWorkspace: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,31 @@ import { RenderResult, render, screen } from '@testing-library/react';
import { Store } from 'redux';

import NavigationRecentList from '../RecentList';
import { convertWorkspace, Workspace } from '../../../services/workspace-adapter';
import { constructWorkspace, Workspace } from '../../../services/workspace-adapter';
import { FakeStoreBuilder } from '../../../store/__mocks__/storeBuilder';
import { createHashHistory } from 'history';
import { createFakeCheWorkspace } from '../../../store/__mocks__/workspace';
import { CheWorkspaceBuilder } from '../../../store/__mocks__/cheWorkspaceBuilder';

jest.mock('react-tooltip', () => {
return function DummyTooltip(): React.ReactElement {
return <div>Dummy Tooltip</div>;
};
});

const cheWorkspaces = [1, 2, 3].map(i => createFakeCheWorkspace('wksp-' + i, 'wksp-' + i));
const workspaces = cheWorkspaces.map(workspace => convertWorkspace(workspace));
let cheWorkspaces: che.Workspace[];
let workspaces: Workspace[];

describe('Navigation Recent List', () => {
beforeEach(() => {
cheWorkspaces = [1, 2, 3].map(i =>
new CheWorkspaceBuilder()
.withId('wksp-' + i)
.withName('wksp-' + i)
.build(),
);
workspaces = cheWorkspaces.map(workspace => constructWorkspace(workspace));
});

function renderComponent(store: Store, workspaces: Workspace[]): RenderResult {
const history = createHashHistory();
return render(
Expand Down
11 changes: 7 additions & 4 deletions packages/dashboard-frontend/src/Layout/Navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ import {
buildWorkspacesLocation,
sanitizeLocation,
} from '../../services/helpers/location';
import {
DeprecatedWorkspaceStatus,
DevWorkspaceStatus,
WorkspaceStatus,
} from '../../services/helpers/types';

export interface NavigationItemObject {
to: string;
Expand All @@ -36,7 +41,7 @@ export interface NavigationItemObject {
export interface NavigationRecentItemObject {
to: string;
label: string;
status: string;
status: WorkspaceStatus | DevWorkspaceStatus | DeprecatedWorkspaceStatus;
workspaceId: string;
isDevWorkspace: boolean;
}
Expand Down Expand Up @@ -111,8 +116,6 @@ export class Navigation extends React.PureComponent<Props, State> {
const { theme, recentWorkspaces, history } = this.props;
const { activeLocation } = this.state;

const recent = recentWorkspaces || [];

return (
<Nav
aria-label="Navigation"
Expand All @@ -121,7 +124,7 @@ export class Navigation extends React.PureComponent<Props, State> {
>
<NavigationMainList activePath={activeLocation.pathname} />
<NavigationRecentList
workspaces={recent}
workspaces={recentWorkspaces}
activePath={activeLocation.pathname}
history={history}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
buildWorkspacesLocation,
} from '../../services/helpers/location';
import { IdeLoaderTab, WorkspaceDetailsTab } from '../../services/helpers/types';
import { convertWorkspace, Workspace } from '../../services/workspace-adapter';
import { constructWorkspace, Workspace } from '../../services/workspace-adapter';
import { CheWorkspaceBuilder } from '../../store/__mocks__/cheWorkspaceBuilder';

jest.mock('../../pages/GetStarted', () => {
Expand Down Expand Up @@ -140,7 +140,7 @@ describe('Routes', () => {
let workspace: Workspace;

beforeEach(() => {
workspace = convertWorkspace(new CheWorkspaceBuilder().withNamespace('namespace').build());
workspace = constructWorkspace(new CheWorkspaceBuilder().withNamespace('namespace').build());
});

it('should handle "/workspace/namespace/name"', async () => {
Expand Down Expand Up @@ -184,7 +184,7 @@ describe('Routes', () => {
let workspace: Workspace;

beforeEach(() => {
workspace = convertWorkspace(new CheWorkspaceBuilder().withNamespace('namespace').build());
workspace = constructWorkspace(new CheWorkspaceBuilder().withNamespace('namespace').build());
});

it('should handle "/ide/namespace/name"', async () => {
Expand Down
15 changes: 9 additions & 6 deletions packages/dashboard-frontend/src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ import {
TextVariants,
} from '@patternfly/react-core';
import WorkspaceStatusLabel from '../WorkspaceStatusLabel';
import {
DeprecatedWorkspaceStatus,
DevWorkspaceStatus,
WorkspaceStatus,
} from '../../services/helpers/types';

const SECTION_THEME = PageSectionVariants.light;

type Props = {
status?: string;
status: WorkspaceStatus | DevWorkspaceStatus | DeprecatedWorkspaceStatus;
title: string;
};

Expand All @@ -41,11 +46,9 @@ class Header extends React.PureComponent<Props> {
<Text component={TextVariants.h1}>{title}</Text>
</TextContent>
</FlexItem>
{status && (
<FlexItem>
<WorkspaceStatusLabel status={status} />
</FlexItem>
)}
<FlexItem>
<WorkspaceStatusLabel status={status} />
</FlexItem>
</Flex>
</PageSection>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ exports[`Progress component should render progress with loading correctly 1`] =
<span>
<div
className="pf-c-progress pf-m-sm pf-m-singleline"
id="che-progress-ind"
id="progress-indicator"
>
<div
aria-hidden="true"
className="pf-c-progress__description"
id="che-progress-ind-description"
id="progress-indicator-description"
onMouseEnter={null}
>

Expand All @@ -19,6 +19,7 @@ exports[`Progress component should render progress with loading correctly 1`] =
className="pf-c-progress__status"
/>
<div
aria-label="Action is in progress"
aria-valuemax={100}
aria-valuemin={0}
aria-valuenow={0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type State = {
progressVal: number;
};

class CheProgress extends React.PureComponent<Props, State> {
class ProgressIndicator extends React.PureComponent<Props, State> {
private intervalId: any;
private readonly onProgressInc: () => void;

Expand Down Expand Up @@ -78,10 +78,11 @@ class CheProgress extends React.PureComponent<Props, State> {
<span className={styles.progressLine}>
{this.props.isLoading || this.state.progressVal !== 0 ? (
<Progress
id="che-progress-ind"
id="progress-indicator"
value={progressVal}
size={ProgressSize.sm}
measureLocation={ProgressMeasureLocation.none}
aria-label="Action is in progress"
/>
) : (
''
Expand All @@ -91,4 +92,4 @@ class CheProgress extends React.PureComponent<Props, State> {
}
}

export default CheProgress;
export default ProgressIndicator;
Loading