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

Spec page #79

Open
wants to merge 11 commits into
base: development
Choose a base branch
from
4 changes: 3 additions & 1 deletion packages/frontend-dist/src/view/DeleteSpecModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ export class DeleteSpecModal extends Component<RouteComponentProps<{ specId: str
};

private closeModalOnDelete = () => {
this.props.history.push(goUpUrl(this.props.match.url, 2));
this.props.history.push(
goUpUrl(this.props.match.url.replace('specs', 'overview'), 2),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work? Why use replace instead of appending overview to the end of the base URL?
What if we're closing the modal from a page other than the overview pages - Won't it go to the overview page instead of the original page?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it’s delete - if we’re deleting the entire spec we can’t stay on the spec page, because there’ll be nothing there.
Juat dismissing the modal without deleting won’t go to overview.

Copy link
Collaborator

@PatrickShaw PatrickShaw Oct 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just do this.props.history.push(goUpUrl(this.props.match.url, 3) + '/overview')?
The problem with the way you've got it at the moment is that if you have a base url that has "specs" in it, say, openapi.specsavers.com/specs/1/delete you'll end up with openapi.overviewavers/overview.

);
};

private closeErrorModal = () => {
Expand Down
46 changes: 3 additions & 43 deletions packages/frontend-dist/src/view/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import React, { Component, ReactNode } from 'react';
import { RouteComponentProps } from 'react-router';
import { Route } from 'react-router-dom';

import { Id, HasId, Spec, SdkConfig } from '@openapi-platform/model';
import { Id } from '@openapi-platform/model';
import { state } from '../state/SpecState';
import { AddSdkConfigModal } from './AddSdkConfigModal';
import { AddSpecModal } from './AddSpecModal';
import { ContentContainer } from './basic/ContentContainer';
import { SimpleToolbar } from './basic/SimpleToolbar';
import { SpecList } from './basic/SpecList';
import { DeleteSpecModal } from './DeleteSpecModal';

/**
* An overview of the current state of Swagger Platform.
Expand All @@ -21,18 +19,9 @@ import { DeleteSpecModal } from './DeleteSpecModal';
export class Overview extends Component<RouteComponentProps<{}>, {}> {
private onSearch = event => {};
private openAddSpecModal = () => this.props.history.push(`${this.props.match.url}/add`);
private openEditSpecModal = (spec: HasId<Spec>) =>
this.props.history.push(`${this.props.match.url}/${spec.id}/edit`);
private openDeleteSpecModal = (spec: HasId<Spec>) =>
this.props.history.push(`${this.props.match.url}/${spec.id}/delete`);
private openAddSdkConfigModal = (spec: HasId<Spec>) =>
this.props.history.push(`${this.props.match.url}/${spec.id}/sdk-configs/add`);
private onEditSdkConfigModal = (sdkConfig: HasId<SdkConfig>) =>
this.props.history.push(
`${this.props.match.url}/${sdkConfig.specId}/sdk-configs/${sdkConfig.id}/edit`,
);
private expandSpec = (id: Id | null) =>
this.props.history.push(`${this.props.match.url}${id === null ? '' : '/' + id}`);
private onSpecOpen = (id: Id | null) => this.props.history.push(`/specs/${id}`);
hferrier marked this conversation as resolved.
Show resolved Hide resolved

private renderSpecList: (
props: RouteComponentProps<{ specId?: string }>,
Expand All @@ -46,14 +35,7 @@ export class Overview extends Component<RouteComponentProps<{}>, {}> {
}
// Expands/collapses a Spec
onSpecExpanded={this.expandSpec}
// Open a modal to edit the current spec
onEditSpec={this.openEditSpecModal}
// Open a model to delete the current spec
onDeleteSpec={this.openDeleteSpecModal}
// Open a modal to add an SDK configuration when the 'Add SDK Configuration' button is
// clicked
onAddSdkConfig={this.openAddSdkConfigModal}
onEditSdkConfig={this.onEditSdkConfigModal}
onSpecOpen={this.onSpecOpen}
/>
)}
</Observer>
Expand Down Expand Up @@ -84,28 +66,6 @@ export class Overview extends Component<RouteComponentProps<{}>, {}> {
path={`${this.props.match.url}/add`}
component={AddSpecModal}
/>
<Route
exact
path={`${this.props.match.url}/:specId(\\d+)/edit`}
component={AddSpecModal}
/>
<Route
exact
path={`${this.props.match.url}/:specId(\\d+)/delete`}
component={DeleteSpecModal}
/>
<Route
exact
path={`${this.props.match.url}/:specId(\\d+)/sdk-configs/add`}
component={AddSdkConfigModal}
/>
<Route
exact
path={`${
this.props.match.url
}/:specId(\\d+)/sdk-configs/:sdkConfigId(\\d+)/edit`}
component={AddSdkConfigModal}
/>
</ContentContainer>
</>
)}
Expand Down
15 changes: 15 additions & 0 deletions packages/frontend-dist/src/view/Page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { ComponentType } from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';

import { AddSdkConfigModal } from './AddSdkConfigModal';
import { AddSpecModal } from './AddSpecModal';
import { NotFound } from './basic/NotFound';
import { createStyled } from './createStyled';
import { DeleteSpecModal } from './DeleteSpecModal';
import { NavigationMenu } from './NavigationMenu';
import { Overview } from './Overview';
import { ProfileViewer } from './ProfileViewer';
Expand Down Expand Up @@ -50,6 +53,18 @@ export const Page: ComponentType<{}> = () => (
<Route path="/settings" component={SettingsViewer} />
<Route component={NotFound} />
</Switch>
<Route exact path="/specs/:specId/edit" component={AddSpecModal} />
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realise this is kind of messy, but these routes no longer work in the Overview component since they're all triggered from the /specs/... route now, and I couldn't get these Route components to work inside SpecViewer since I couldn't extract the specId match prop, since it's part of the match in Page.
I probably just don't understand Routes well enough though, let me know if there's a cleaner way to do this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried doing something like <Route path={`${match.path}/edit`} component={AddSpecModal}/> inside SpecViewer? This should let you access match.params.id inside AddSpecModal.

<Route exact path="/specs/:specId/delete" component={DeleteSpecModal} />
<Route
exact
path="/specs/:specId/sdk-configs/add"
component={AddSdkConfigModal}
/>
<Route
exact
path="/specs/:specId/sdk-configs/:sdkConfigId/edit"
component={AddSdkConfigModal}
/>
</main>
</div>
)}
Expand Down
38 changes: 34 additions & 4 deletions packages/frontend-dist/src/view/SpecViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,41 @@ import { observer } from 'mobx-react';
import React, { SFC } from 'react';
import { RouteComponentProps } from 'react-router';

import { state } from '../state/SpecState';
import { Spec, SdkConfig, HasId } from '@openapi-platform/model';
import { state as sdkConfigState } from '../state/SdkConfigState';
import { state as specState } from '../state/SpecState';
import { NotFound } from './basic/NotFound';
import { SpecInformation } from './basic/SpecInformation';

export const SpecViewer: SFC<RouteComponentProps<{}>> = observer(({ match }) => {
const spec = state.specs.get(Number.parseInt(match.params.id, 10));
return spec ? <SpecInformation spec={spec} /> : <NotFound item="specification" />;
export const SpecViewer: SFC<RouteComponentProps<{}>> = observer(({ history, match }) => {
const specId = Number.parseInt(match.params.id, 10);
const specification = specState.specs.get(specId);
const sdkConfigs = sdkConfigState.specSdkConfigs.get(specId);

const onNavigateBack = () => history.push(match.url.replace('specs', 'overview'));

const onEditSdkConfigModal = (sdkConfig: HasId<SdkConfig>) =>
history.push(`${match.url}/sdk-configs/${sdkConfig.id}/edit`);
const openEditSpecModal = (spec: HasId<Spec>) => history.push(`${match.url}/edit`);
const openDeleteSpecModal = (spec: HasId<Spec>) => history.push(`${match.url}/delete`);
const openAddSdkConfigModal = (spec: HasId<Spec>) =>
history.push(`${match.url}/sdk-configs/add`);

return specification ? (
<SpecInformation
spec={specification}
sdkConfigs={sdkConfigs}
onEditSdkConfig={onEditSdkConfigModal}
onNavigateBack={onNavigateBack}
// Open a modal to edit the current spec
onEditSpec={openEditSpecModal}
// Open a model to delete the current spec
onDeleteSpec={openDeleteSpecModal}
// Open a modal to add an SDK configuration when the 'Add SDK Configuration' button is
// clicked
onAddSdkConfig={openAddSdkConfigModal}
/>
) : (
<NotFound item="specification" />
);
});
28 changes: 14 additions & 14 deletions packages/frontend-dist/src/view/basic/SdkConfigItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import * as Icons from '@material-ui/icons';
import { observable, action } from 'mobx';
import { Observer } from 'mobx-react';

import { HasId } from '@openapi-platform/model';
import { SdkConfig, BuildStatus } from '@openapi-platform/model';
import { SdkConfig, BuildStatus, HasId } from '@openapi-platform/model';
import { Sdk } from '@openapi-platform/model';
import { client } from '../../client';
import { createStyled } from '../createStyled';
Expand Down Expand Up @@ -37,7 +36,7 @@ const Styled: any = createStyled(theme => ({

export interface SdkConfigItemProps extends React.DOMAttributes<HTMLDivElement> {
sdkConfig: HasId<SdkConfig>;
onEditSdkConfig: (sdkConfig: HasId<SdkConfig>) => void;
onEditSdkConfig?: (sdkConfig: HasId<SdkConfig>) => void;
}

/**
Expand All @@ -58,9 +57,8 @@ export class SdkConfigItem extends Component<SdkConfigItemProps> {
this.latestSdkUrl = sdk.path;
};

private onEditSdkConfig = () => {
this.props.onEditSdkConfig(this.props.sdkConfig);
};
private onEditSdkConfig = () =>
this.props.onEditSdkConfig && this.props.onEditSdkConfig(this.props.sdkConfig);

public render() {
const { sdkConfig } = this.props;
Expand Down Expand Up @@ -91,14 +89,6 @@ export class SdkConfigItem extends Component<SdkConfigItemProps> {
</TableCell>
<TableCell numeric>
<div className={classes.sdkConfigActions}>
{this.latestSdkUrl ? (
<IconButton href={this.latestSdkUrl}>
<Icons.CloudDownload />
</IconButton>
) : null}
<IconButton aria-label="Edit" onClick={this.onEditSdkConfig}>
<Icons.Edit />
</IconButton>
<Button
size="small"
disabled={sdkConfig.buildStatus === BuildStatus.Running}
Expand All @@ -108,6 +98,16 @@ export class SdkConfigItem extends Component<SdkConfigItemProps> {
? 'Running...'
: 'Run'}
</Button>
{this.latestSdkUrl ? (
<IconButton href={this.latestSdkUrl}>
<Icons.CloudDownload />
</IconButton>
) : null}
{this.props.onEditSdkConfig ? (
<IconButton aria-label="Edit" onClick={this.onEditSdkConfig}>
<Icons.Edit />
</IconButton>
) : null}
</div>
</TableCell>
</TableRow>
Expand Down
22 changes: 17 additions & 5 deletions packages/frontend-dist/src/view/basic/SimpleToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { SFC } from 'react';

import { TextField, Toolbar, Typography } from '@material-ui/core';
import { IconButton, TextField, Toolbar, Typography } from '@material-ui/core';
import * as Icons from '@material-ui/icons';

import { Category } from '../../Storybook';
Expand All @@ -11,10 +11,12 @@ export interface SimpleToolbarProps extends React.DOMAttributes<HTMLDivElement>
searchPrompt: string;
onSearchInputChange: (event: { target: { value: string } }) => void;
actions: any[];
showBack?: boolean;
onNavigateBack?: () => void;
}

const Styled = createStyled(theme => ({
title: {
leftArea: {
flex: 1,
color: theme.palette.text.secondary,
marginRight: theme.spacing.unit,
Expand Down Expand Up @@ -57,13 +59,23 @@ export const SimpleToolbar: SFC<SimpleToolbarProps> = ({
searchPrompt,
onSearchInputChange,
actions,
showBack,
onNavigateBack,
}) => (
<Styled>
{({ classes }) => (
<Toolbar className={classes.toolbar}>
<Typography variant="title" className={classes.title}>
{title}
</Typography>
<div className={classes.leftArea}>
{showBack ? (
<IconButton className={classes.title} onClick={onNavigateBack}>
<Icons.ArrowBack />
</IconButton>
) : (
<Typography variant="title" className={classes.title}>
{title}
</Typography>
)}
</div>
<TextField
placeholder={searchPrompt}
className={classes.searchArea}
Expand Down
Loading