forked from vmware-tanzu/kubeapps
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* listable catalog stuff * Add instance and binding * Add secret info to binding * Concurrent service bindings * immutable refactor * wip * flexbox plans * provision * update provision * selectable chart versions (vmware-tanzu#39) * selectable chart versions - select chart versions from chart versions list - adds route /chart/:repo/:chart/versions/:version to drill down on version details - chartview is rendered based on the selected chart version type (latest by default) instead of the chart type * style show all link correctly * listable catalog stuff * wip * stashing * card lists * working provision * sample parameters for provision * fixed routes * add CardContainer * status message styling * added tags to class cards * working plan card images * grid based cards * catalog sync * fixed card widths & removed template code from containers * fixed Card infinite width growth * retrieve name and bullets from service plan metadata * update catalog fetch time in brokerview * remove string[] from body * move components to own folders * Cleanup - Migrated several `fetch` queries to use axios - Changed the AppRepoForm appear in a modal instead of its own URL - Refactored repo dispatch code from container to actions - Moved Card css into separate CSS file - Changed nulls to `undefined`
- Loading branch information
Showing
39 changed files
with
2,495 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
.vscode | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import { Dispatch } from "redux"; | ||
import { createAction, getReturnOfExpression } from "typesafe-actions"; | ||
|
||
import { | ||
IServiceBinding, | ||
IServiceBroker, | ||
IServiceClass, | ||
IServiceInstance, | ||
IServicePlan, | ||
ServiceCatalog, | ||
} from "../shared/ServiceCatalog"; | ||
import { IStoreState } from "../shared/types"; | ||
|
||
export const checkCatalogInstall = createAction("CHECK_INSTALL"); | ||
export const installed = createAction("INSTALLED"); | ||
export const notInstalled = createAction("_NOT_INSTALLED"); | ||
export const requestBrokers = createAction("REQUEST_BROKERS"); | ||
export const receiveBrokers = createAction("RECEIVE_BROKERS", (brokers: IServiceBroker[]) => ({ | ||
brokers, | ||
type: "RECEIVE_BROKERS", | ||
})); | ||
export const requestPlans = createAction("REQUEST_PLANS"); | ||
export const receivePlans = createAction("RECEIVE_PLANS", (plans: IServicePlan[]) => ({ | ||
plans, | ||
type: "RECEIVE_PLANS", | ||
})); | ||
export const requestInstances = createAction("REQUEST_INSTANCES"); | ||
export const receiveInstances = createAction( | ||
"RECEIVE_INSTANCES", | ||
(instances: IServiceInstance[]) => ({ type: "RECEIVE_INSTANCES", instances }), | ||
); | ||
export const requestBindings = createAction("REQUEST_BINDINGS"); | ||
export const receiveBindings = createAction("RECEIVE_BINDINGS", (bindings: IServiceBinding[]) => ({ | ||
bindings, | ||
type: "RECEIVE_BINDINGS", | ||
})); | ||
export const requestClasses = createAction("REQUEST_PLANS"); | ||
export const receiveClasses = createAction("RECEIVE_CLASSES", (classes: IServiceClass[]) => ({ | ||
classes, | ||
type: "RECEIVE_CLASSES", | ||
})); | ||
|
||
const actions = [ | ||
checkCatalogInstall, | ||
installed, | ||
notInstalled, | ||
requestBrokers, | ||
receiveBrokers, | ||
requestPlans, | ||
receivePlans, | ||
requestInstances, | ||
receiveInstances, | ||
requestBindings, | ||
receiveBindings, | ||
requestClasses, | ||
receiveClasses, | ||
].map(getReturnOfExpression); | ||
|
||
export function provision( | ||
releaseName: string, | ||
namespace: string, | ||
className: string, | ||
planName: string, | ||
parameters: {}, | ||
) { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
return ServiceCatalog.provisionInstance( | ||
releaseName, | ||
namespace, | ||
className, | ||
planName, | ||
parameters, | ||
); | ||
}; | ||
} | ||
|
||
export function sync(broker: IServiceBroker) { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
return ServiceCatalog.syncBroker(broker); | ||
}; | ||
} | ||
|
||
export type ServiceCatalogAction = typeof actions[number]; | ||
|
||
export function getBindings() { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(requestBindings()); | ||
const bindings = await ServiceCatalog.getServiceBindings(); | ||
dispatch(receiveBindings(bindings)); | ||
return bindings; | ||
}; | ||
} | ||
|
||
export function getBrokers() { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(requestBrokers()); | ||
const brokers = await ServiceCatalog.getServiceBrokers(); | ||
dispatch(receiveBrokers(brokers)); | ||
return brokers; | ||
}; | ||
} | ||
|
||
export function getClasses() { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(requestClasses()); | ||
const classes = await ServiceCatalog.getServiceClasses(); | ||
dispatch(receiveClasses(classes)); | ||
return classes; | ||
}; | ||
} | ||
|
||
export function getInstances() { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(requestInstances()); | ||
const instances = await ServiceCatalog.getServiceInstances(); | ||
dispatch(receiveInstances(instances)); | ||
return instances; | ||
}; | ||
} | ||
|
||
export function getPlans() { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(requestPlans()); | ||
const plans = await ServiceCatalog.getServicePlans(); | ||
dispatch(receivePlans(plans)); | ||
return plans; | ||
}; | ||
} | ||
|
||
export function getCatalog() { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(getBindings()); | ||
dispatch(getBrokers()); | ||
dispatch(getClasses()); | ||
dispatch(getInstances()); | ||
dispatch(getPlans()); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
import * as catalog from "./catalog"; | ||
import * as charts from "./charts"; | ||
import * as repos from "./repos"; | ||
|
||
export default { | ||
catalog, | ||
charts, | ||
repos, | ||
}; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { createAction, getReturnOfExpression } from "typesafe-actions"; | ||
|
||
import { Dispatch } from "react-redux"; | ||
import { AppRepository } from "../shared/AppRepository"; | ||
import { IAppRepository, IStoreState } from "../shared/types"; | ||
|
||
export const addRepo = createAction("ADD_REPO"); | ||
export const addedRepo = createAction("ADDED_REPO", (added: IAppRepository) => ({ | ||
added, | ||
type: "ADDED_REPO", | ||
})); | ||
export const requestRepos = createAction("REQUEST_REPOS"); | ||
export const receiveRepos = createAction("RECEIVE_REPOS", (repos: IAppRepository[]) => { | ||
return { | ||
repos, | ||
type: "RECEIVE_REPOS", | ||
}; | ||
}); | ||
export const showForm = createAction("SHOW_FORM"); | ||
export const hideForm = createAction("HIDE_FORM"); | ||
export const resetForm = createAction("RESET_FORM"); | ||
export const submitForm = createAction("SUBMIT_FROM"); | ||
export const updateForm = createAction( | ||
"UPDATE_FORM", | ||
(values: { name?: string; namespace?: string; url?: string }) => { | ||
return { | ||
type: "UPDATE_FORM", | ||
values, | ||
}; | ||
}, | ||
); | ||
export const redirect = createAction("REDIRECT", (path: string) => ({ type: "REDIRECT", path })); | ||
export const redirected = createAction("REDIRECTED"); | ||
|
||
const allActions = [ | ||
addRepo, | ||
addedRepo, | ||
requestRepos, | ||
receiveRepos, | ||
resetForm, | ||
submitForm, | ||
updateForm, | ||
showForm, | ||
hideForm, | ||
redirect, | ||
redirected, | ||
].map(getReturnOfExpression); | ||
export type AppReposAction = typeof allActions[number]; | ||
|
||
export const deleteRepo = (name: string, namespace: string = "kubeapps") => { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
await AppRepository.delete(name, namespace); | ||
dispatch(requestRepos()); | ||
const repos = await AppRepository.list(); | ||
dispatch(receiveRepos(repos.items)); | ||
return repos; | ||
}; | ||
}; | ||
|
||
export const fetchRepos = () => { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(requestRepos()); | ||
const repos = await AppRepository.list(); | ||
dispatch(receiveRepos(repos.items)); | ||
return repos; | ||
}; | ||
}; | ||
|
||
export const installRepo = (name: string, url: string, namespace: string) => { | ||
return async (dispatch: Dispatch<IStoreState>) => { | ||
dispatch(addRepo()); | ||
const added = await AppRepository.create(name, url, namespace); | ||
dispatch(addedRepo(added)); | ||
return added; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import * as React from "react"; | ||
import * as Modal from "react-modal"; | ||
import { Redirect } from "react-router"; | ||
|
||
interface IAppRepoFormProps { | ||
name: string; | ||
url: string; | ||
message?: string; | ||
redirectTo?: string; | ||
install: (name: string, url: string) => Promise<any>; | ||
update: (values: { name?: string; url?: string }) => void; | ||
onAfterInstall?: () => Promise<any>; | ||
} | ||
|
||
export const AppRepoForm = (props: IAppRepoFormProps) => { | ||
const { name, url, update, install, onAfterInstall } = props; | ||
const handleInstallClick = async () => { | ||
await install(name, url); | ||
if (onAfterInstall) { | ||
await onAfterInstall(); | ||
} | ||
}; | ||
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => | ||
update({ name: e.target.value }); | ||
const handleURLChange = (e: React.ChangeEvent<HTMLInputElement>) => | ||
update({ url: e.target.value }); | ||
return ( | ||
<div className="app-repo-form"> | ||
<h1>Add an App Repository</h1> | ||
<label> | ||
Name: | ||
<input type="text" value={name} onChange={handleNameChange} /> | ||
</label> | ||
<label> | ||
URL: | ||
<input type="text" value={url} onChange={handleURLChange} /> | ||
</label> | ||
<button className="button button-primary" onClick={handleInstallClick}> | ||
Install Repo | ||
</button> | ||
{props.redirectTo && <Redirect to={props.redirectTo} />} | ||
</div> | ||
); | ||
}; | ||
|
||
interface IAppRepoAddButtonProps { | ||
install: (name: string, url: string) => Promise<any>; | ||
redirectTo?: string; | ||
} | ||
interface IAppRepoAddButtonState { | ||
error?: string; | ||
modalIsOpen: boolean; | ||
name: string; | ||
url: string; | ||
} | ||
|
||
export class AppRepoAddButton extends React.Component< | ||
IAppRepoAddButtonProps, | ||
IAppRepoAddButtonState | ||
> { | ||
public state = { | ||
error: undefined, | ||
modalIsOpen: false, | ||
name: "", | ||
url: "", | ||
}; | ||
|
||
public render() { | ||
const { redirectTo, install } = this.props; | ||
const { name, url } = this.state; | ||
return ( | ||
<div className="AppRepoAddButton"> | ||
<button className="button button-primary" onClick={this.openModal}> | ||
Add App Repository | ||
</button> | ||
<Modal | ||
isOpen={this.state.modalIsOpen} | ||
onRequestClose={this.closeModal} | ||
contentLabel="Modal" | ||
> | ||
{this.state.error && ( | ||
<div className="container padding-v-bigger bg-action">{this.state.error}</div> | ||
)} | ||
<AppRepoForm | ||
name={name} | ||
url={url} | ||
update={this.updateValues} | ||
install={install} | ||
onAfterInstall={this.closeModal} | ||
/> | ||
</Modal> | ||
{redirectTo && <Redirect to={redirectTo} />} | ||
</div> | ||
); | ||
} | ||
|
||
private closeModal = async () => this.setState({ modalIsOpen: false }); | ||
private openModal = async () => this.setState({ modalIsOpen: true }); | ||
private updateValues = async (values: { name: string; url: string }) => | ||
this.setState({ ...values }); | ||
} |
Oops, something went wrong.