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

CLAPPS: Fix StackScript routing #4625

Merged
merged 3 commits into from
Mar 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions src/containers/profile.container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { connect } from 'react-redux';
import { ApplicationState } from 'src/store';

export interface ProfileProps {
profile?: Linode.Profile;
}

export default <TInner extends {}, TOutter extends {}>(
mapAccountToProps: (ownProps: TOutter, account?: Linode.Profile) => TInner
) =>
connect((state: ApplicationState, ownProps: TOutter) => {
const profile = state.__resources.profile.data;

return mapAccountToProps(ownProps, profile);
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compose, pathOr } from 'ramda';
import { pathOr } from 'ramda';
import * as React from 'react';
import { connect } from 'react-redux';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { compose } from 'recompose';
import Button from 'src/components/Button';
import CircleProgress from 'src/components/CircleProgress';
import Paper from 'src/components/core/Paper';
Expand All @@ -11,11 +13,12 @@ import {
} from 'src/components/core/styles';
import Typography from 'src/components/core/Typography';
import Notice from 'src/components/Notice';
import RenderGuard from 'src/components/RenderGuard';
import RenderGuard, { RenderGuardProps } from 'src/components/RenderGuard';
import Table from 'src/components/Table';
import { getStackScript } from 'src/services/stackscripts';
import { MapState } from 'src/store/types';
import { formatDate } from 'src/utilities/format-date-iso8601';
import { getParamFromUrl } from 'src/utilities/queryParams';
import stripImageName from 'src/utilities/stripImageName';
import truncateText from 'src/utilities/truncateText';
import StackScriptTableHead from '../Partials/StackScriptTableHead';
Expand Down Expand Up @@ -76,7 +79,7 @@ const styles: StyleRulesCallback<ClassNames> = theme => ({
}
});

interface Props {
interface Props extends RenderGuardProps {
selectedId: number | undefined;
selectedUsername?: string;
error?: string;
Expand All @@ -90,12 +93,20 @@ interface Props {
publicImages: Linode.Image[];
resetSelectedStackScript: () => void;
disabled?: boolean;
request: () => Promise<Linode.ResourcePage<any>>;
request: (
username: string,
params?: any,
filter?: any
) => Promise<Linode.ResourcePage<any>>;
category: string;
header: string;
}

type CombinedProps = Props & StateProps & WithStyles<ClassNames>;
type CombinedProps = Props &
StateProps &
RouteComponentProps<{}> &
RenderGuardProps &
WithStyles<ClassNames>;

interface State {
stackScript?: Linode.StackScript.Response;
Expand All @@ -112,9 +123,12 @@ class SelectStackScriptPanel extends React.Component<CombinedProps, State> {
mounted: boolean = false;

componentDidMount() {
if (this.props.selectedId) {
const selected =
this.props.selectedId ||
getParamFromUrl(this.props.location.search, 'stackScriptID');
if (selected) {
this.setState({ stackScriptLoading: true });
getStackScript(this.props.selectedId)
getStackScript(selected)
.then(stackScript => {
this.setState({ stackScript, stackScriptLoading: false });
this.props.onSelect(
Expand Down Expand Up @@ -195,11 +209,7 @@ class SelectStackScriptPanel extends React.Component<CombinedProps, State> {
</tbody>
</Table>
<div className={classes.link}>
<Button
href="/linodes/create?type=fromStackScript"
onClick={this.resetStackScript}
type="secondary"
>
<Button onClick={this.resetStackScript} type="secondary">
Choose another StackScript
</Button>
</div>
Expand Down Expand Up @@ -255,12 +265,8 @@ const connected = connect(mapStateToProps);

const styled = withStyles(styles);

export default compose<
Linode.TodoAny,
Linode.TodoAny,
Linode.TodoAny,
Linode.TodoAny
>(
export default compose<CombinedProps, Props>(
withRouter,
connected,
RenderGuard,
styled
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { path } from 'ramda';
import * as React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { compose } from 'recompose';

import ActionMenu, { Action } from 'src/components/ActionMenu/ActionMenu';
import withProfile from 'src/containers/profile.container';

import { getStackScriptUrl } from '../stackScriptUtils';

interface Props {
stackScriptID: number;
Expand All @@ -12,6 +17,8 @@ interface Props {
canDelete: boolean;
canEdit: boolean;
isPublic: boolean;
// From Profile HOC
username?: string;
}

type CombinedProps = Props & RouteComponentProps<{}>;
Expand All @@ -28,7 +35,8 @@ const StackScriptActionMenu: React.StatelessComponent<
stackScriptLabel,
canDelete,
canEdit,
isPublic
isPublic,
username
} = props;

const createActions = () => {
Expand All @@ -38,8 +46,12 @@ const StackScriptActionMenu: React.StatelessComponent<
title: 'Deploy New Linode',
onClick: (e: React.MouseEvent<HTMLElement>) => {
history.push(
`/linodes/create?type=fromStackScript` +
`&stackScriptID=${stackScriptID}&stackScriptUsername=${stackScriptUsername}`
getStackScriptUrl(
stackScriptUsername,
stackScriptID,
stackScriptLabel,
username
)
);
e.preventDefault();
}
Expand Down Expand Up @@ -83,4 +95,14 @@ const StackScriptActionMenu: React.StatelessComponent<
return <ActionMenu createActions={createActions()} />;
};

export default withRouter(StackScriptActionMenu);
const enhanced = compose<CombinedProps, Props>(
withRouter,
withProfile((ownProps, profile) => {
return {
...ownProps,
username: path(['username'], profile)
};
})
);

export default enhanced(StackScriptActionMenu);
42 changes: 36 additions & 6 deletions src/features/StackScripts/StackScriptsDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { compose } from 'ramda';
import { compose, path } from 'ramda';
import * as React from 'react';

import { RouteComponentProps } from 'react-router-dom';
Expand All @@ -14,10 +14,13 @@ import setDocs, { SetDocsProps } from 'src/components/DocsSidebar/setDocs';
import Grid from 'src/components/Grid';
import NotFound from 'src/components/NotFound';
import StackScript from 'src/components/StackScript';
import withProfile from 'src/containers/profile.container';
import { StackScripts as StackScriptsDocs } from 'src/documentation';

import { getStackScript } from 'src/services/stackscripts';

import { getStackScriptUrl } from './stackScriptUtils';

interface MatchProps {
stackScriptId: string;
}
Expand Down Expand Up @@ -49,7 +52,15 @@ const styles: StyleRulesCallback<ClassNames> = theme => ({
}
});

type CombinedProps = RouteProps & WithStyles<ClassNames> & SetDocsProps;
interface ProfileProps {
// From Profile container
username?: string;
}

type CombinedProps = ProfileProps &
RouteProps &
WithStyles<ClassNames> &
SetDocsProps;

export class StackScriptsDetail extends React.Component<CombinedProps, {}> {
state: State = {
Expand All @@ -69,6 +80,21 @@ export class StackScriptsDetail extends React.Component<CombinedProps, {}> {
});
}

handleClick = () => {
const { history, username } = this.props;
const { stackScript } = this.state;
if (!stackScript) {
return;
}
const url = getStackScriptUrl(
stackScript.username,
stackScript.id,
stackScript.label,
username
);
history.push(url);
};

render() {
const { classes } = this.props;
const { loading, stackScript } = this.state;
Expand Down Expand Up @@ -97,9 +123,7 @@ export class StackScriptsDetail extends React.Component<CombinedProps, {}> {
<Button
type="primary"
className={classes.button}
href={`/linodes/create?type=fromStackScript&stackScriptID=${
stackScript.id
}&stackScriptUsername=${stackScript.username}`}
onClick={this.handleClick}
data-qa-stack-deploy
>
Deploy New Linode
Expand All @@ -116,5 +140,11 @@ export class StackScriptsDetail extends React.Component<CombinedProps, {}> {

export default compose(
withStyles(styles),
setDocs([StackScriptsDocs])
setDocs([StackScriptsDocs]),
withProfile((ownProps, profile) => {
return {
...ownProps,
username: path(['username'], profile)
};
})
)(StackScriptsDetail);
27 changes: 27 additions & 0 deletions src/features/StackScripts/stackScriptUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,30 @@ export const getErrorText = (error: any) => {
}
return 'There was an error loading your StackScripts. Please try again later.';
};

export const getStackScriptUrl = (
username: string,
id: number,
label: string,
currentUser?: string
) => {
let type;
let subtype;
switch (username) {
case 'linode':
// This is a Cloud App (unless it isn't, which we are unable to handle at this time)
type = 'One-Click';
subtype = 'One-Click%20Apps';
break;
case currentUser:
// My StackScripts
type = 'My%20Images';
subtype = 'My%20StackScripts';
break;
default:
// Community StackScripts
type = 'One-Click';
subtype = 'Community%20StackScripts';
}
return `/linodes/create?type=${type}&stackScriptID=${id}&stackScriptUsername=${username}&stackScriptLabel=${label}&subtype=${subtype}`;
};
6 changes: 3 additions & 3 deletions src/features/linodes/LinodesCreate/CALinodeCreate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { parse } from 'querystring';
import * as React from 'react';
import { connect, MapDispatchToProps } from 'react-redux';
import CircleProgress from 'src/components/CircleProgress';
Expand All @@ -12,6 +11,7 @@ import {
getCommunityStackscripts,
getStackScriptsByUser
} from 'src/features/StackScripts/stackScriptUtils';
import { getParamsFromUrl } from 'src/utilities/queryParams';
import SubTabs, { Tab } from './CALinodeCreateSubTabs';
import FromAppsContent from './TabbedContent/FromAppsContent';
import FromBackupsContent from './TabbedContent/FromBackupsContent';
Expand Down Expand Up @@ -51,12 +51,12 @@ interface State {
export class LinodeCreate extends React.PureComponent<
CombinedProps & DispatchProps,
State
> {
> {
constructor(props: CombinedProps & DispatchProps) {
super(props);

/** get the query params as an object, excluding the "?" */
const queryParams = parse(location.search.replace('?', ''));
const queryParams = getParamsFromUrl(location.search);

/** will be -1 if the query param is not found */
const preSelectedTab = this.tabs.findIndex((eachTab, index) => {
Expand Down
10 changes: 10 additions & 0 deletions src/features/linodes/LinodesCreate/LinodeCreateContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
hasGrant,
isRestrictedUser
} from 'src/features/Profile/permissionsHelpers';
import { getParamsFromUrl } from 'src/utilities/queryParams';
import CALinodeCreate from './CALinodeCreate';
import { ExtendedType } from './SelectPlanPanel';

Expand Down Expand Up @@ -134,6 +135,15 @@ class LinodeCreateContainer extends React.PureComponent<CombinedProps, State> {
}

componentDidMount() {
const params = getParamsFromUrl(this.props.location.search);
if (params && params !== {}) {
this.setState({
// Each of these will be undefined if not included in the URL, so this will behave correctly:
selectedStackScriptID: Number(params.stackScriptID),
selectedStackScriptLabel: params.stackScriptLabel,
selectedStackScriptUsername: params.stackScriptUserName
});
}
this.setState({ appInstancesLoading: true });
getCloudApps()
.then(response => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export class FromStackScriptContent extends React.PureComponent<CombinedProps> {
resetSelectedStackScript={() => null}
disabled={disabled}
request={request}
category={'apps'}
/>
{!disabled && userDefinedFields && userDefinedFields.length > 0 && (
<UserDefinedFieldsPanel
Expand Down