mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-23 17:00:30 +00:00
commit
4505d892f8
86 changed files with 3451 additions and 3318 deletions
16
.editorconfig
Normal file
16
.editorconfig
Normal file
|
@ -0,0 +1,16 @@
|
|||
root = true
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
|
@ -1,38 +1,33 @@
|
|||
module.exports = {
|
||||
"extends": [
|
||||
"standard",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:react/recommended",
|
||||
"prettier",
|
||||
"prettier/react"
|
||||
],
|
||||
"plugins": [
|
||||
"react",
|
||||
"jest",
|
||||
"prettier"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2016,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"jest/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"react/prop-types": 1,
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"trailingComma": "all",
|
||||
"useTabs": true
|
||||
}
|
||||
]
|
||||
}
|
||||
extends: [
|
||||
"standard",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:react/recommended",
|
||||
"prettier",
|
||||
"prettier/react"
|
||||
],
|
||||
plugins: ["react", "jest", "prettier"],
|
||||
parser: "babel-eslint",
|
||||
parserOptions: {
|
||||
ecmaVersion: 2016,
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
}
|
||||
},
|
||||
env: {
|
||||
es6: true,
|
||||
browser: true,
|
||||
node: true,
|
||||
"jest/globals": true
|
||||
},
|
||||
rules: {
|
||||
"react/prop-types": 1,
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
trailingComma: "all",
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
import React from "react";
|
||||
|
||||
export const drone = (client, Component) => {
|
||||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||
// eslint-disable-next-line react/display-name
|
||||
const component = class extends React.Component {
|
||||
getChildContext() {
|
||||
return {
|
||||
drone: client,
|
||||
};
|
||||
}
|
||||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||
// eslint-disable-next-line react/display-name
|
||||
const component = class extends React.Component {
|
||||
getChildContext() {
|
||||
return {
|
||||
drone: client,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Component {...this.state} {...this.props} />;
|
||||
}
|
||||
};
|
||||
render() {
|
||||
return <Component {...this.state} {...this.props} />;
|
||||
}
|
||||
};
|
||||
|
||||
component.childContextTypes = {
|
||||
drone: (props, propName) => {},
|
||||
};
|
||||
component.childContextTypes = {
|
||||
drone: (props, propName) => {},
|
||||
};
|
||||
|
||||
return component;
|
||||
return component;
|
||||
};
|
||||
|
||||
export const inject = Component => {
|
||||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||
// eslint-disable-next-line react/display-name
|
||||
const component = class extends React.Component {
|
||||
render() {
|
||||
this.props.drone = this.context.drone;
|
||||
return <Component {...this.state} {...this.props} />;
|
||||
}
|
||||
};
|
||||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||
// eslint-disable-next-line react/display-name
|
||||
const component = class extends React.Component {
|
||||
render() {
|
||||
this.props.drone = this.context.drone;
|
||||
return <Component {...this.state} {...this.props} />;
|
||||
}
|
||||
};
|
||||
|
||||
return component;
|
||||
return component;
|
||||
};
|
||||
|
|
|
@ -4,75 +4,75 @@ const user = window.DRONE_USER;
|
|||
const sync = window.DRONE_SYNC;
|
||||
|
||||
const state = {
|
||||
follow: false,
|
||||
language: "en-US",
|
||||
follow: false,
|
||||
language: "en-US",
|
||||
|
||||
user: {
|
||||
data: user,
|
||||
error: undefined,
|
||||
loaded: true,
|
||||
syncing: sync,
|
||||
},
|
||||
user: {
|
||||
data: user,
|
||||
error: undefined,
|
||||
loaded: true,
|
||||
syncing: sync,
|
||||
},
|
||||
|
||||
feed: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
feed: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
|
||||
repos: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
repos: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
|
||||
secrets: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
secrets: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
|
||||
registry: {
|
||||
error: undefined,
|
||||
loaded: false,
|
||||
data: {},
|
||||
},
|
||||
registry: {
|
||||
error: undefined,
|
||||
loaded: false,
|
||||
data: {},
|
||||
},
|
||||
|
||||
builds: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
builds: {
|
||||
loaded: false,
|
||||
error: undefined,
|
||||
data: {},
|
||||
},
|
||||
|
||||
logs: {
|
||||
follow: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
data: {},
|
||||
},
|
||||
logs: {
|
||||
follow: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
data: {},
|
||||
},
|
||||
|
||||
token: {
|
||||
value: undefined,
|
||||
error: undefined,
|
||||
loading: false,
|
||||
},
|
||||
token: {
|
||||
value: undefined,
|
||||
error: undefined,
|
||||
loading: false,
|
||||
},
|
||||
|
||||
message: {
|
||||
show: false,
|
||||
text: undefined,
|
||||
error: false,
|
||||
},
|
||||
message: {
|
||||
show: false,
|
||||
text: undefined,
|
||||
error: false,
|
||||
},
|
||||
|
||||
location: {
|
||||
protocol: window.location.protocol,
|
||||
host: window.location.host,
|
||||
},
|
||||
location: {
|
||||
protocol: window.location.protocol,
|
||||
host: window.location.host,
|
||||
},
|
||||
};
|
||||
|
||||
const tree = new Baobab(state);
|
||||
|
||||
if (window) {
|
||||
window.tree = tree;
|
||||
window.tree = tree;
|
||||
}
|
||||
|
||||
export default tree;
|
||||
|
|
|
@ -5,8 +5,8 @@ import { render } from "react-dom";
|
|||
let root;
|
||||
|
||||
function init() {
|
||||
let App = require("./screens/drone").default;
|
||||
root = render(<App />, document.body, root);
|
||||
let App = require("./screens/drone").default;
|
||||
root = render(<App />, document.body, root);
|
||||
}
|
||||
|
||||
init();
|
||||
|
|
|
@ -16,37 +16,37 @@ import { BrowserRouter, Route, Switch } from "react-router-dom";
|
|||
import styles from "./drone.less";
|
||||
|
||||
if (module.hot) {
|
||||
require("preact/devtools");
|
||||
require("preact/devtools");
|
||||
}
|
||||
|
||||
class App extends Component {
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div>
|
||||
<Title />
|
||||
<Switch>
|
||||
<Route path="/" exact={true} component={RedirectRoot} />
|
||||
<Route path="/login/form" exact={true} component={LoginForm} />
|
||||
<Route path="/login/error" exact={true} component={LoginError} />
|
||||
<Route path="/" exact={false} component={Layout} />
|
||||
</Switch>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div>
|
||||
<Title />
|
||||
<Switch>
|
||||
<Route path="/" exact={true} component={RedirectRoot} />
|
||||
<Route path="/login/form" exact={true} component={LoginForm} />
|
||||
<Route path="/login/error" exact={true} component={LoginError} />
|
||||
<Route path="/" exact={false} component={Layout} />
|
||||
</Switch>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (tree.exists(["user", "data"])) {
|
||||
fetchFeedOnce(tree, client);
|
||||
subscribeToFeedOnce(tree, client);
|
||||
fetchFeedOnce(tree, client);
|
||||
subscribeToFeedOnce(tree, client);
|
||||
}
|
||||
|
||||
client.onerror = error => {
|
||||
console.error(error);
|
||||
if (error.status === 401) {
|
||||
tree.unset(["user", "data"]);
|
||||
}
|
||||
console.error(error);
|
||||
if (error.status === 401) {
|
||||
tree.unset(["user", "data"]);
|
||||
}
|
||||
};
|
||||
|
||||
export default root(tree, drone(client, App));
|
||||
|
|
|
@ -8,48 +8,48 @@ import styles from "./list.less";
|
|||
import { StarIcon } from "shared/components/icons/index";
|
||||
|
||||
export const List = ({ children }) => (
|
||||
<div className={styles.list}>{children}</div>
|
||||
<div className={styles.list}>{children}</div>
|
||||
);
|
||||
|
||||
export class Item extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleFave = this.handleFave.bind(this);
|
||||
}
|
||||
this.handleFave = this.handleFave.bind(this);
|
||||
}
|
||||
|
||||
handleFave(e) {
|
||||
e.preventDefault();
|
||||
this.props.onFave(this.props.item.full_name);
|
||||
}
|
||||
handleFave(e) {
|
||||
e.preventDefault();
|
||||
this.props.onFave(this.props.item.full_name);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item, faved } = this.props;
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div onClick={this.handleFave}>
|
||||
<StarIcon filled={faved} size={16} className={styles.star} />
|
||||
</div>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>{item.full_name}</div>
|
||||
<div className={styles.icon}>
|
||||
{item.status ? <Status status={item.status} /> : <noscript />}
|
||||
</div>
|
||||
</div>
|
||||
render() {
|
||||
const { item, faved } = this.props;
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div onClick={this.handleFave}>
|
||||
<StarIcon filled={faved} size={16} className={styles.star} />
|
||||
</div>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>{item.full_name}</div>
|
||||
<div className={styles.icon}>
|
||||
{item.status ? <Status status={item.status} /> : <noscript />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.body}>
|
||||
<BuildTime
|
||||
start={item.started_at || item.created_at}
|
||||
finish={item.finished_at}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div className={styles.body}>
|
||||
<BuildTime
|
||||
start={item.started_at || item.created_at}
|
||||
finish={item.finished_at}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.item !== nextProps.item || this.props.faved !== nextProps.faved
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.item !== nextProps.item || this.props.faved !== nextProps.faved
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,173 +14,173 @@ import style from "./index.less";
|
|||
import Collapsible from "react-collapsible";
|
||||
|
||||
const binding = (props, context) => {
|
||||
return { feed: ["feed"] };
|
||||
return { feed: ["feed"] };
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class Sidebar extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.setState({
|
||||
starred: JSON.parse(localStorage.getItem("starred") || "[]"),
|
||||
starredOpen: (localStorage.getItem("starredOpen") || "true") === "true",
|
||||
reposOpen: (localStorage.getItem("reposOpen") || "true") === "true",
|
||||
});
|
||||
this.setState({
|
||||
starred: JSON.parse(localStorage.getItem("starred") || "[]"),
|
||||
starredOpen: (localStorage.getItem("starredOpen") || "true") === "true",
|
||||
reposOpen: (localStorage.getItem("reposOpen") || "true") === "true",
|
||||
});
|
||||
|
||||
this.handleFilter = this.handleFilter.bind(this);
|
||||
this.toggleStarred = this.toggleItem.bind(this, "starredOpen");
|
||||
this.toggleAll = this.toggleItem.bind(this, "reposOpen");
|
||||
}
|
||||
this.handleFilter = this.handleFilter.bind(this);
|
||||
this.toggleStarred = this.toggleItem.bind(this, "starredOpen");
|
||||
this.toggleAll = this.toggleItem.bind(this, "reposOpen");
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.feed !== nextProps.feed ||
|
||||
this.state.filter !== nextState.filter ||
|
||||
this.state.starred.length !== nextState.starred.length
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.feed !== nextProps.feed ||
|
||||
this.state.filter !== nextState.filter ||
|
||||
this.state.starred.length !== nextState.starred.length
|
||||
);
|
||||
}
|
||||
|
||||
handleFilter(e) {
|
||||
this.setState({
|
||||
filter: e.target.value,
|
||||
});
|
||||
}
|
||||
handleFilter(e) {
|
||||
this.setState({
|
||||
filter: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
toggleItem = item => {
|
||||
this.setState(state => {
|
||||
return { [item]: !state[item] };
|
||||
});
|
||||
toggleItem = item => {
|
||||
this.setState(state => {
|
||||
return { [item]: !state[item] };
|
||||
});
|
||||
|
||||
localStorage.setItem(item, this.state[item]);
|
||||
};
|
||||
localStorage.setItem(item, this.state[item]);
|
||||
};
|
||||
|
||||
renderFeed = (list, renderStarred) => {
|
||||
return (
|
||||
<div>
|
||||
<List>{list.map(item => this.renderItem(item, renderStarred))}</List>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
renderFeed = (list, renderStarred) => {
|
||||
return (
|
||||
<div>
|
||||
<List>{list.map(item => this.renderItem(item, renderStarred))}</List>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderItem = (item, renderStarred) => {
|
||||
const starred = this.state.starred;
|
||||
if (renderStarred && !starred.includes(item.full_name)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Link to={`/${item.full_name}`} key={item.full_name}>
|
||||
<Item
|
||||
item={item}
|
||||
onFave={this.onFave}
|
||||
faved={starred.includes(item.full_name)}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
renderItem = (item, renderStarred) => {
|
||||
const starred = this.state.starred;
|
||||
if (renderStarred && !starred.includes(item.full_name)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Link to={`/${item.full_name}`} key={item.full_name}>
|
||||
<Item
|
||||
item={item}
|
||||
onFave={this.onFave}
|
||||
faved={starred.includes(item.full_name)}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
onFave = fullName => {
|
||||
if (!this.state.starred.includes(fullName)) {
|
||||
this.setState(state => {
|
||||
const list = state.starred.concat(fullName);
|
||||
return { starred: list };
|
||||
});
|
||||
} else {
|
||||
this.setState(state => {
|
||||
const list = state.starred.filter(v => v !== fullName);
|
||||
return { starred: list };
|
||||
});
|
||||
}
|
||||
onFave = fullName => {
|
||||
if (!this.state.starred.includes(fullName)) {
|
||||
this.setState(state => {
|
||||
const list = state.starred.concat(fullName);
|
||||
return { starred: list };
|
||||
});
|
||||
} else {
|
||||
this.setState(state => {
|
||||
const list = state.starred.filter(v => v !== fullName);
|
||||
return { starred: list };
|
||||
});
|
||||
}
|
||||
|
||||
localStorage.setItem("starred", JSON.stringify(this.state.starred));
|
||||
};
|
||||
localStorage.setItem("starred", JSON.stringify(this.state.starred));
|
||||
};
|
||||
|
||||
render() {
|
||||
const { feed } = this.props;
|
||||
const { filter } = this.state;
|
||||
render() {
|
||||
const { feed } = this.props;
|
||||
const { filter } = this.state;
|
||||
|
||||
const list = feed.data ? Object.values(feed.data) : [];
|
||||
const list = feed.data ? Object.values(feed.data) : [];
|
||||
|
||||
const filterFunc = item => {
|
||||
return !filter || item.full_name.indexOf(filter) !== -1;
|
||||
};
|
||||
const filterFunc = item => {
|
||||
return !filter || item.full_name.indexOf(filter) !== -1;
|
||||
};
|
||||
|
||||
const filtered = list.filter(filterFunc).sort(compareFeedItem);
|
||||
const starredOpen = this.state.starredOpen;
|
||||
const reposOpen = this.state.reposOpen;
|
||||
return (
|
||||
<div className={style.feed}>
|
||||
{LOGO}
|
||||
<Collapsible
|
||||
trigger="Starred"
|
||||
triggerTagName="div"
|
||||
transitionTime={200}
|
||||
open={starredOpen}
|
||||
onOpen={this.toggleStarred}
|
||||
onClose={this.toggleStarred}
|
||||
triggerOpenedClassName={style.Collapsible__trigger}
|
||||
triggerClassName={style.Collapsible__trigger}
|
||||
>
|
||||
{feed.loaded === false ? (
|
||||
LOADING
|
||||
) : feed.error ? (
|
||||
ERROR
|
||||
) : list.length === 0 ? (
|
||||
EMPTY
|
||||
) : (
|
||||
this.renderFeed(list, true)
|
||||
)}
|
||||
</Collapsible>
|
||||
<Collapsible
|
||||
trigger="Repos"
|
||||
triggerTagName="div"
|
||||
transitionTime={200}
|
||||
open={reposOpen}
|
||||
onOpen={this.toggleAll}
|
||||
onClose={this.toggleAll}
|
||||
triggerOpenedClassName={style.Collapsible__trigger}
|
||||
triggerClassName={style.Collapsible__trigger}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search …"
|
||||
onChange={this.handleFilter}
|
||||
/>
|
||||
{feed.loaded === false ? (
|
||||
LOADING
|
||||
) : feed.error ? (
|
||||
ERROR
|
||||
) : list.length === 0 ? (
|
||||
EMPTY
|
||||
) : filtered.length > 0 ? (
|
||||
this.renderFeed(filtered.sort(compareFeedItem), false)
|
||||
) : (
|
||||
NO_MATCHES
|
||||
)}
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const filtered = list.filter(filterFunc).sort(compareFeedItem);
|
||||
const starredOpen = this.state.starredOpen;
|
||||
const reposOpen = this.state.reposOpen;
|
||||
return (
|
||||
<div className={style.feed}>
|
||||
{LOGO}
|
||||
<Collapsible
|
||||
trigger="Starred"
|
||||
triggerTagName="div"
|
||||
transitionTime={200}
|
||||
open={starredOpen}
|
||||
onOpen={this.toggleStarred}
|
||||
onClose={this.toggleStarred}
|
||||
triggerOpenedClassName={style.Collapsible__trigger}
|
||||
triggerClassName={style.Collapsible__trigger}
|
||||
>
|
||||
{feed.loaded === false ? (
|
||||
LOADING
|
||||
) : feed.error ? (
|
||||
ERROR
|
||||
) : list.length === 0 ? (
|
||||
EMPTY
|
||||
) : (
|
||||
this.renderFeed(list, true)
|
||||
)}
|
||||
</Collapsible>
|
||||
<Collapsible
|
||||
trigger="Repos"
|
||||
triggerTagName="div"
|
||||
transitionTime={200}
|
||||
open={reposOpen}
|
||||
onOpen={this.toggleAll}
|
||||
onClose={this.toggleAll}
|
||||
triggerOpenedClassName={style.Collapsible__trigger}
|
||||
triggerClassName={style.Collapsible__trigger}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search …"
|
||||
onChange={this.handleFilter}
|
||||
/>
|
||||
{feed.loaded === false ? (
|
||||
LOADING
|
||||
) : feed.error ? (
|
||||
ERROR
|
||||
) : list.length === 0 ? (
|
||||
EMPTY
|
||||
) : filtered.length > 0 ? (
|
||||
this.renderFeed(filtered.sort(compareFeedItem), false)
|
||||
) : (
|
||||
NO_MATCHES
|
||||
)}
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const LOGO = (
|
||||
<div className={style.brand}>
|
||||
<DroneIcon />
|
||||
<p>
|
||||
Woodpecker<span style="margin-left: 4px;">{window.DRONE_VERSION}</span>
|
||||
<br />
|
||||
<span>
|
||||
<a
|
||||
href="https://woodpecker.laszlo.cloud"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Docs
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className={style.brand}>
|
||||
<DroneIcon />
|
||||
<p>
|
||||
Woodpecker<span style="margin-left: 4px;">{window.DRONE_VERSION}</span>
|
||||
<br />
|
||||
<span>
|
||||
<a
|
||||
href="https://woodpecker.laszlo.cloud"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Docs
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const LOADING = <div className={style.message}>Loading</div>;
|
||||
|
@ -190,7 +190,7 @@ const EMPTY = <div className={style.message}>Your build feed is empty</div>;
|
|||
const NO_MATCHES = <div className={style.message}>No results found</div>;
|
||||
|
||||
const ERROR = (
|
||||
<div className={style.message}>
|
||||
Oops. It looks like there was a problem loading your feed
|
||||
</div>
|
||||
<div className={style.message}>
|
||||
Oops. It looks like there was a problem loading your feed
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -30,198 +30,195 @@ import { Drawer, DOCK_RIGHT } from "shared/components/drawer/drawer";
|
|||
import styles from "./layout.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
return {
|
||||
user: ["user"],
|
||||
message: ["message"],
|
||||
sidebar: ["sidebar"],
|
||||
menu: ["menu"],
|
||||
};
|
||||
return {
|
||||
user: ["user"],
|
||||
message: ["message"],
|
||||
sidebar: ["sidebar"],
|
||||
menu: ["menu"],
|
||||
};
|
||||
};
|
||||
|
||||
const mapScreenSizeToProps = screenSize => {
|
||||
return {
|
||||
isTablet: screenSize["small"],
|
||||
isMobile: screenSize["mobile"],
|
||||
isDesktop: screenSize["> small"],
|
||||
};
|
||||
return {
|
||||
isTablet: screenSize["small"],
|
||||
isMobile: screenSize["mobile"],
|
||||
isDesktop: screenSize["> small"],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
@connectScreenSize(mapScreenSizeToProps)
|
||||
export default class Default extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
menu: false,
|
||||
feed: false,
|
||||
};
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
menu: false,
|
||||
feed: false,
|
||||
};
|
||||
|
||||
this.openMenu = this.openMenu.bind(this);
|
||||
this.closeMenu = this.closeMenu.bind(this);
|
||||
this.closeSnackbar = this.closeSnackbar.bind(this);
|
||||
}
|
||||
this.openMenu = this.openMenu.bind(this);
|
||||
this.closeMenu = this.closeMenu.bind(this);
|
||||
this.closeSnackbar = this.closeSnackbar.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.location !== this.props.location) {
|
||||
this.closeMenu(true);
|
||||
}
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.location !== this.props.location) {
|
||||
this.closeMenu(true);
|
||||
}
|
||||
}
|
||||
|
||||
openMenu() {
|
||||
this.props.dispatch(tree => {
|
||||
tree.set(["menu"], true);
|
||||
});
|
||||
}
|
||||
openMenu() {
|
||||
this.props.dispatch(tree => {
|
||||
tree.set(["menu"], true);
|
||||
});
|
||||
}
|
||||
|
||||
closeMenu() {
|
||||
this.props.dispatch(tree => {
|
||||
tree.set(["menu"], false);
|
||||
});
|
||||
}
|
||||
closeMenu() {
|
||||
this.props.dispatch(tree => {
|
||||
tree.set(["menu"], false);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user, message, menu } = this.props;
|
||||
render() {
|
||||
const { user, message, menu } = this.props;
|
||||
|
||||
const classes = classnames(!user || !user.data ? styles.guest : null);
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={styles.left}>
|
||||
<Switch>
|
||||
<Route path={"/"} component={Feed} />
|
||||
</Switch>
|
||||
</div>
|
||||
<div className={styles.center}>
|
||||
{!user || !user.data ? (
|
||||
<a
|
||||
href={"/login?url=" + window.location.href}
|
||||
target="_self"
|
||||
className={styles.login}
|
||||
>
|
||||
Click to Login
|
||||
</a>
|
||||
) : (
|
||||
<noscript />
|
||||
)}
|
||||
<div className={styles.title}>
|
||||
<Switch>
|
||||
<Route path="/account/repos" component={UserRepoTitle} />
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||
exact={true}
|
||||
component={BuildLogsTitle}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)"
|
||||
component={BuildLogsTitle}
|
||||
/>
|
||||
<Route path="/:owner/:repo" component={RepoHeader} />
|
||||
</Switch>
|
||||
{user && user.data ? (
|
||||
<div className={styles.avatar}>
|
||||
<img src={user.data.avatar_url} />
|
||||
</div>
|
||||
) : (
|
||||
undefined
|
||||
)}
|
||||
{user && user.data ? (
|
||||
<button onClick={this.openMenu}>
|
||||
<MenuIcon />
|
||||
</button>
|
||||
) : (
|
||||
<noscript />
|
||||
)}
|
||||
</div>
|
||||
const classes = classnames(!user || !user.data ? styles.guest : null);
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={styles.left}>
|
||||
<Switch>
|
||||
<Route path={"/"} component={Feed} />
|
||||
</Switch>
|
||||
</div>
|
||||
<div className={styles.center}>
|
||||
{!user || !user.data ? (
|
||||
<a
|
||||
href={"/login?url=" + window.location.href}
|
||||
target="_self"
|
||||
className={styles.login}
|
||||
>
|
||||
Click to Login
|
||||
</a>
|
||||
) : (
|
||||
<noscript />
|
||||
)}
|
||||
<div className={styles.title}>
|
||||
<Switch>
|
||||
<Route path="/account/repos" component={UserRepoTitle} />
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||
exact={true}
|
||||
component={BuildLogsTitle}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)"
|
||||
component={BuildLogsTitle}
|
||||
/>
|
||||
<Route path="/:owner/:repo" component={RepoHeader} />
|
||||
</Switch>
|
||||
{user && user.data ? (
|
||||
<div className={styles.avatar}>
|
||||
<img src={user.data.avatar_url} />
|
||||
</div>
|
||||
) : (
|
||||
undefined
|
||||
)}
|
||||
{user && user.data ? (
|
||||
<button onClick={this.openMenu}>
|
||||
<MenuIcon />
|
||||
</button>
|
||||
) : (
|
||||
<noscript />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.menu}>
|
||||
<Switch>
|
||||
<Route
|
||||
path="/account/repos"
|
||||
exact={true}
|
||||
component={UserReposMenu}
|
||||
/>
|
||||
<Route
|
||||
path="/account/"
|
||||
exact={false}
|
||||
component={undefined}
|
||||
/>BuildMenu
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||
exact={true}
|
||||
component={BuildMenu}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)"
|
||||
exact={true}
|
||||
component={BuildMenu}
|
||||
/>
|
||||
<Route path="/:owner/:repo" exact={false} component={RepoMenu} />
|
||||
</Switch>
|
||||
</div>
|
||||
<div className={styles.menu}>
|
||||
<Switch>
|
||||
<Route
|
||||
path="/account/repos"
|
||||
exact={true}
|
||||
component={UserReposMenu}
|
||||
/>
|
||||
<Route path="/account/" exact={false} component={undefined} />
|
||||
BuildMenu
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||
exact={true}
|
||||
component={BuildMenu}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)"
|
||||
exact={true}
|
||||
component={BuildMenu}
|
||||
/>
|
||||
<Route path="/:owner/:repo" exact={false} component={RepoMenu} />
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
<Switch>
|
||||
<Route path="/account/token" exact={true} component={UserTokens} />
|
||||
<Route path="/account/repos" exact={true} component={UserRepos} />
|
||||
<Route
|
||||
path="/:owner/:repo/settings/secrets"
|
||||
exact={true}
|
||||
component={RepoSecrets}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/settings/registry"
|
||||
exact={true}
|
||||
component={RepoRegistry}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/settings"
|
||||
exact={true}
|
||||
component={RepoSettings}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)"
|
||||
exact={true}
|
||||
component={BuildLogs}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||
exact={true}
|
||||
component={BuildLogs}
|
||||
/>
|
||||
<Route path="/:owner/:repo" exact={true} component={RepoBuilds} />
|
||||
<Route path="/" exact={true} component={RedirectRoot} />
|
||||
</Switch>
|
||||
</div>
|
||||
<Switch>
|
||||
<Route path="/account/token" exact={true} component={UserTokens} />
|
||||
<Route path="/account/repos" exact={true} component={UserRepos} />
|
||||
<Route
|
||||
path="/:owner/:repo/settings/secrets"
|
||||
exact={true}
|
||||
component={RepoSecrets}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/settings/registry"
|
||||
exact={true}
|
||||
component={RepoRegistry}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/settings"
|
||||
exact={true}
|
||||
component={RepoSettings}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)"
|
||||
exact={true}
|
||||
component={BuildLogs}
|
||||
/>
|
||||
<Route
|
||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||
exact={true}
|
||||
component={BuildLogs}
|
||||
/>
|
||||
<Route path="/:owner/:repo" exact={true} component={RepoBuilds} />
|
||||
<Route path="/" exact={true} component={RedirectRoot} />
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
<Snackbar message={message.text} onClose={this.closeSnackbar} />
|
||||
<Snackbar message={message.text} onClose={this.closeSnackbar} />
|
||||
|
||||
<Drawer onClick={this.closeMenu} position={DOCK_RIGHT} open={menu}>
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/account/repos">Repositories</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/account/token">Token</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/logout" target="_self">
|
||||
Logout
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<Drawer onClick={this.closeMenu} position={DOCK_RIGHT} open={menu}>
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/account/repos">Repositories</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/account/token">Token</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/logout" target="_self">
|
||||
Logout
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
closeSnackbar() {
|
||||
this.props.dispatch(tree => {
|
||||
tree.unset(["message", "text"]);
|
||||
});
|
||||
}
|
||||
closeSnackbar() {
|
||||
this.props.dispatch(tree => {
|
||||
tree.unset(["message", "text"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,28 +7,28 @@ import styles from "./index.less";
|
|||
const DEFAULT_ERROR = "The system failed to process your Login request.";
|
||||
|
||||
class Error extends Component {
|
||||
render() {
|
||||
const parsed = queryString.parse(window.location.search);
|
||||
let error = DEFAULT_ERROR;
|
||||
render() {
|
||||
const parsed = queryString.parse(window.location.search);
|
||||
let error = DEFAULT_ERROR;
|
||||
|
||||
switch (parsed.code || parsed.error) {
|
||||
case "oauth_error":
|
||||
break;
|
||||
case "access_denied":
|
||||
break;
|
||||
}
|
||||
switch (parsed.code || parsed.error) {
|
||||
case "oauth_error":
|
||||
break;
|
||||
case "access_denied":
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.alert}>
|
||||
<div>
|
||||
<Icon />
|
||||
</div>
|
||||
<div>{error}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.alert}>
|
||||
<div>
|
||||
<Icon />
|
||||
</div>
|
||||
<div>{error}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Error;
|
||||
|
|
|
@ -3,19 +3,19 @@ import React from "react";
|
|||
import styles from "./index.less";
|
||||
|
||||
const LoginForm = props => (
|
||||
<div className={styles.login}>
|
||||
<form method="post" action="/authorize">
|
||||
<p>Login with your version control system username and password.</p>
|
||||
<input
|
||||
placeholder="Username"
|
||||
name="username"
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
/>
|
||||
<input placeholder="Password" name="password" type="password" />
|
||||
<input value="Login" type="submit" />
|
||||
</form>
|
||||
</div>
|
||||
<div className={styles.login}>
|
||||
<form method="post" action="/authorize">
|
||||
<p>Login with your version control system username and password.</p>
|
||||
<input
|
||||
placeholder="Username"
|
||||
name="username"
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
/>
|
||||
<input placeholder="Password" name="password" type="password" />
|
||||
<input value="Login" type="submit" />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default LoginForm;
|
||||
|
|
|
@ -4,38 +4,38 @@ import { branch } from "baobab-react/higher-order";
|
|||
import { Message } from "shared/components/sync";
|
||||
|
||||
const binding = (props, context) => {
|
||||
return {
|
||||
feed: ["feed"],
|
||||
user: ["user", "data"],
|
||||
syncing: ["user", "syncing"],
|
||||
};
|
||||
return {
|
||||
feed: ["feed"],
|
||||
user: ["user", "data"],
|
||||
syncing: ["user", "syncing"],
|
||||
};
|
||||
};
|
||||
|
||||
@branch(binding)
|
||||
export default class RedirectRoot extends Component {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { user } = nextProps;
|
||||
if (!user && window) {
|
||||
window.location.href = "/login?url=" + window.location.href;
|
||||
}
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { user } = nextProps;
|
||||
if (!user && window) {
|
||||
window.location.href = "/login?url=" + window.location.href;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user, syncing } = this.props;
|
||||
const { latest, loaded } = this.props.feed;
|
||||
render() {
|
||||
const { user, syncing } = this.props;
|
||||
const { latest, loaded } = this.props.feed;
|
||||
|
||||
return !loaded && syncing ? (
|
||||
<Message />
|
||||
) : !loaded ? (
|
||||
undefined
|
||||
) : !user ? (
|
||||
undefined
|
||||
) : !latest ? (
|
||||
<Redirect to="/account/repos" />
|
||||
) : !latest.number ? (
|
||||
<Redirect to={`/${latest.full_name}`} />
|
||||
) : (
|
||||
<Redirect to={`/${latest.full_name}/${latest.number}`} />
|
||||
);
|
||||
}
|
||||
return !loaded && syncing ? (
|
||||
<Message />
|
||||
) : !loaded ? (
|
||||
undefined
|
||||
) : !user ? (
|
||||
undefined
|
||||
) : !latest ? (
|
||||
<Redirect to="/account/repos" />
|
||||
) : !latest.number ? (
|
||||
<Redirect to={`/${latest.full_name}`} />
|
||||
) : (
|
||||
<Redirect to={`/${latest.full_name}/${latest.number}`} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import React from "react";
|
|||
import style from "./approval.less";
|
||||
|
||||
export const Approval = ({ onapprove, ondecline }) => (
|
||||
<div className={style.root}>
|
||||
<p>Pipeline execution is blocked pending administrator approval</p>
|
||||
<button onClick={onapprove}>Approve</button>
|
||||
<button onClick={ondecline}>Decline</button>
|
||||
</div>
|
||||
<div className={style.root}>
|
||||
<p>Pipeline execution is blocked pending administrator approval</p>
|
||||
<button onClick={onapprove}>Approve</button>
|
||||
<button onClick={ondecline}>Decline</button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -7,36 +7,36 @@ import { StatusLabel } from "shared/components/status";
|
|||
import styles from "./details.less";
|
||||
|
||||
export class Details extends Component {
|
||||
render() {
|
||||
const { build } = this.props;
|
||||
render() {
|
||||
const { build } = this.props;
|
||||
|
||||
return (
|
||||
<div className={styles.info}>
|
||||
<StatusLabel status={build.status} />
|
||||
return (
|
||||
<div className={styles.info}>
|
||||
<StatusLabel status={build.status} />
|
||||
|
||||
<section className={styles.message} style={{ whiteSpace: "pre-line" }}>
|
||||
{build.message}
|
||||
</section>
|
||||
<section className={styles.message} style={{ whiteSpace: "pre-line" }}>
|
||||
{build.message}
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<BuildTime
|
||||
start={build.started_at || build.created_at}
|
||||
finish={build.finished_at}
|
||||
/>
|
||||
</section>
|
||||
<section>
|
||||
<BuildTime
|
||||
start={build.started_at || build.created_at}
|
||||
finish={build.finished_at}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<BuildMeta
|
||||
link={build.link_url}
|
||||
event={build.event}
|
||||
commit={build.commit}
|
||||
branch={build.branch}
|
||||
target={build.deploy_to}
|
||||
refspec={build.refspec}
|
||||
refs={build.ref}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<section>
|
||||
<BuildMeta
|
||||
link={build.link_url}
|
||||
event={build.event}
|
||||
commit={build.commit}
|
||||
branch={build.branch}
|
||||
target={build.deploy_to}
|
||||
refspec={build.refspec}
|
||||
refs={build.ref}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export class Elapsed extends Component {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
elapsed: 0,
|
||||
};
|
||||
this.state = {
|
||||
elapsed: 0,
|
||||
};
|
||||
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.timer = setInterval(this.tick, 1000);
|
||||
}
|
||||
componentDidMount() {
|
||||
this.timer = setInterval(this.tick, 1000);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
|
||||
tick() {
|
||||
const { start } = this.props;
|
||||
const stop = ~~(Date.now() / 1000);
|
||||
this.setState({
|
||||
elapsed: stop - start,
|
||||
});
|
||||
}
|
||||
tick() {
|
||||
const { start } = this.props;
|
||||
const stop = ~~(Date.now() / 1000);
|
||||
this.setState({
|
||||
elapsed: stop - start,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { elapsed } = this.state;
|
||||
const date = new Date(null);
|
||||
date.setSeconds(elapsed);
|
||||
return (
|
||||
<time>
|
||||
{!elapsed ? (
|
||||
undefined
|
||||
) : elapsed > 3600 ? (
|
||||
date.toISOString().substr(11, 8)
|
||||
) : (
|
||||
date.toISOString().substr(14, 5)
|
||||
)}
|
||||
</time>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { elapsed } = this.state;
|
||||
const date = new Date(null);
|
||||
date.setSeconds(elapsed);
|
||||
return (
|
||||
<time>
|
||||
{!elapsed ? (
|
||||
undefined
|
||||
) : elapsed > 3600 ? (
|
||||
date.toISOString().substr(11, 8)
|
||||
) : (
|
||||
date.toISOString().substr(14, 5)
|
||||
)}
|
||||
</time>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -53,11 +53,11 @@ export class Elapsed extends Component {
|
|||
* @return {string}
|
||||
*/
|
||||
export const formatTime = (end, start) => {
|
||||
const diff = end - start;
|
||||
const date = new Date(null);
|
||||
date.setSeconds(diff);
|
||||
const diff = end - start;
|
||||
const date = new Date(null);
|
||||
date.setSeconds(diff);
|
||||
|
||||
return diff > 3600
|
||||
? date.toISOString().substr(11, 8)
|
||||
: date.toISOString().substr(14, 5);
|
||||
return diff > 3600
|
||||
? date.toISOString().substr(11, 8)
|
||||
: date.toISOString().substr(14, 5);
|
||||
};
|
||||
|
|
|
@ -8,69 +8,69 @@ import { default as Status, StatusText } from "shared/components/status";
|
|||
import styles from "./procs.less";
|
||||
|
||||
const renderEnviron = data => {
|
||||
return (
|
||||
<div>
|
||||
{data[0]}={data[1]}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
{data[0]}={data[1]}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ProcListHolder = ({ vars, renderName, children }) => (
|
||||
<div className={styles.list}>
|
||||
{renderName && vars.name !== "drone" ? (
|
||||
<div>
|
||||
<StatusText status={vars.state} text={vars.name} />
|
||||
</div>
|
||||
) : null}
|
||||
{vars.environ ? (
|
||||
<div>
|
||||
<StatusText
|
||||
status={vars.state}
|
||||
text={Object.entries(vars.environ).map(renderEnviron)}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{children}
|
||||
</div>
|
||||
<div className={styles.list}>
|
||||
{renderName && vars.name !== "drone" ? (
|
||||
<div>
|
||||
<StatusText status={vars.state} text={vars.name} />
|
||||
</div>
|
||||
) : null}
|
||||
{vars.environ ? (
|
||||
<div>
|
||||
<StatusText
|
||||
status={vars.state}
|
||||
text={Object.entries(vars.environ).map(renderEnviron)}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export class ProcList extends Component {
|
||||
render() {
|
||||
const { repo, build, rootProc, selectedProc, renderName } = this.props;
|
||||
return (
|
||||
<ProcListHolder vars={rootProc} renderName={renderName}>
|
||||
{this.props.rootProc.children.map(function(child) {
|
||||
return (
|
||||
<Link
|
||||
to={`/${repo.full_name}/${build.number}/${child.pid}`}
|
||||
key={`${repo.full_name}-${build.number}-${child.pid}`}
|
||||
>
|
||||
<ProcListItem
|
||||
key={child.pid}
|
||||
name={child.name}
|
||||
start={child.start_time}
|
||||
finish={child.end_time}
|
||||
state={child.state}
|
||||
selected={child.pid === selectedProc.pid}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</ProcListHolder>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { repo, build, rootProc, selectedProc, renderName } = this.props;
|
||||
return (
|
||||
<ProcListHolder vars={rootProc} renderName={renderName}>
|
||||
{this.props.rootProc.children.map(function(child) {
|
||||
return (
|
||||
<Link
|
||||
to={`/${repo.full_name}/${build.number}/${child.pid}`}
|
||||
key={`${repo.full_name}-${build.number}-${child.pid}`}
|
||||
>
|
||||
<ProcListItem
|
||||
key={child.pid}
|
||||
name={child.name}
|
||||
start={child.start_time}
|
||||
finish={child.end_time}
|
||||
state={child.state}
|
||||
selected={child.pid === selectedProc.pid}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</ProcListHolder>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ProcListItem = ({ name, start, finish, state, selected }) => (
|
||||
<div className={classnames(styles.item, selected ? styles.selected : null)}>
|
||||
<h3>{name}</h3>
|
||||
{finish ? (
|
||||
<time>{formatTime(finish, start)}</time>
|
||||
) : (
|
||||
<Elapsed start={start} />
|
||||
)}
|
||||
<div>
|
||||
<Status status={state} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={classnames(styles.item, selected ? styles.selected : null)}>
|
||||
<h3>{name}</h3>
|
||||
{finish ? (
|
||||
<time>{formatTime(finish, start)}</time>
|
||||
) : (
|
||||
<Elapsed start={start} />
|
||||
)}
|
||||
<div>
|
||||
<Status status={state} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -3,9 +3,9 @@ import { Link } from "react-router-dom";
|
|||
|
||||
import { fetchBuild, approveBuild, declineBuild } from "shared/utils/build";
|
||||
import {
|
||||
STATUS_BLOCKED,
|
||||
STATUS_DECLINED,
|
||||
STATUS_ERROR,
|
||||
STATUS_BLOCKED,
|
||||
STATUS_DECLINED,
|
||||
STATUS_ERROR,
|
||||
} from "shared/constants/status";
|
||||
|
||||
import { findChildProcess } from "shared/utils/proc";
|
||||
|
@ -23,235 +23,235 @@ import Output from "./logs";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo, build } = props.match.params;
|
||||
const slug = `${owner}/${repo}`;
|
||||
const number = parseInt(build);
|
||||
const { owner, repo, build } = props.match.params;
|
||||
const slug = `${owner}/${repo}`;
|
||||
const number = parseInt(build);
|
||||
|
||||
return {
|
||||
repo: ["repos", "data", slug],
|
||||
build: ["builds", "data", slug, number],
|
||||
};
|
||||
return {
|
||||
repo: ["repos", "data", slug],
|
||||
build: ["builds", "data", slug, number],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class BuildLogs extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleApprove = this.handleApprove.bind(this);
|
||||
this.handleDecline = this.handleDecline.bind(this);
|
||||
}
|
||||
this.handleApprove = this.handleApprove.bind(this);
|
||||
this.handleDecline = this.handleDecline.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.synchronize(this.props);
|
||||
}
|
||||
componentWillMount() {
|
||||
this.synchronize(this.props);
|
||||
}
|
||||
|
||||
handleApprove() {
|
||||
const { repo, build, drone } = this.props;
|
||||
this.props.dispatch(
|
||||
approveBuild,
|
||||
drone,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
build.number,
|
||||
);
|
||||
}
|
||||
handleApprove() {
|
||||
const { repo, build, drone } = this.props;
|
||||
this.props.dispatch(
|
||||
approveBuild,
|
||||
drone,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
build.number,
|
||||
);
|
||||
}
|
||||
|
||||
handleDecline() {
|
||||
const { repo, build, drone } = this.props;
|
||||
this.props.dispatch(
|
||||
declineBuild,
|
||||
drone,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
build.number,
|
||||
);
|
||||
}
|
||||
handleDecline() {
|
||||
const { repo, build, drone } = this.props;
|
||||
this.props.dispatch(
|
||||
declineBuild,
|
||||
drone,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
build.number,
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
if (this.props.match.url !== nextProps.match.url) {
|
||||
this.synchronize(nextProps);
|
||||
}
|
||||
}
|
||||
componentWillUpdate(nextProps) {
|
||||
if (this.props.match.url !== nextProps.match.url) {
|
||||
this.synchronize(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
synchronize(props) {
|
||||
if (!props.repo) {
|
||||
this.props.dispatch(
|
||||
fetchRepository,
|
||||
props.drone,
|
||||
props.match.params.owner,
|
||||
props.match.params.repo,
|
||||
);
|
||||
}
|
||||
if (!props.build || !props.build.procs) {
|
||||
this.props.dispatch(
|
||||
fetchBuild,
|
||||
props.drone,
|
||||
props.match.params.owner,
|
||||
props.match.params.repo,
|
||||
props.match.params.build,
|
||||
);
|
||||
}
|
||||
}
|
||||
synchronize(props) {
|
||||
if (!props.repo) {
|
||||
this.props.dispatch(
|
||||
fetchRepository,
|
||||
props.drone,
|
||||
props.match.params.owner,
|
||||
props.match.params.repo,
|
||||
);
|
||||
}
|
||||
if (!props.build || !props.build.procs) {
|
||||
this.props.dispatch(
|
||||
fetchBuild,
|
||||
props.drone,
|
||||
props.match.params.owner,
|
||||
props.match.params.repo,
|
||||
props.match.params.build,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props !== nextProps;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props !== nextProps;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { repo, build } = this.props;
|
||||
render() {
|
||||
const { repo, build } = this.props;
|
||||
|
||||
if (!build || !repo) {
|
||||
return this.renderLoading();
|
||||
}
|
||||
if (!build || !repo) {
|
||||
return this.renderLoading();
|
||||
}
|
||||
|
||||
if (build.status === STATUS_DECLINED || build.status === STATUS_ERROR) {
|
||||
return this.renderError();
|
||||
}
|
||||
if (build.status === STATUS_DECLINED || build.status === STATUS_ERROR) {
|
||||
return this.renderError();
|
||||
}
|
||||
|
||||
if (build.status === STATUS_BLOCKED) {
|
||||
return this.renderBlocked();
|
||||
}
|
||||
if (build.status === STATUS_BLOCKED) {
|
||||
return this.renderBlocked();
|
||||
}
|
||||
|
||||
if (!build.procs) {
|
||||
return this.renderLoading();
|
||||
}
|
||||
if (!build.procs) {
|
||||
return this.renderLoading();
|
||||
}
|
||||
|
||||
return this.renderSimple();
|
||||
}
|
||||
return this.renderSimple();
|
||||
}
|
||||
|
||||
renderLoading() {
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>Loading ...</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
renderLoading() {
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>Loading ...</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderBlocked() {
|
||||
const { build } = this.props;
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>
|
||||
<Details build={build} />
|
||||
</div>
|
||||
<div className={styles.left}>
|
||||
<Approval
|
||||
onapprove={this.handleApprove}
|
||||
ondecline={this.handleDecline}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
renderBlocked() {
|
||||
const { build } = this.props;
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>
|
||||
<Details build={build} />
|
||||
</div>
|
||||
<div className={styles.left}>
|
||||
<Approval
|
||||
onapprove={this.handleApprove}
|
||||
ondecline={this.handleDecline}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderError() {
|
||||
const { build } = this.props;
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>
|
||||
<Details build={build} />
|
||||
</div>
|
||||
<div className={styles.left}>
|
||||
<div className={styles.logerror}>
|
||||
{build.status === STATUS_ERROR ? (
|
||||
build.error
|
||||
) : (
|
||||
"Pipeline execution was declined"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
renderError() {
|
||||
const { build } = this.props;
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>
|
||||
<Details build={build} />
|
||||
</div>
|
||||
<div className={styles.left}>
|
||||
<div className={styles.logerror}>
|
||||
{build.status === STATUS_ERROR ? (
|
||||
build.error
|
||||
) : (
|
||||
"Pipeline execution was declined"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
highlightedLine() {
|
||||
if (location.hash.startsWith("#L")) {
|
||||
return parseInt(location.hash.substr(2)) - 1;
|
||||
}
|
||||
highlightedLine() {
|
||||
if (location.hash.startsWith("#L")) {
|
||||
return parseInt(location.hash.substr(2)) - 1;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
renderSimple() {
|
||||
// if (nextProps.build.procs[0].children !== undefined){
|
||||
// return null;
|
||||
// }
|
||||
renderSimple() {
|
||||
// if (nextProps.build.procs[0].children !== undefined){
|
||||
// return null;
|
||||
// }
|
||||
|
||||
const { repo, build, match } = this.props;
|
||||
const selectedProc = match.params.proc
|
||||
? findChildProcess(build.procs, match.params.proc)
|
||||
: build.procs[0].children[0];
|
||||
const selectedProcParent = findChildProcess(build.procs, selectedProc.ppid);
|
||||
const highlighted = this.highlightedLine();
|
||||
const { repo, build, match } = this.props;
|
||||
const selectedProc = match.params.proc
|
||||
? findChildProcess(build.procs, match.params.proc)
|
||||
: build.procs[0].children[0];
|
||||
const selectedProcParent = findChildProcess(build.procs, selectedProc.ppid);
|
||||
const highlighted = this.highlightedLine();
|
||||
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>
|
||||
<Details build={build} />
|
||||
<section className={styles.sticky}>
|
||||
{build.procs.map(function(rootProc) {
|
||||
return (
|
||||
<div style="padding-bottom: 50px;" key={rootProc.pid}>
|
||||
<ProcList
|
||||
key={rootProc.pid}
|
||||
repo={repo}
|
||||
build={build}
|
||||
rootProc={rootProc}
|
||||
selectedProc={selectedProc}
|
||||
renderName={build.procs.length > 1}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</div>
|
||||
<div className={styles.left}>
|
||||
{selectedProc && selectedProc.error ? (
|
||||
<div className={styles.logerror}>{selectedProc.error}</div>
|
||||
) : null}
|
||||
{selectedProcParent && selectedProcParent.error ? (
|
||||
<div className={styles.logerror}>{selectedProcParent.error}</div>
|
||||
) : null}
|
||||
<Output
|
||||
match={this.props.match}
|
||||
build={this.props.build}
|
||||
proc={selectedProc}
|
||||
highlighted={highlighted}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.right}>
|
||||
<Details build={build} />
|
||||
<section className={styles.sticky}>
|
||||
{build.procs.map(function(rootProc) {
|
||||
return (
|
||||
<div style="padding-bottom: 50px;" key={rootProc.pid}>
|
||||
<ProcList
|
||||
key={rootProc.pid}
|
||||
repo={repo}
|
||||
build={build}
|
||||
rootProc={rootProc}
|
||||
selectedProc={selectedProc}
|
||||
renderName={build.procs.length > 1}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</div>
|
||||
<div className={styles.left}>
|
||||
{selectedProc && selectedProc.error ? (
|
||||
<div className={styles.logerror}>{selectedProc.error}</div>
|
||||
) : null}
|
||||
{selectedProcParent && selectedProcParent.error ? (
|
||||
<div className={styles.logerror}>{selectedProcParent.error}</div>
|
||||
) : null}
|
||||
<Output
|
||||
match={this.props.match}
|
||||
build={this.props.build}
|
||||
proc={selectedProc}
|
||||
highlighted={highlighted}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class BuildLogsTitle extends Component {
|
||||
render() {
|
||||
const { owner, repo, build } = this.props.match.params;
|
||||
return (
|
||||
<Breadcrumb
|
||||
elements={[
|
||||
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
||||
{owner} / {repo}
|
||||
</Link>,
|
||||
SEPARATOR,
|
||||
<Link
|
||||
to={`/${owner}/${repo}/${build}`}
|
||||
key={`${owner}-${repo}-${build}`}
|
||||
>
|
||||
{build}
|
||||
</Link>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { owner, repo, build } = this.props.match.params;
|
||||
return (
|
||||
<Breadcrumb
|
||||
elements={[
|
||||
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
||||
{owner} / {repo}
|
||||
</Link>,
|
||||
SEPARATOR,
|
||||
<Link
|
||||
to={`/${owner}/${repo}/${build}`}
|
||||
key={`${owner}-${repo}-${build}`}
|
||||
>
|
||||
{build}
|
||||
</Link>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ export const Top = () => <div className={styles.top} />;
|
|||
export const Bottom = () => <div className={styles.bottom} />;
|
||||
|
||||
export const scrollToTop = () => {
|
||||
document.querySelector(`.${styles.top}`).scrollIntoView();
|
||||
document.querySelector(`.${styles.top}`).scrollIntoView();
|
||||
};
|
||||
|
||||
export const scrollToBottom = () => {
|
||||
document.querySelector(`.${styles.bottom}`).scrollIntoView();
|
||||
document.querySelector(`.${styles.bottom}`).scrollIntoView();
|
||||
};
|
||||
|
|
|
@ -7,81 +7,81 @@ let formatter = new AnsiUp();
|
|||
formatter.use_classes = true;
|
||||
|
||||
class Term extends Component {
|
||||
render() {
|
||||
const { lines, exitcode, highlighted } = this.props;
|
||||
return (
|
||||
<div className={style.term}>
|
||||
{lines.map(line => renderTermLine(line, highlighted))}
|
||||
{exitcode !== undefined ? renderExitCode(exitcode) : undefined}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { lines, exitcode, highlighted } = this.props;
|
||||
return (
|
||||
<div className={style.term}>
|
||||
{lines.map(line => renderTermLine(line, highlighted))}
|
||||
{exitcode !== undefined ? renderExitCode(exitcode) : undefined}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.lines !== nextProps.lines ||
|
||||
this.props.exitcode !== nextProps.exitcode ||
|
||||
this.props.highlighted !== nextProps.highlighted
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.lines !== nextProps.lines ||
|
||||
this.props.exitcode !== nextProps.exitcode ||
|
||||
this.props.highlighted !== nextProps.highlighted
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TermLine extends Component {
|
||||
render() {
|
||||
const { line, highlighted } = this.props;
|
||||
return (
|
||||
<div
|
||||
className={highlighted === line.pos ? style.highlight : style.line}
|
||||
key={line.pos}
|
||||
ref={highlighted === line.pos ? ref => (this.ref = ref) : null}
|
||||
>
|
||||
<div>
|
||||
<Link to={`#L${line.pos + 1}`} key={line.pos + 1}>
|
||||
{line.pos + 1}
|
||||
</Link>
|
||||
</div>
|
||||
<div dangerouslySetInnerHTML={{ __html: this.colored }} />
|
||||
<div>{line.time || 0}s</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { line, highlighted } = this.props;
|
||||
return (
|
||||
<div
|
||||
className={highlighted === line.pos ? style.highlight : style.line}
|
||||
key={line.pos}
|
||||
ref={highlighted === line.pos ? ref => (this.ref = ref) : null}
|
||||
>
|
||||
<div>
|
||||
<Link to={`#L${line.pos + 1}`} key={line.pos + 1}>
|
||||
{line.pos + 1}
|
||||
</Link>
|
||||
</div>
|
||||
<div dangerouslySetInnerHTML={{ __html: this.colored }} />
|
||||
<div>{line.time || 0}s</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.ref !== undefined) {
|
||||
scrollToRef(this.ref);
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
if (this.ref !== undefined) {
|
||||
scrollToRef(this.ref);
|
||||
}
|
||||
}
|
||||
|
||||
get colored() {
|
||||
return formatter.ansi_to_html(this.props.line.out || "");
|
||||
}
|
||||
get colored() {
|
||||
return formatter.ansi_to_html(this.props.line.out || "");
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.line.out !== nextProps.line.out ||
|
||||
this.props.highlighted !== nextProps.highlighted
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.line.out !== nextProps.line.out ||
|
||||
this.props.highlighted !== nextProps.highlighted
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const renderTermLine = (line, highlighted) => {
|
||||
return <TermLine line={line} highlighted={highlighted} />;
|
||||
return <TermLine line={line} highlighted={highlighted} />;
|
||||
};
|
||||
|
||||
const renderExitCode = code => {
|
||||
return <div className={style.exitcode}>exit code {code}</div>;
|
||||
return <div className={style.exitcode}>exit code {code}</div>;
|
||||
};
|
||||
|
||||
const TermError = () => {
|
||||
return (
|
||||
<div className={style.error}>
|
||||
Oops. There was a problem loading the logs.
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={style.error}>
|
||||
Oops. There was a problem loading the logs.
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TermLoading = () => {
|
||||
return <div className={style.loading}>Loading ...</div>;
|
||||
return <div className={style.loading}>Loading ...</div>;
|
||||
};
|
||||
|
||||
const scrollToRef = ref => window.scrollTo(0, ref.offsetTop - 100);
|
||||
|
|
|
@ -14,104 +14,104 @@ import { ExpandIcon, PauseIcon, PlayIcon } from "shared/components/icons/index";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo, build } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const number = parseInt(build);
|
||||
const pid = parseInt(props.proc.pid);
|
||||
const { owner, repo, build } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const number = parseInt(build);
|
||||
const pid = parseInt(props.proc.pid);
|
||||
|
||||
return {
|
||||
logs: ["logs", "data", slug, number, pid, "data"],
|
||||
eof: ["logs", "data", slug, number, pid, "eof"],
|
||||
loading: ["logs", "data", slug, number, pid, "loading"],
|
||||
error: ["logs", "data", slug, number, pid, "error"],
|
||||
follow: ["logs", "follow"],
|
||||
};
|
||||
return {
|
||||
logs: ["logs", "data", slug, number, pid, "data"],
|
||||
eof: ["logs", "data", slug, number, pid, "eof"],
|
||||
loading: ["logs", "data", slug, number, pid, "loading"],
|
||||
error: ["logs", "data", slug, number, pid, "error"],
|
||||
follow: ["logs", "follow"],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class Output extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.handleFollow = this.handleFollow.bind(this);
|
||||
}
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.handleFollow = this.handleFollow.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
if (this.props.proc) {
|
||||
this.componentWillUpdate(this.props);
|
||||
}
|
||||
}
|
||||
componentWillMount() {
|
||||
if (this.props.proc) {
|
||||
this.componentWillUpdate(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
const { loading, logs, eof, error } = nextProps;
|
||||
const routeChange = this.props.match.url !== nextProps.match.url;
|
||||
componentWillUpdate(nextProps) {
|
||||
const { loading, logs, eof, error } = nextProps;
|
||||
const routeChange = this.props.match.url !== nextProps.match.url;
|
||||
|
||||
if (loading || error || (logs && eof)) {
|
||||
return;
|
||||
}
|
||||
if (loading || error || (logs && eof)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (assertProcFinished(nextProps.proc)) {
|
||||
return this.props.dispatch(
|
||||
fetchLogs,
|
||||
nextProps.drone,
|
||||
nextProps.match.params.owner,
|
||||
nextProps.match.params.repo,
|
||||
nextProps.build.number,
|
||||
nextProps.proc.pid,
|
||||
);
|
||||
}
|
||||
if (assertProcFinished(nextProps.proc)) {
|
||||
return this.props.dispatch(
|
||||
fetchLogs,
|
||||
nextProps.drone,
|
||||
nextProps.match.params.owner,
|
||||
nextProps.match.params.repo,
|
||||
nextProps.build.number,
|
||||
nextProps.proc.pid,
|
||||
);
|
||||
}
|
||||
|
||||
if (assertProcRunning(nextProps.proc) && (!logs || routeChange)) {
|
||||
this.props.dispatch(
|
||||
subscribeToLogs,
|
||||
nextProps.drone,
|
||||
nextProps.match.params.owner,
|
||||
nextProps.match.params.repo,
|
||||
nextProps.build.number,
|
||||
nextProps.proc,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (assertProcRunning(nextProps.proc) && (!logs || routeChange)) {
|
||||
this.props.dispatch(
|
||||
subscribeToLogs,
|
||||
nextProps.drone,
|
||||
nextProps.match.params.owner,
|
||||
nextProps.match.params.repo,
|
||||
nextProps.build.number,
|
||||
nextProps.proc,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.props.follow) {
|
||||
scrollToBottom();
|
||||
}
|
||||
}
|
||||
componentDidUpdate() {
|
||||
if (this.props.follow) {
|
||||
scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
handleFollow() {
|
||||
this.props.dispatch(toggleLogs, !this.props.follow);
|
||||
}
|
||||
handleFollow() {
|
||||
this.props.dispatch(toggleLogs, !this.props.follow);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { logs, error, proc, loading, follow, highlighted } = this.props;
|
||||
render() {
|
||||
const { logs, error, proc, loading, follow, highlighted } = this.props;
|
||||
|
||||
if (loading || !proc) {
|
||||
return <Term.Loading />;
|
||||
}
|
||||
if (loading || !proc) {
|
||||
return <Term.Loading />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <Term.Error />;
|
||||
}
|
||||
if (error) {
|
||||
return <Term.Error />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Top />
|
||||
<Term
|
||||
lines={logs || []}
|
||||
highlighted={highlighted}
|
||||
exitcode={assertProcFinished(proc) ? proc.exit_code : undefined}
|
||||
/>
|
||||
<Bottom />
|
||||
<Actions
|
||||
running={assertProcRunning(proc)}
|
||||
following={follow}
|
||||
onfollow={this.handleFollow}
|
||||
onunfollow={this.handleFollow}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Top />
|
||||
<Term
|
||||
lines={logs || []}
|
||||
highlighted={highlighted}
|
||||
exitcode={assertProcFinished(proc) ? proc.exit_code : undefined}
|
||||
/>
|
||||
<Bottom />
|
||||
<Actions
|
||||
running={assertProcRunning(proc)}
|
||||
following={follow}
|
||||
onfollow={this.handleFollow}
|
||||
onunfollow={this.handleFollow}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,25 +119,25 @@ export default class Output extends Component {
|
|||
* to follow, unfollow, scroll to top and scroll to bottom.
|
||||
*/
|
||||
const Actions = ({ following, running, onfollow, onunfollow }) => (
|
||||
<div className={styles.actions}>
|
||||
{running && !following ? (
|
||||
<button onClick={onfollow} className={styles.follow}>
|
||||
<PlayIcon />
|
||||
</button>
|
||||
) : null}
|
||||
<div className={styles.actions}>
|
||||
{running && !following ? (
|
||||
<button onClick={onfollow} className={styles.follow}>
|
||||
<PlayIcon />
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
{running && following ? (
|
||||
<button onClick={onunfollow} className={styles.unfollow}>
|
||||
<PauseIcon />
|
||||
</button>
|
||||
) : null}
|
||||
{running && following ? (
|
||||
<button onClick={onunfollow} className={styles.unfollow}>
|
||||
<PauseIcon />
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
<button onClick={scrollToTop} className={styles.bottom}>
|
||||
<ExpandIcon />
|
||||
</button>
|
||||
<button onClick={scrollToTop} className={styles.bottom}>
|
||||
<ExpandIcon />
|
||||
</button>
|
||||
|
||||
<button onClick={scrollToBottom} className={styles.top}>
|
||||
<ExpandIcon />
|
||||
</button>
|
||||
</div>
|
||||
<button onClick={scrollToBottom} className={styles.top}>
|
||||
<ExpandIcon />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -10,69 +10,69 @@ import { branch } from "baobab-react/higher-order";
|
|||
import { inject } from "config/client/inject";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo, build } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const number = parseInt(build);
|
||||
return {
|
||||
repo: ["repos", "data", slug],
|
||||
build: ["builds", "data", slug, number],
|
||||
};
|
||||
const { owner, repo, build } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const number = parseInt(build);
|
||||
return {
|
||||
repo: ["repos", "data", slug],
|
||||
build: ["builds", "data", slug, number],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class BuildMenu extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleCancel = this.handleCancel.bind(this);
|
||||
this.handleRestart = this.handleRestart.bind(this);
|
||||
}
|
||||
this.handleCancel = this.handleCancel.bind(this);
|
||||
this.handleRestart = this.handleRestart.bind(this);
|
||||
}
|
||||
|
||||
handleRestart() {
|
||||
const { dispatch, drone, repo, build } = this.props;
|
||||
dispatch(restartBuild, drone, repo.owner, repo.name, build.number);
|
||||
}
|
||||
handleRestart() {
|
||||
const { dispatch, drone, repo, build } = this.props;
|
||||
dispatch(restartBuild, drone, repo.owner, repo.name, build.number);
|
||||
}
|
||||
|
||||
handleCancel() {
|
||||
const { dispatch, drone, repo, build, match } = this.props;
|
||||
const proc = findChildProcess(build.procs, match.params.proc || 2);
|
||||
handleCancel() {
|
||||
const { dispatch, drone, repo, build, match } = this.props;
|
||||
const proc = findChildProcess(build.procs, match.params.proc || 2);
|
||||
|
||||
dispatch(
|
||||
cancelBuild,
|
||||
drone,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
build.number,
|
||||
proc.ppid,
|
||||
);
|
||||
}
|
||||
dispatch(
|
||||
cancelBuild,
|
||||
drone,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
build.number,
|
||||
proc.ppid,
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { build } = this.props;
|
||||
render() {
|
||||
const { build } = this.props;
|
||||
|
||||
const rightSide = !build ? (
|
||||
undefined
|
||||
) : (
|
||||
<section>
|
||||
{build.status === "pending" || build.status === "running" ? (
|
||||
<button onClick={this.handleCancel}>
|
||||
<CloseIcon />
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={this.handleRestart}>
|
||||
<RefreshIcon />
|
||||
<span>Restart Build</span>
|
||||
</button>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
const rightSide = !build ? (
|
||||
undefined
|
||||
) : (
|
||||
<section>
|
||||
{build.status === "pending" || build.status === "running" ? (
|
||||
<button onClick={this.handleCancel}>
|
||||
<CloseIcon />
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={this.handleRestart}>
|
||||
<RefreshIcon />
|
||||
<span>Restart Build</span>
|
||||
</button>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<RepoMenu {...this.props} right={rightSide} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<RepoMenu {...this.props} right={rightSide} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,48 +8,48 @@ import BuildMeta from "shared/components/build_event";
|
|||
import styles from "./list.less";
|
||||
|
||||
export const List = ({ children }) => (
|
||||
<div className={styles.list}>{children}</div>
|
||||
<div className={styles.list}>{children}</div>
|
||||
);
|
||||
|
||||
export class Item extends Component {
|
||||
render() {
|
||||
const { build } = this.props;
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div className={styles.icon}>
|
||||
<img src={build.author_avatar} />
|
||||
</div>
|
||||
render() {
|
||||
const { build } = this.props;
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div className={styles.icon}>
|
||||
<img src={build.author_avatar} />
|
||||
</div>
|
||||
|
||||
<div className={styles.body}>
|
||||
<h3>{build.message.split("\n")[0]}</h3>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<h3>{build.message.split("\n")[0]}</h3>
|
||||
</div>
|
||||
|
||||
<div className={styles.meta}>
|
||||
<BuildMeta
|
||||
link={build.link_url}
|
||||
event={build.event}
|
||||
commit={build.commit}
|
||||
branch={build.branch}
|
||||
target={build.deploy_to}
|
||||
refspec={build.refspec}
|
||||
refs={build.ref}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.meta}>
|
||||
<BuildMeta
|
||||
link={build.link_url}
|
||||
event={build.event}
|
||||
commit={build.commit}
|
||||
branch={build.branch}
|
||||
target={build.deploy_to}
|
||||
refspec={build.refspec}
|
||||
refs={build.ref}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.break} />
|
||||
<div className={styles.break} />
|
||||
|
||||
<div className={styles.time}>
|
||||
<BuildTime
|
||||
start={build.started_at || build.created_at}
|
||||
finish={build.finished_at}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.time}>
|
||||
<BuildTime
|
||||
start={build.started_at || build.created_at}
|
||||
finish={build.finished_at}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.status}>
|
||||
<StatusNumber status={build.status} number={build.number} />
|
||||
<Status status={build.status} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div className={styles.status}>
|
||||
<StatusNumber status={build.status} number={build.number} />
|
||||
<Status status={build.status} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,18 +3,18 @@ import { Link } from "react-router-dom";
|
|||
import Breadcrumb from "shared/components/breadcrumb";
|
||||
|
||||
export default class Header extends Component {
|
||||
render() {
|
||||
const { owner, repo } = this.props.match.params;
|
||||
return (
|
||||
<div>
|
||||
<Breadcrumb
|
||||
elements={[
|
||||
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
||||
{owner} / {repo}
|
||||
</Link>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { owner, repo } = this.props.match.params;
|
||||
return (
|
||||
<div>
|
||||
<Breadcrumb
|
||||
elements={[
|
||||
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
||||
{owner} / {repo}
|
||||
</Link>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,114 +11,114 @@ import { inject } from "config/client/inject";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
repo: ["repos", "data", slug],
|
||||
builds: ["builds", "data", slug],
|
||||
loaded: ["builds", "loaded"],
|
||||
error: ["builds", "error"],
|
||||
};
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
repo: ["repos", "data", slug],
|
||||
builds: ["builds", "data", slug],
|
||||
loaded: ["builds", "loaded"],
|
||||
error: ["builds", "error"],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class Main extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.fetchNextBuildPage = this.fetchNextBuildPage.bind(this);
|
||||
}
|
||||
this.fetchNextBuildPage = this.fetchNextBuildPage.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.synchronize(this.props);
|
||||
}
|
||||
componentWillMount() {
|
||||
this.synchronize(this.props);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.repo !== nextProps.repo ||
|
||||
(nextProps.builds !== undefined &&
|
||||
this.props.builds !== nextProps.builds) ||
|
||||
this.props.error !== nextProps.error ||
|
||||
this.props.loaded !== nextProps.loaded
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.repo !== nextProps.repo ||
|
||||
(nextProps.builds !== undefined &&
|
||||
this.props.builds !== nextProps.builds) ||
|
||||
this.props.error !== nextProps.error ||
|
||||
this.props.loaded !== nextProps.loaded
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
if (this.props.match.url !== nextProps.match.url) {
|
||||
this.synchronize(nextProps);
|
||||
}
|
||||
}
|
||||
componentWillUpdate(nextProps) {
|
||||
if (this.props.match.url !== nextProps.match.url) {
|
||||
this.synchronize(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.location !== prevProps.location) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.location !== prevProps.location) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
synchronize(props) {
|
||||
const { drone, dispatch, match, repo } = props;
|
||||
synchronize(props) {
|
||||
const { drone, dispatch, match, repo } = props;
|
||||
|
||||
if (!repo) {
|
||||
dispatch(fetchRepository, drone, match.params.owner, match.params.repo);
|
||||
}
|
||||
if (!repo) {
|
||||
dispatch(fetchRepository, drone, match.params.owner, match.params.repo);
|
||||
}
|
||||
|
||||
dispatch(fetchBuildList, drone, match.params.owner, match.params.repo);
|
||||
}
|
||||
dispatch(fetchBuildList, drone, match.params.owner, match.params.repo);
|
||||
}
|
||||
|
||||
fetchNextBuildPage(buildList) {
|
||||
const { drone, dispatch, match } = this.props;
|
||||
const page = Math.floor(buildList.length / 50) + 1;
|
||||
fetchNextBuildPage(buildList) {
|
||||
const { drone, dispatch, match } = this.props;
|
||||
const page = Math.floor(buildList.length / 50) + 1;
|
||||
|
||||
dispatch(
|
||||
fetchBuildList,
|
||||
drone,
|
||||
match.params.owner,
|
||||
match.params.repo,
|
||||
page,
|
||||
);
|
||||
}
|
||||
dispatch(
|
||||
fetchBuildList,
|
||||
drone,
|
||||
match.params.owner,
|
||||
match.params.repo,
|
||||
page,
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { repo, builds, loaded, error } = this.props;
|
||||
const list = Object.values(builds || {});
|
||||
render() {
|
||||
const { repo, builds, loaded, error } = this.props;
|
||||
const list = Object.values(builds || {});
|
||||
|
||||
function renderBuild(build) {
|
||||
return (
|
||||
<Link to={`/${repo.full_name}/${build.number}`} key={build.number}>
|
||||
<Item build={build} />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
function renderBuild(build) {
|
||||
return (
|
||||
<Link to={`/${repo.full_name}/${build.number}`} key={build.number}>
|
||||
<Item build={build} />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div>Not Found</div>;
|
||||
}
|
||||
if (error) {
|
||||
return <div>Not Found</div>;
|
||||
}
|
||||
|
||||
if (!loaded && list.length === 0) {
|
||||
return <div>Loading</div>;
|
||||
}
|
||||
if (!loaded && list.length === 0) {
|
||||
return <div>Loading</div>;
|
||||
}
|
||||
|
||||
if (!repo) {
|
||||
return <div>Loading</div>;
|
||||
}
|
||||
if (!repo) {
|
||||
return <div>Loading</div>;
|
||||
}
|
||||
|
||||
if (list.length === 0) {
|
||||
return <div>Build list is empty</div>;
|
||||
}
|
||||
if (list.length === 0) {
|
||||
return <div>Build list is empty</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<List>{list.sort(compareBuild).map(renderBuild)}</List>
|
||||
{list.length < repo.last_build && (
|
||||
<button
|
||||
onClick={() => this.fetchNextBuildPage(list)}
|
||||
className={styles.more}
|
||||
>
|
||||
Show more builds
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<List>{list.sort(compareBuild).map(renderBuild)}</List>
|
||||
{list.length < repo.last_build && (
|
||||
<button
|
||||
onClick={() => this.fetchNextBuildPage(list)}
|
||||
className={styles.more}
|
||||
>
|
||||
Show more builds
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ import React, { Component } from "react";
|
|||
import Menu from "shared/components/menu";
|
||||
|
||||
export default class RepoMenu extends Component {
|
||||
render() {
|
||||
const { owner, repo } = this.props.match.params;
|
||||
const menu = [
|
||||
{ to: `/${owner}/${repo}`, label: "Builds" },
|
||||
{ to: `/${owner}/${repo}/settings/secrets`, label: "Secrets" },
|
||||
{ to: `/${owner}/${repo}/settings/registry`, label: "Registry" },
|
||||
{ to: `/${owner}/${repo}/settings`, label: "Settings" },
|
||||
];
|
||||
return <Menu items={menu} {...this.props} />;
|
||||
}
|
||||
render() {
|
||||
const { owner, repo } = this.props.match.params;
|
||||
const menu = [
|
||||
{ to: `/${owner}/${repo}`, label: "Builds" },
|
||||
{ to: `/${owner}/${repo}/settings/secrets`, label: "Secrets" },
|
||||
{ to: `/${owner}/${repo}/settings/registry`, label: "Registry" },
|
||||
{ to: `/${owner}/${repo}/settings`, label: "Settings" },
|
||||
];
|
||||
return <Menu items={menu} {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,79 +2,79 @@ import React, { Component } from "react";
|
|||
import styles from "./form.less";
|
||||
|
||||
export class Form extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
address: "",
|
||||
username: "",
|
||||
password: "",
|
||||
};
|
||||
this.state = {
|
||||
address: "",
|
||||
username: "",
|
||||
password: "",
|
||||
};
|
||||
|
||||
this._handleAddressChange = this._handleAddressChange.bind(this);
|
||||
this._handleUsernameChange = this._handleUsernameChange.bind(this);
|
||||
this._handlePasswordChange = this._handlePasswordChange.bind(this);
|
||||
this._handleSubmit = this._handleSubmit.bind(this);
|
||||
this._handleAddressChange = this._handleAddressChange.bind(this);
|
||||
this._handleUsernameChange = this._handleUsernameChange.bind(this);
|
||||
this._handlePasswordChange = this._handlePasswordChange.bind(this);
|
||||
this._handleSubmit = this._handleSubmit.bind(this);
|
||||
|
||||
this.clear = this.clear.bind(this);
|
||||
}
|
||||
this.clear = this.clear.bind(this);
|
||||
}
|
||||
|
||||
_handleAddressChange(event) {
|
||||
this.setState({ address: event.target.value });
|
||||
}
|
||||
_handleAddressChange(event) {
|
||||
this.setState({ address: event.target.value });
|
||||
}
|
||||
|
||||
_handleUsernameChange(event) {
|
||||
this.setState({ username: event.target.value });
|
||||
}
|
||||
_handleUsernameChange(event) {
|
||||
this.setState({ username: event.target.value });
|
||||
}
|
||||
|
||||
_handlePasswordChange(event) {
|
||||
this.setState({ password: event.target.value });
|
||||
}
|
||||
_handlePasswordChange(event) {
|
||||
this.setState({ password: event.target.value });
|
||||
}
|
||||
|
||||
_handleSubmit() {
|
||||
const { onsubmit } = this.props;
|
||||
_handleSubmit() {
|
||||
const { onsubmit } = this.props;
|
||||
|
||||
const detail = {
|
||||
address: this.state.address,
|
||||
username: this.state.username,
|
||||
password: this.state.password,
|
||||
};
|
||||
const detail = {
|
||||
address: this.state.address,
|
||||
username: this.state.username,
|
||||
password: this.state.password,
|
||||
};
|
||||
|
||||
onsubmit({ detail });
|
||||
this.clear();
|
||||
}
|
||||
onsubmit({ detail });
|
||||
this.clear();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.setState({ address: "" });
|
||||
this.setState({ username: "" });
|
||||
this.setState({ password: "" });
|
||||
}
|
||||
clear() {
|
||||
this.setState({ address: "" });
|
||||
this.setState({ username: "" });
|
||||
this.setState({ password: "" });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.form}>
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.address}
|
||||
onChange={this._handleAddressChange}
|
||||
placeholder="Registry Address (e.g. docker.io)"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.username}
|
||||
onChange={this._handleUsernameChange}
|
||||
placeholder="Registry Username"
|
||||
/>
|
||||
<textarea
|
||||
rows="1"
|
||||
value={this.state.password}
|
||||
onChange={this._handlePasswordChange}
|
||||
placeholder="Registry Password"
|
||||
/>
|
||||
<div className={styles.actions}>
|
||||
<button onClick={this._handleSubmit}>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.form}>
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.address}
|
||||
onChange={this._handleAddressChange}
|
||||
placeholder="Registry Address (e.g. docker.io)"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.username}
|
||||
onChange={this._handleUsernameChange}
|
||||
placeholder="Registry Username"
|
||||
/>
|
||||
<textarea
|
||||
rows="1"
|
||||
value={this.state.password}
|
||||
onChange={this._handlePasswordChange}
|
||||
placeholder="Registry Password"
|
||||
/>
|
||||
<div className={styles.actions}>
|
||||
<button onClick={this._handleSubmit}>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ import React from "react";
|
|||
import styles from "./list.less";
|
||||
|
||||
export const List = ({ children }) => (
|
||||
<div className={styles.list}>{children}</div>
|
||||
<div className={styles.list}>{children}</div>
|
||||
);
|
||||
|
||||
export const Item = props => (
|
||||
<div className={styles.item} key={props.name}>
|
||||
<div>{props.name}</div>
|
||||
<div>
|
||||
<button onClick={props.ondelete}>delete</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.item} key={props.name}>
|
||||
<div>{props.name}</div>
|
||||
<div>
|
||||
<button onClick={props.ondelete}>delete</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -2,9 +2,9 @@ import React, { Component } from "react";
|
|||
|
||||
import { repositorySlug } from "shared/utils/repository";
|
||||
import {
|
||||
fetchRegistryList,
|
||||
createRegistry,
|
||||
deleteRegistry,
|
||||
fetchRegistryList,
|
||||
createRegistry,
|
||||
deleteRegistry,
|
||||
} from "shared/utils/registry";
|
||||
|
||||
import { branch } from "baobab-react/higher-order";
|
||||
|
@ -15,89 +15,89 @@ import { List, Item, Form } from "./components";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
loaded: ["registry", "loaded"],
|
||||
registries: ["registry", "data", slug],
|
||||
};
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
loaded: ["registry", "loaded"],
|
||||
registries: ["registry", "data", slug],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class RepoRegistry extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleDelete = this.handleDelete.bind(this);
|
||||
this.handleSave = this.handleSave.bind(this);
|
||||
}
|
||||
this.handleDelete = this.handleDelete.bind(this);
|
||||
this.handleSave = this.handleSave.bind(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.registries !== nextProps.registries;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.registries !== nextProps.registries;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
dispatch(fetchRegistryList, drone, owner, repo);
|
||||
}
|
||||
componentWillMount() {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
dispatch(fetchRegistryList, drone, owner, repo);
|
||||
}
|
||||
|
||||
handleSave(e) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
const registry = {
|
||||
address: e.detail.address,
|
||||
username: e.detail.username,
|
||||
password: e.detail.password,
|
||||
};
|
||||
handleSave(e) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
const registry = {
|
||||
address: e.detail.address,
|
||||
username: e.detail.username,
|
||||
password: e.detail.password,
|
||||
};
|
||||
|
||||
dispatch(createRegistry, drone, owner, repo, registry);
|
||||
}
|
||||
dispatch(createRegistry, drone, owner, repo, registry);
|
||||
}
|
||||
|
||||
handleDelete(registry) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
dispatch(deleteRegistry, drone, owner, repo, registry.address);
|
||||
}
|
||||
handleDelete(registry) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
dispatch(deleteRegistry, drone, owner, repo, registry.address);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { registries, loaded } = this.props;
|
||||
render() {
|
||||
const { registries, loaded } = this.props;
|
||||
|
||||
if (!loaded) {
|
||||
return LOADING;
|
||||
}
|
||||
if (!loaded) {
|
||||
return LOADING;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.left}>
|
||||
{Object.keys(registries || {}).length === 0 ? EMPTY : undefined}
|
||||
<List>
|
||||
{Object.values(registries || {}).map(renderRegistry.bind(this))}
|
||||
</List>
|
||||
</div>
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.left}>
|
||||
{Object.keys(registries || {}).length === 0 ? EMPTY : undefined}
|
||||
<List>
|
||||
{Object.values(registries || {}).map(renderRegistry.bind(this))}
|
||||
</List>
|
||||
</div>
|
||||
|
||||
<div className={styles.right}>
|
||||
<Form onsubmit={this.handleSave} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div className={styles.right}>
|
||||
<Form onsubmit={this.handleSave} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function renderRegistry(registry) {
|
||||
return (
|
||||
<Item
|
||||
name={registry.address}
|
||||
ondelete={this.handleDelete.bind(this, registry)}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Item
|
||||
name={registry.address}
|
||||
ondelete={this.handleDelete.bind(this, registry)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const LOADING = <div className={styles.loading}>Loading</div>;
|
||||
|
||||
const EMPTY = (
|
||||
<div className={styles.empty}>
|
||||
There are no registry credentials for this repository.
|
||||
</div>
|
||||
<div className={styles.empty}>
|
||||
There are no registry credentials for this repository.
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,140 +1,140 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
import {
|
||||
EVENT_PUSH,
|
||||
EVENT_TAG,
|
||||
EVENT_PULL_REQUEST,
|
||||
EVENT_DEPLOY,
|
||||
EVENT_PUSH,
|
||||
EVENT_TAG,
|
||||
EVENT_PULL_REQUEST,
|
||||
EVENT_DEPLOY,
|
||||
} from "shared/constants/events";
|
||||
|
||||
import styles from "./form.less";
|
||||
|
||||
export class Form extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
name: "",
|
||||
value: "",
|
||||
event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY],
|
||||
};
|
||||
this.state = {
|
||||
name: "",
|
||||
value: "",
|
||||
event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY],
|
||||
};
|
||||
|
||||
this._handleNameChange = this._handleNameChange.bind(this);
|
||||
this._handleValueChange = this._handleValueChange.bind(this);
|
||||
this._handleEventChange = this._handleEventChange.bind(this);
|
||||
this._handleSubmit = this._handleSubmit.bind(this);
|
||||
this._handleNameChange = this._handleNameChange.bind(this);
|
||||
this._handleValueChange = this._handleValueChange.bind(this);
|
||||
this._handleEventChange = this._handleEventChange.bind(this);
|
||||
this._handleSubmit = this._handleSubmit.bind(this);
|
||||
|
||||
this.clear = this.clear.bind(this);
|
||||
}
|
||||
this.clear = this.clear.bind(this);
|
||||
}
|
||||
|
||||
_handleNameChange(event) {
|
||||
this.setState({ name: event.target.value });
|
||||
}
|
||||
_handleNameChange(event) {
|
||||
this.setState({ name: event.target.value });
|
||||
}
|
||||
|
||||
_handleValueChange(event) {
|
||||
this.setState({ value: event.target.value });
|
||||
}
|
||||
_handleValueChange(event) {
|
||||
this.setState({ value: event.target.value });
|
||||
}
|
||||
|
||||
_handleEventChange(event) {
|
||||
const selected = this.state.event;
|
||||
let index;
|
||||
_handleEventChange(event) {
|
||||
const selected = this.state.event;
|
||||
let index;
|
||||
|
||||
if (event.target.checked) {
|
||||
selected.push(event.target.value);
|
||||
} else {
|
||||
index = selected.indexOf(event.target.value);
|
||||
selected.splice(index, 1);
|
||||
}
|
||||
if (event.target.checked) {
|
||||
selected.push(event.target.value);
|
||||
} else {
|
||||
index = selected.indexOf(event.target.value);
|
||||
selected.splice(index, 1);
|
||||
}
|
||||
|
||||
this.setState({ event: selected });
|
||||
}
|
||||
this.setState({ event: selected });
|
||||
}
|
||||
|
||||
_handleSubmit() {
|
||||
const { onsubmit } = this.props;
|
||||
_handleSubmit() {
|
||||
const { onsubmit } = this.props;
|
||||
|
||||
const detail = {
|
||||
name: this.state.name,
|
||||
value: this.state.value,
|
||||
event: this.state.event,
|
||||
};
|
||||
const detail = {
|
||||
name: this.state.name,
|
||||
value: this.state.value,
|
||||
event: this.state.event,
|
||||
};
|
||||
|
||||
onsubmit({ detail });
|
||||
this.clear();
|
||||
}
|
||||
onsubmit({ detail });
|
||||
this.clear();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.setState({ name: "" });
|
||||
this.setState({ value: "" });
|
||||
this.setState({ event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY] });
|
||||
}
|
||||
clear() {
|
||||
this.setState({ name: "" });
|
||||
this.setState({ value: "" });
|
||||
this.setState({ event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY] });
|
||||
}
|
||||
|
||||
render() {
|
||||
let checked = this.state.event.reduce((map, event) => {
|
||||
map[event] = true;
|
||||
return map;
|
||||
}, {});
|
||||
render() {
|
||||
let checked = this.state.event.reduce((map, event) => {
|
||||
map[event] = true;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
return (
|
||||
<div className={styles.form}>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={this.state.name}
|
||||
placeholder="Secret Name"
|
||||
onChange={this._handleNameChange}
|
||||
/>
|
||||
<textarea
|
||||
rows="1"
|
||||
name="value"
|
||||
value={this.state.value}
|
||||
placeholder="Secret Value"
|
||||
onChange={this._handleValueChange}
|
||||
/>
|
||||
<section>
|
||||
<h2>Events</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_PUSH]}
|
||||
value={EVENT_PUSH}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>push</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_TAG]}
|
||||
value={EVENT_TAG}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>tag</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_PULL_REQUEST]}
|
||||
value={EVENT_PULL_REQUEST}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>pull request</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_DEPLOY]}
|
||||
value={EVENT_DEPLOY}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>deploy</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<div className={styles.actions}>
|
||||
<button onClick={this._handleSubmit}>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.form}>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={this.state.name}
|
||||
placeholder="Secret Name"
|
||||
onChange={this._handleNameChange}
|
||||
/>
|
||||
<textarea
|
||||
rows="1"
|
||||
name="value"
|
||||
value={this.state.value}
|
||||
placeholder="Secret Value"
|
||||
onChange={this._handleValueChange}
|
||||
/>
|
||||
<section>
|
||||
<h2>Events</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_PUSH]}
|
||||
value={EVENT_PUSH}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>push</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_TAG]}
|
||||
value={EVENT_TAG}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>tag</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_PULL_REQUEST]}
|
||||
value={EVENT_PULL_REQUEST}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>pull request</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked[EVENT_DEPLOY]}
|
||||
value={EVENT_DEPLOY}
|
||||
onChange={this._handleEventChange}
|
||||
/>
|
||||
<span>deploy</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<div className={styles.actions}>
|
||||
<button onClick={this._handleSubmit}>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,17 @@ import styles from "./list.less";
|
|||
export const List = ({ children }) => <div>{children}</div>;
|
||||
|
||||
export const Item = props => (
|
||||
<div className={styles.item} key={props.name}>
|
||||
<div>
|
||||
{props.name}
|
||||
<ul>{props.event ? props.event.map(renderEvent) : null}</ul>
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={props.ondelete}>delete</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.item} key={props.name}>
|
||||
<div>
|
||||
{props.name}
|
||||
<ul>{props.event ? props.event.map(renderEvent) : null}</ul>
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={props.ondelete}>delete</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderEvent = event => {
|
||||
return <li>{event}</li>;
|
||||
return <li>{event}</li>;
|
||||
};
|
||||
|
|
|
@ -2,9 +2,9 @@ import React, { Component } from "react";
|
|||
|
||||
import { repositorySlug } from "shared/utils/repository";
|
||||
import {
|
||||
fetchSecretList,
|
||||
createSecret,
|
||||
deleteSecret,
|
||||
fetchSecretList,
|
||||
createSecret,
|
||||
deleteSecret,
|
||||
} from "shared/utils/secrets";
|
||||
|
||||
import { branch } from "baobab-react/higher-order";
|
||||
|
@ -15,85 +15,85 @@ import { List, Item, Form } from "./components";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
loaded: ["secrets", "loaded"],
|
||||
secrets: ["secrets", "data", slug],
|
||||
};
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
loaded: ["secrets", "loaded"],
|
||||
secrets: ["secrets", "data", slug],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class RepoSecrets extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleSave = this.handleSave.bind(this);
|
||||
}
|
||||
this.handleSave = this.handleSave.bind(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.secrets !== nextProps.secrets;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.secrets !== nextProps.secrets;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { owner, repo } = this.props.match.params;
|
||||
this.props.dispatch(fetchSecretList, this.props.drone, owner, repo);
|
||||
}
|
||||
componentWillMount() {
|
||||
const { owner, repo } = this.props.match.params;
|
||||
this.props.dispatch(fetchSecretList, this.props.drone, owner, repo);
|
||||
}
|
||||
|
||||
handleSave(e) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
const secret = {
|
||||
name: e.detail.name,
|
||||
value: e.detail.value,
|
||||
event: e.detail.event,
|
||||
};
|
||||
handleSave(e) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
const secret = {
|
||||
name: e.detail.name,
|
||||
value: e.detail.value,
|
||||
event: e.detail.event,
|
||||
};
|
||||
|
||||
dispatch(createSecret, drone, owner, repo, secret);
|
||||
}
|
||||
dispatch(createSecret, drone, owner, repo, secret);
|
||||
}
|
||||
|
||||
handleDelete(secret) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
dispatch(deleteSecret, drone, owner, repo, secret.name);
|
||||
}
|
||||
handleDelete(secret) {
|
||||
const { dispatch, drone, match } = this.props;
|
||||
const { owner, repo } = match.params;
|
||||
dispatch(deleteSecret, drone, owner, repo, secret.name);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { secrets, loaded } = this.props;
|
||||
render() {
|
||||
const { secrets, loaded } = this.props;
|
||||
|
||||
if (!loaded) {
|
||||
return LOADING;
|
||||
}
|
||||
if (!loaded) {
|
||||
return LOADING;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.left}>
|
||||
{Object.keys(secrets || {}).length === 0 ? EMPTY : undefined}
|
||||
<List>
|
||||
{Object.values(secrets || {}).map(renderSecret.bind(this))}
|
||||
</List>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
<Form onsubmit={this.handleSave} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.left}>
|
||||
{Object.keys(secrets || {}).length === 0 ? EMPTY : undefined}
|
||||
<List>
|
||||
{Object.values(secrets || {}).map(renderSecret.bind(this))}
|
||||
</List>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
<Form onsubmit={this.handleSave} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function renderSecret(secret) {
|
||||
return (
|
||||
<Item
|
||||
name={secret.name}
|
||||
event={secret.event}
|
||||
ondelete={this.handleDelete.bind(this, secret)}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Item
|
||||
name={secret.name}
|
||||
event={secret.event}
|
||||
ondelete={this.handleDelete.bind(this, secret)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const LOADING = <div className={styles.loading}>Loading</div>;
|
||||
|
||||
const EMPTY = (
|
||||
<div className={styles.empty}>There are no secrets for this repository.</div>
|
||||
<div className={styles.empty}>There are no secrets for this repository.</div>
|
||||
);
|
||||
|
|
|
@ -4,241 +4,241 @@ import { branch } from "baobab-react/higher-order";
|
|||
import { inject } from "config/client/inject";
|
||||
|
||||
import {
|
||||
fetchRepository,
|
||||
updateRepository,
|
||||
repositorySlug,
|
||||
fetchRepository,
|
||||
updateRepository,
|
||||
repositorySlug,
|
||||
} from "shared/utils/repository";
|
||||
|
||||
import {
|
||||
VISIBILITY_PUBLIC,
|
||||
VISIBILITY_PRIVATE,
|
||||
VISIBILITY_INTERNAL,
|
||||
VISIBILITY_PUBLIC,
|
||||
VISIBILITY_PRIVATE,
|
||||
VISIBILITY_INTERNAL,
|
||||
} from "shared/constants/visibility";
|
||||
|
||||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
user: ["user", "data"],
|
||||
repo: ["repos", "data", slug],
|
||||
};
|
||||
const { owner, repo } = props.match.params;
|
||||
const slug = repositorySlug(owner, repo);
|
||||
return {
|
||||
user: ["user", "data"],
|
||||
repo: ["repos", "data", slug],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class Settings extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handlePushChange = this.handlePushChange.bind(this);
|
||||
this.handlePullChange = this.handlePullChange.bind(this);
|
||||
this.handleTagChange = this.handleTagChange.bind(this);
|
||||
this.handleDeployChange = this.handleDeployChange.bind(this);
|
||||
this.handleTrustedChange = this.handleTrustedChange.bind(this);
|
||||
this.handleProtectedChange = this.handleProtectedChange.bind(this);
|
||||
this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
|
||||
this.handleTimeoutChange = this.handleTimeoutChange.bind(this);
|
||||
this.handlePathChange = this.handlePathChange.bind(this);
|
||||
this.handleFallbackChange = this.handleFallbackChange.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
this.handlePushChange = this.handlePushChange.bind(this);
|
||||
this.handlePullChange = this.handlePullChange.bind(this);
|
||||
this.handleTagChange = this.handleTagChange.bind(this);
|
||||
this.handleDeployChange = this.handleDeployChange.bind(this);
|
||||
this.handleTrustedChange = this.handleTrustedChange.bind(this);
|
||||
this.handleProtectedChange = this.handleProtectedChange.bind(this);
|
||||
this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
|
||||
this.handleTimeoutChange = this.handleTimeoutChange.bind(this);
|
||||
this.handlePathChange = this.handlePathChange.bind(this);
|
||||
this.handleFallbackChange = this.handleFallbackChange.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.repo !== nextProps.repo;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.repo !== nextProps.repo;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { drone, dispatch, match, repo } = this.props;
|
||||
componentWillMount() {
|
||||
const { drone, dispatch, match, repo } = this.props;
|
||||
|
||||
if (!repo) {
|
||||
dispatch(fetchRepository, drone, match.params.owner, match.params.repo);
|
||||
}
|
||||
}
|
||||
if (!repo) {
|
||||
dispatch(fetchRepository, drone, match.params.owner, match.params.repo);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { repo } = this.props;
|
||||
render() {
|
||||
const { repo } = this.props;
|
||||
|
||||
if (!repo) {
|
||||
return undefined;
|
||||
}
|
||||
if (!repo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<section>
|
||||
<h2>Pipeline Path</h2>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
value={repo.config_file}
|
||||
onBlur={this.handlePathChange}
|
||||
/>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.fallback}
|
||||
onChange={this.handleFallbackChange}
|
||||
/>
|
||||
<span>Fallback to .drone.yml if path not exists</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Repository Hooks</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_push}
|
||||
onChange={this.handlePushChange}
|
||||
/>
|
||||
<span>push</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_pr}
|
||||
onChange={this.handlePullChange}
|
||||
/>
|
||||
<span>pull request</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_tags}
|
||||
onChange={this.handleTagChange}
|
||||
/>
|
||||
<span>tag</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_deploys}
|
||||
onChange={this.handleDeployChange}
|
||||
/>
|
||||
<span>deployment</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<section>
|
||||
<h2>Pipeline Path</h2>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
value={repo.config_file}
|
||||
onBlur={this.handlePathChange}
|
||||
/>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.fallback}
|
||||
onChange={this.handleFallbackChange}
|
||||
/>
|
||||
<span>Fallback to .drone.yml if path not exists</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Repository Hooks</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_push}
|
||||
onChange={this.handlePushChange}
|
||||
/>
|
||||
<span>push</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_pr}
|
||||
onChange={this.handlePullChange}
|
||||
/>
|
||||
<span>pull request</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_tags}
|
||||
onChange={this.handleTagChange}
|
||||
/>
|
||||
<span>tag</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.allow_deploys}
|
||||
onChange={this.handleDeployChange}
|
||||
/>
|
||||
<span>deployment</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Project Settings</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.gated}
|
||||
onChange={this.handleProtectedChange}
|
||||
/>
|
||||
<span>Protected</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.trusted}
|
||||
onChange={this.handleTrustedChange}
|
||||
/>
|
||||
<span>Trusted</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Project Settings</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.gated}
|
||||
onChange={this.handleProtectedChange}
|
||||
/>
|
||||
<span>Protected</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={repo.trusted}
|
||||
onChange={this.handleTrustedChange}
|
||||
/>
|
||||
<span>Trusted</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Project Visibility</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="visibility"
|
||||
value="public"
|
||||
checked={repo.visibility === VISIBILITY_PUBLIC}
|
||||
onChange={this.handleVisibilityChange}
|
||||
/>
|
||||
<span>Public</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="visibility"
|
||||
value="private"
|
||||
checked={repo.visibility === VISIBILITY_PRIVATE}
|
||||
onChange={this.handleVisibilityChange}
|
||||
/>
|
||||
<span>Private</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="visibility"
|
||||
value="internal"
|
||||
checked={repo.visibility === VISIBILITY_INTERNAL}
|
||||
onChange={this.handleVisibilityChange}
|
||||
/>
|
||||
<span>Internal</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Project Visibility</h2>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="visibility"
|
||||
value="public"
|
||||
checked={repo.visibility === VISIBILITY_PUBLIC}
|
||||
onChange={this.handleVisibilityChange}
|
||||
/>
|
||||
<span>Public</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="visibility"
|
||||
value="private"
|
||||
checked={repo.visibility === VISIBILITY_PRIVATE}
|
||||
onChange={this.handleVisibilityChange}
|
||||
/>
|
||||
<span>Private</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="visibility"
|
||||
value="internal"
|
||||
checked={repo.visibility === VISIBILITY_INTERNAL}
|
||||
onChange={this.handleVisibilityChange}
|
||||
/>
|
||||
<span>Internal</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Timeout</h2>
|
||||
<div>
|
||||
<input
|
||||
type="number"
|
||||
value={repo.timeout}
|
||||
onBlur={this.handleTimeoutChange}
|
||||
/>
|
||||
<span className={styles.minutes}>minutes</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<section>
|
||||
<h2>Timeout</h2>
|
||||
<div>
|
||||
<input
|
||||
type="number"
|
||||
value={repo.timeout}
|
||||
onBlur={this.handleTimeoutChange}
|
||||
/>
|
||||
<span className={styles.minutes}>minutes</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handlePushChange(e) {
|
||||
this.handleChange("allow_push", e.target.checked);
|
||||
}
|
||||
handlePushChange(e) {
|
||||
this.handleChange("allow_push", e.target.checked);
|
||||
}
|
||||
|
||||
handlePullChange(e) {
|
||||
this.handleChange("allow_pr", e.target.checked);
|
||||
}
|
||||
handlePullChange(e) {
|
||||
this.handleChange("allow_pr", e.target.checked);
|
||||
}
|
||||
|
||||
handleTagChange(e) {
|
||||
this.handleChange("allow_tag", e.target.checked);
|
||||
}
|
||||
handleTagChange(e) {
|
||||
this.handleChange("allow_tag", e.target.checked);
|
||||
}
|
||||
|
||||
handleDeployChange(e) {
|
||||
this.handleChange("allow_deploy", e.target.checked);
|
||||
}
|
||||
handleDeployChange(e) {
|
||||
this.handleChange("allow_deploy", e.target.checked);
|
||||
}
|
||||
|
||||
handleTrustedChange(e) {
|
||||
this.handleChange("trusted", e.target.checked);
|
||||
}
|
||||
handleTrustedChange(e) {
|
||||
this.handleChange("trusted", e.target.checked);
|
||||
}
|
||||
|
||||
handleProtectedChange(e) {
|
||||
this.handleChange("gated", e.target.checked);
|
||||
}
|
||||
handleProtectedChange(e) {
|
||||
this.handleChange("gated", e.target.checked);
|
||||
}
|
||||
|
||||
handleVisibilityChange(e) {
|
||||
this.handleChange("visibility", e.target.value);
|
||||
}
|
||||
handleVisibilityChange(e) {
|
||||
this.handleChange("visibility", e.target.value);
|
||||
}
|
||||
|
||||
handleTimeoutChange(e) {
|
||||
this.handleChange("timeout", parseInt(e.target.value));
|
||||
}
|
||||
handleTimeoutChange(e) {
|
||||
this.handleChange("timeout", parseInt(e.target.value));
|
||||
}
|
||||
|
||||
handlePathChange(e) {
|
||||
this.handleChange("config_file", e.target.value);
|
||||
}
|
||||
handlePathChange(e) {
|
||||
this.handleChange("config_file", e.target.value);
|
||||
}
|
||||
|
||||
handleFallbackChange(e) {
|
||||
this.handleChange("fallback", e.target.checked);
|
||||
}
|
||||
handleFallbackChange(e) {
|
||||
this.handleChange("fallback", e.target.checked);
|
||||
}
|
||||
|
||||
handleChange(prop, value) {
|
||||
const { dispatch, drone, repo } = this.props;
|
||||
let data = {};
|
||||
data[prop] = value;
|
||||
dispatch(updateRepository, drone, repo.owner, repo.name, data);
|
||||
}
|
||||
handleChange(prop, value) {
|
||||
const { dispatch, drone, repo } = this.props;
|
||||
let data = {};
|
||||
data[prop] = value;
|
||||
dispatch(updateRepository, drone, repo.owner, repo.name, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@ import Title from "react-title-component";
|
|||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||
// eslint-disable-next-line react/display-name
|
||||
export default function() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/account/tokens" exact={true} component={accountTitle} />
|
||||
<Route path="/account/repos" exact={true} component={accountRepos} />
|
||||
<Route path="/login" exact={false} component={loginTitle} />
|
||||
<Route path="/:owner/:repo" exact={false} component={repoTitle} />
|
||||
<Route path="/" exact={false} component={defautTitle} />
|
||||
</Switch>
|
||||
);
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/account/tokens" exact={true} component={accountTitle} />
|
||||
<Route path="/account/repos" exact={true} component={accountRepos} />
|
||||
<Route path="/login" exact={false} component={loginTitle} />
|
||||
<Route path="/:owner/:repo" exact={false} component={repoTitle} />
|
||||
<Route path="/" exact={false} component={defautTitle} />
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
const accountTitle = () => <Title render="Tokens | drone" />;
|
||||
|
@ -23,7 +23,7 @@ const accountRepos = () => <Title render="Repositories | drone" />;
|
|||
const loginTitle = () => <Title render="Login | drone" />;
|
||||
|
||||
const repoTitle = ({ match }) => (
|
||||
<Title render={`${match.params.owner}/${match.params.repo} | drone`} />
|
||||
<Title render={`${match.params.owner}/${match.params.repo} | drone`} />
|
||||
);
|
||||
|
||||
const defautTitle = () => <Title render="Welcome | drone" />;
|
||||
|
|
|
@ -7,34 +7,34 @@ import { Switch } from "./switch";
|
|||
import styles from "./list.less";
|
||||
|
||||
export const List = ({ children }) => (
|
||||
<div className={styles.list}>{children}</div>
|
||||
<div className={styles.list}>{children}</div>
|
||||
);
|
||||
|
||||
export class Item extends Component {
|
||||
render() {
|
||||
const { owner, name, active, link, onchange } = this.props;
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div>
|
||||
{owner}/{name}
|
||||
</div>
|
||||
<div className={active ? styles.active : styles.inactive}>
|
||||
<Link to={link}>
|
||||
<LaunchIcon />
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
<Switch onchange={onchange} checked={active} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { owner, name, active, link, onchange } = this.props;
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div>
|
||||
{owner}/{name}
|
||||
</div>
|
||||
<div className={active ? styles.active : styles.inactive}>
|
||||
<Link to={link}>
|
||||
<LaunchIcon />
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
<Switch onchange={onchange} checked={active} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return (
|
||||
this.props.owner !== nextProps.owner ||
|
||||
this.props.name !== nextProps.name ||
|
||||
this.props.active !== nextProps.active
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return (
|
||||
this.props.owner !== nextProps.owner ||
|
||||
this.props.name !== nextProps.name ||
|
||||
this.props.active !== nextProps.active
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ import React, { Component } from "react";
|
|||
import styles from "./switch.less";
|
||||
|
||||
export class Switch extends Component {
|
||||
render() {
|
||||
const { checked, onchange } = this.props;
|
||||
return (
|
||||
<label className={styles.switch}>
|
||||
<input type="checkbox" checked={checked} onChange={onchange} />
|
||||
</label>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { checked, onchange } = this.props;
|
||||
return (
|
||||
<label className={styles.switch}>
|
||||
<input type="checkbox" checked={checked} onChange={onchange} />
|
||||
</label>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ import { branch } from "baobab-react/higher-order";
|
|||
import { inject } from "config/client/inject";
|
||||
|
||||
import {
|
||||
fetchRepostoryList,
|
||||
disableRepository,
|
||||
enableRepository,
|
||||
fetchRepostoryList,
|
||||
disableRepository,
|
||||
enableRepository,
|
||||
} from "shared/utils/repository";
|
||||
|
||||
import { List, Item } from "./components";
|
||||
|
@ -15,105 +15,105 @@ import Breadcrumb, { SEPARATOR } from "shared/components/breadcrumb";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
return {
|
||||
repos: ["repos", "data"],
|
||||
loaded: ["repos", "loaded"],
|
||||
error: ["repos", "error"],
|
||||
};
|
||||
return {
|
||||
repos: ["repos", "data"],
|
||||
loaded: ["repos", "loaded"],
|
||||
error: ["repos", "error"],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class UserRepos extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleFilter = this.handleFilter.bind(this);
|
||||
this.renderItem = this.renderItem.bind(this);
|
||||
this.handleToggle = this.handleToggle.bind(this);
|
||||
}
|
||||
this.handleFilter = this.handleFilter.bind(this);
|
||||
this.renderItem = this.renderItem.bind(this);
|
||||
this.handleToggle = this.handleToggle.bind(this);
|
||||
}
|
||||
|
||||
handleFilter(e) {
|
||||
this.setState({
|
||||
search: e.target.value,
|
||||
});
|
||||
}
|
||||
handleFilter(e) {
|
||||
this.setState({
|
||||
search: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
handleToggle(repo, e) {
|
||||
const { dispatch, drone } = this.props;
|
||||
if (e.target.checked) {
|
||||
dispatch(enableRepository, drone, repo.owner, repo.name);
|
||||
} else {
|
||||
dispatch(disableRepository, drone, repo.owner, repo.name);
|
||||
}
|
||||
}
|
||||
handleToggle(repo, e) {
|
||||
const { dispatch, drone } = this.props;
|
||||
if (e.target.checked) {
|
||||
dispatch(enableRepository, drone, repo.owner, repo.name);
|
||||
} else {
|
||||
dispatch(disableRepository, drone, repo.owner, repo.name);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
if (!this._dispatched) {
|
||||
this._dispatched = true;
|
||||
this.props.dispatch(fetchRepostoryList, this.props.drone);
|
||||
}
|
||||
}
|
||||
componentWillMount() {
|
||||
if (!this._dispatched) {
|
||||
this._dispatched = true;
|
||||
this.props.dispatch(fetchRepostoryList, this.props.drone);
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.repos !== nextProps.repos ||
|
||||
this.state.search !== nextState.search
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.repos !== nextProps.repos ||
|
||||
this.state.search !== nextState.search
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { repos, loaded, error } = this.props;
|
||||
const { search } = this.state;
|
||||
const list = Object.values(repos || {});
|
||||
render() {
|
||||
const { repos, loaded, error } = this.props;
|
||||
const { search } = this.state;
|
||||
const list = Object.values(repos || {});
|
||||
|
||||
if (error) {
|
||||
return ERROR;
|
||||
}
|
||||
if (error) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
return LOADING;
|
||||
}
|
||||
if (!loaded) {
|
||||
return LOADING;
|
||||
}
|
||||
|
||||
if (list.length === 0) {
|
||||
return EMPTY;
|
||||
}
|
||||
if (list.length === 0) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
const filter = repo => {
|
||||
return !search || repo.full_name.indexOf(search) !== -1;
|
||||
};
|
||||
const filter = repo => {
|
||||
return !search || repo.full_name.indexOf(search) !== -1;
|
||||
};
|
||||
|
||||
const filtered = list.filter(filter);
|
||||
const filtered = list.filter(filter);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.search}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search …"
|
||||
onChange={this.handleFilter}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.root}>
|
||||
{filtered.length === 0 ? NO_MATCHES : null}
|
||||
<List>{list.filter(filter).map(this.renderItem)}</List>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.search}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search …"
|
||||
onChange={this.handleFilter}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.root}>
|
||||
{filtered.length === 0 ? NO_MATCHES : null}
|
||||
<List>{list.filter(filter).map(this.renderItem)}</List>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem(repo) {
|
||||
return (
|
||||
<Item
|
||||
key={repo.full_name}
|
||||
owner={repo.owner}
|
||||
name={repo.name}
|
||||
active={repo.active}
|
||||
link={`/${repo.full_name}`}
|
||||
onchange={this.handleToggle.bind(this, repo)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
renderItem(repo) {
|
||||
return (
|
||||
<Item
|
||||
key={repo.full_name}
|
||||
owner={repo.owner}
|
||||
name={repo.name}
|
||||
active={repo.active}
|
||||
link={`/${repo.full_name}`}
|
||||
onchange={this.handleToggle.bind(this, repo)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const LOADING = <div>Loading</div>;
|
||||
|
@ -126,12 +126,12 @@ const ERROR = <div>Error</div>;
|
|||
|
||||
/* eslint-disable react/jsx-key */
|
||||
export class UserRepoTitle extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Breadcrumb
|
||||
elements={[<span>Account</span>, SEPARATOR, <span>Repositories</span>]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Breadcrumb
|
||||
elements={[<span>Account</span>, SEPARATOR, <span>Repositories</span>]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
/* eslint-enable react/jsx-key */
|
||||
|
|
|
@ -6,36 +6,36 @@ import { SyncIcon } from "shared/components/icons";
|
|||
import Menu from "shared/components/menu";
|
||||
|
||||
const binding = (props, context) => {
|
||||
return {
|
||||
repos: ["repos"],
|
||||
};
|
||||
return {
|
||||
repos: ["repos"],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class UserReposMenu extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
const { dispatch, drone } = this.props;
|
||||
dispatch(syncRepostoryList, drone);
|
||||
}
|
||||
handleClick() {
|
||||
const { dispatch, drone } = this.props;
|
||||
dispatch(syncRepostoryList, drone);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { loaded } = this.props.repos;
|
||||
const right = (
|
||||
<section>
|
||||
<button disabled={!loaded} onClick={this.handleClick}>
|
||||
<SyncIcon />
|
||||
<span>Synchronize</span>
|
||||
</button>
|
||||
</section>
|
||||
);
|
||||
render() {
|
||||
const { loaded } = this.props.repos;
|
||||
const right = (
|
||||
<section>
|
||||
<button disabled={!loaded} onClick={this.handleClick}>
|
||||
<SyncIcon />
|
||||
<span>Synchronize</span>
|
||||
</button>
|
||||
</section>
|
||||
);
|
||||
|
||||
return <Menu items={[]} right={right} />;
|
||||
}
|
||||
return <Menu items={[]} right={right} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,53 +6,53 @@ import { inject } from "config/client/inject";
|
|||
import styles from "./index.less";
|
||||
|
||||
const binding = (props, context) => {
|
||||
return {
|
||||
location: ["location"],
|
||||
token: ["token"],
|
||||
};
|
||||
return {
|
||||
location: ["location"],
|
||||
token: ["token"],
|
||||
};
|
||||
};
|
||||
|
||||
@inject
|
||||
@branch(binding)
|
||||
export default class Tokens extends Component {
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.location !== nextProps.location ||
|
||||
this.props.token !== nextProps.token
|
||||
);
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.props.location !== nextProps.location ||
|
||||
this.props.token !== nextProps.token
|
||||
);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { drone, dispatch } = this.props;
|
||||
componentWillMount() {
|
||||
const { drone, dispatch } = this.props;
|
||||
|
||||
dispatch(generateToken, drone);
|
||||
}
|
||||
dispatch(generateToken, drone);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { location, token } = this.props;
|
||||
render() {
|
||||
const { location, token } = this.props;
|
||||
|
||||
if (!location || !token) {
|
||||
return <div>Loading</div>;
|
||||
}
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<h2>Your Personal Token:</h2>
|
||||
<pre>{token}</pre>
|
||||
<h2>Example API Usage:</h2>
|
||||
<pre>{usageWithCURL(location, token)}</pre>
|
||||
<h2>Example CLI Usage:</h2>
|
||||
<pre>{usageWithCLI(location, token)}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (!location || !token) {
|
||||
return <div>Loading</div>;
|
||||
}
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<h2>Your Personal Token:</h2>
|
||||
<pre>{token}</pre>
|
||||
<h2>Example API Usage:</h2>
|
||||
<pre>{usageWithCURL(location, token)}</pre>
|
||||
<h2>Example CLI Usage:</h2>
|
||||
<pre>{usageWithCLI(location, token)}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const usageWithCURL = (location, token) => {
|
||||
return `curl -i ${location.protocol}//${location.host}/api/user -H "Authorization: Bearer ${token}"`;
|
||||
return `curl -i ${location.protocol}//${location.host}/api/user -H "Authorization: Bearer ${token}"`;
|
||||
};
|
||||
|
||||
const usageWithCLI = (location, token) => {
|
||||
return `export DRONE_SERVER=${location.protocol}//${location.host}
|
||||
return `export DRONE_SERVER=${location.protocol}//${location.host}
|
||||
export DRONE_TOKEN=${token}
|
||||
|
||||
drone info`;
|
||||
|
|
|
@ -3,30 +3,30 @@ import { mount } from "enzyme";
|
|||
|
||||
import Status from "../status";
|
||||
import {
|
||||
STATUS_FAILURE,
|
||||
STATUS_RUNNING,
|
||||
STATUS_SUCCESS,
|
||||
STATUS_FAILURE,
|
||||
STATUS_RUNNING,
|
||||
STATUS_SUCCESS,
|
||||
} from "shared/constants/status";
|
||||
|
||||
jest.dontMock("../status");
|
||||
|
||||
describe("Status component", () => {
|
||||
test("updates on status change", () => {
|
||||
const status = mount(<Status status={STATUS_FAILURE} />);
|
||||
const instance = status.instance();
|
||||
test("updates on status change", () => {
|
||||
const status = mount(<Status status={STATUS_FAILURE} />);
|
||||
const instance = status.instance();
|
||||
|
||||
expect(
|
||||
instance.shouldComponentUpdate({ status: STATUS_FAILURE }),
|
||||
).toBeFalsy();
|
||||
expect(
|
||||
instance.shouldComponentUpdate({ status: STATUS_SUCCESS }),
|
||||
).toBeTruthy();
|
||||
expect(status.hasClass("failure")).toBeTruthy();
|
||||
});
|
||||
expect(
|
||||
instance.shouldComponentUpdate({ status: STATUS_FAILURE }),
|
||||
).toBeFalsy();
|
||||
expect(
|
||||
instance.shouldComponentUpdate({ status: STATUS_SUCCESS }),
|
||||
).toBeTruthy();
|
||||
expect(status.hasClass("failure")).toBeTruthy();
|
||||
});
|
||||
|
||||
test("uses the status as the class name", () => {
|
||||
const status = mount(<Status status={STATUS_RUNNING} />);
|
||||
test("uses the status as the class name", () => {
|
||||
const status = mount(<Status status={STATUS_RUNNING} />);
|
||||
|
||||
expect(status.hasClass("running")).toBeTruthy();
|
||||
});
|
||||
expect(status.hasClass("running")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,11 +2,11 @@ import React, { Component } from "react";
|
|||
import styles from "./avatar.less";
|
||||
|
||||
export default class Avatar extends Component {
|
||||
render() {
|
||||
const image = this.props.image;
|
||||
const style = {
|
||||
backgroundImage: `url(${image})`,
|
||||
};
|
||||
return <div className={styles.avatar} style={style} />;
|
||||
}
|
||||
render() {
|
||||
const image = this.props.image;
|
||||
const style = {
|
||||
backgroundImage: `url(${image})`,
|
||||
};
|
||||
return <div className={styles.avatar} style={style} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ export const BACK_BUTTON = <BackIcon size={18} className={style.back} />;
|
|||
|
||||
// helper function to render a list item.
|
||||
const renderItem = (element, index) => {
|
||||
return <li key={index}>{element}</li>;
|
||||
return <li key={index}>{element}</li>;
|
||||
};
|
||||
|
||||
export default class Breadcrumb extends Component {
|
||||
render() {
|
||||
const { elements } = this.props;
|
||||
return <ol className={style.breadcrumb}>{elements.map(renderItem)}</ol>;
|
||||
}
|
||||
render() {
|
||||
const { elements } = this.props;
|
||||
return <ol className={style.breadcrumb}>{elements.map(renderItem)}</ol>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
import React, { Component } from "react";
|
||||
import {
|
||||
BranchIcon,
|
||||
CommitIcon,
|
||||
DeployIcon,
|
||||
LaunchIcon,
|
||||
MergeIcon,
|
||||
TagIcon,
|
||||
BranchIcon,
|
||||
CommitIcon,
|
||||
DeployIcon,
|
||||
LaunchIcon,
|
||||
MergeIcon,
|
||||
TagIcon,
|
||||
} from "shared/components/icons/index";
|
||||
import {
|
||||
EVENT_TAG,
|
||||
EVENT_PULL_REQUEST,
|
||||
EVENT_DEPLOY,
|
||||
EVENT_TAG,
|
||||
EVENT_PULL_REQUEST,
|
||||
EVENT_DEPLOY,
|
||||
} from "shared/constants/events";
|
||||
|
||||
import styles from "./build_event.less";
|
||||
|
||||
export default class BuildEvent extends Component {
|
||||
render() {
|
||||
const { event, branch, commit, refs, refspec, link, target } = this.props;
|
||||
render() {
|
||||
const { event, branch, commit, refs, refspec, link, target } = this.props;
|
||||
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<CommitIcon />
|
||||
</div>
|
||||
<div>{commit && commit.substr(0, 10)}</div>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
{event === EVENT_TAG ? (
|
||||
<TagIcon />
|
||||
) : event === EVENT_PULL_REQUEST ? (
|
||||
<MergeIcon />
|
||||
) : event === EVENT_DEPLOY ? (
|
||||
<DeployIcon />
|
||||
) : (
|
||||
<BranchIcon />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{event === EVENT_TAG && refs ? (
|
||||
trimTagRef(refs)
|
||||
) : event === EVENT_PULL_REQUEST && refspec ? (
|
||||
trimMergeRef(refs)
|
||||
) : event === EVENT_DEPLOY && target ? (
|
||||
target
|
||||
) : (
|
||||
branch
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<a href={link} target="_blank">
|
||||
<LaunchIcon />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<CommitIcon />
|
||||
</div>
|
||||
<div>{commit && commit.substr(0, 10)}</div>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
{event === EVENT_TAG ? (
|
||||
<TagIcon />
|
||||
) : event === EVENT_PULL_REQUEST ? (
|
||||
<MergeIcon />
|
||||
) : event === EVENT_DEPLOY ? (
|
||||
<DeployIcon />
|
||||
) : (
|
||||
<BranchIcon />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{event === EVENT_TAG && refs ? (
|
||||
trimTagRef(refs)
|
||||
) : event === EVENT_PULL_REQUEST && refspec ? (
|
||||
trimMergeRef(refs)
|
||||
) : event === EVENT_DEPLOY && target ? (
|
||||
target
|
||||
) : (
|
||||
branch
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<a href={link} target="_blank">
|
||||
<LaunchIcon />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const trimMergeRef = ref => {
|
||||
return ref.match(/\d/g) || ref;
|
||||
return ref.match(/\d/g) || ref;
|
||||
};
|
||||
|
||||
const trimTagRef = ref => {
|
||||
return ref.startsWith("refs/tags/") ? ref.substr(10) : ref;
|
||||
return ref.startsWith("refs/tags/") ? ref.substr(10) : ref;
|
||||
};
|
||||
|
||||
// push
|
||||
|
|
|
@ -7,31 +7,31 @@ import Duration from "./duration";
|
|||
import styles from "./build_time.less";
|
||||
|
||||
export default class Runtime extends Component {
|
||||
render() {
|
||||
const { start, finish } = this.props;
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<ScheduleIcon />
|
||||
</div>
|
||||
<div>{start ? <TimeAgo date={start * 1000} /> : <span>--</span>}</div>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<TimelapseIcon />
|
||||
</div>
|
||||
<div>
|
||||
{finish ? (
|
||||
<Duration start={start} finished={finish} />
|
||||
) : start ? (
|
||||
<TimeAgo date={start * 1000} />
|
||||
) : (
|
||||
<span>--</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { start, finish } = this.props;
|
||||
return (
|
||||
<div className={styles.host}>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<ScheduleIcon />
|
||||
</div>
|
||||
<div>{start ? <TimeAgo date={start * 1000} /> : <span>--</span>}</div>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<TimelapseIcon />
|
||||
</div>
|
||||
<div>
|
||||
{finish ? (
|
||||
<Duration start={start} finished={finish} />
|
||||
) : start ? (
|
||||
<TimeAgo date={start * 1000} />
|
||||
) : (
|
||||
<span>--</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,56 +7,56 @@ export const DOCK_LEFT = styles.left;
|
|||
export const DOCK_RIGHT = styles.right;
|
||||
|
||||
export class Drawer extends Component {
|
||||
render() {
|
||||
const { open, position } = this.props;
|
||||
render() {
|
||||
const { open, position } = this.props;
|
||||
|
||||
let classes = [styles.drawer];
|
||||
if (open) {
|
||||
classes.push(styles.open);
|
||||
}
|
||||
if (position) {
|
||||
classes.push(position);
|
||||
}
|
||||
let classes = [styles.drawer];
|
||||
if (open) {
|
||||
classes.push(styles.open);
|
||||
}
|
||||
if (position) {
|
||||
classes.push(position);
|
||||
}
|
||||
|
||||
var child = open ? (
|
||||
<div key={0} onClick={this.props.onClick} className={styles.backdrop} />
|
||||
) : null;
|
||||
var child = open ? (
|
||||
<div key={0} onClick={this.props.onClick} className={styles.backdrop} />
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={classes.join(" ")}>
|
||||
<CSSTransitionGroup
|
||||
transitionName="fade"
|
||||
transitionEnterTimeout={150}
|
||||
transitionLeaveTimeout={150}
|
||||
transitionAppearTimeout={150}
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
>
|
||||
{child}
|
||||
</CSSTransitionGroup>
|
||||
<div className={styles.inner}>{this.props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={classes.join(" ")}>
|
||||
<CSSTransitionGroup
|
||||
transitionName="fade"
|
||||
transitionEnterTimeout={150}
|
||||
transitionLeaveTimeout={150}
|
||||
transitionAppearTimeout={150}
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
>
|
||||
{child}
|
||||
</CSSTransitionGroup>
|
||||
<div className={styles.inner}>{this.props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class CloseButton extends Component {
|
||||
render() {
|
||||
return (
|
||||
<button className={styles.close} onClick={this.props.onClick}>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<button className={styles.close} onClick={this.props.onClick}>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class MenuButton extends Component {
|
||||
render() {
|
||||
return (
|
||||
<button className={styles.close} onClick={this.props.onClick}>
|
||||
Show Menu
|
||||
</button>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<button className={styles.close} onClick={this.props.onClick}>
|
||||
Show Menu
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import humanizeDuration from "humanize-duration";
|
|||
import React from "react";
|
||||
|
||||
export default class Duration extends React.Component {
|
||||
render() {
|
||||
const { start, finished } = this.props;
|
||||
render() {
|
||||
const { start, finished } = this.props;
|
||||
|
||||
return <time>{humanizeDuration((finished - start) * 1000)}</time>;
|
||||
}
|
||||
return <time>{humanizeDuration((finished - start) * 1000)}</time>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class BackIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class BranchIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M6,2A3,3 0 0,1 9,5C9,6.28 8.19,7.38 7.06,7.81C7.15,8.27 7.39,8.83 8,9.63C9,10.92 11,12.83 12,14.17C13,12.83 15,10.92 16,9.63C16.61,8.83 16.85,8.27 16.94,7.81C15.81,7.38 15,6.28 15,5A3,3 0 0,1 18,2A3,3 0 0,1 21,5C21,6.32 20.14,7.45 18.95,7.85C18.87,8.37 18.64,9 18,9.83C17,11.17 15,13.08 14,14.38C13.39,15.17 13.15,15.73 13.06,16.19C14.19,16.62 15,17.72 15,19A3,3 0 0,1 12,22A3,3 0 0,1 9,19C9,17.72 9.81,16.62 10.94,16.19C10.85,15.73 10.61,15.17 10,14.38C9,13.08 7,11.17 6,9.83C5.36,9 5.13,8.37 5.05,7.85C3.86,7.45 3,6.32 3,5A3,3 0 0,1 6,2M6,4A1,1 0 0,0 5,5A1,1 0 0,0 6,6A1,1 0 0,0 7,5A1,1 0 0,0 6,4M18,4A1,1 0 0,0 17,5A1,1 0 0,0 18,6A1,1 0 0,0 19,5A1,1 0 0,0 18,4M12,18A1,1 0 0,0 11,19A1,1 0 0,0 12,20A1,1 0 0,0 13,19A1,1 0 0,0 12,18Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M6,2A3,3 0 0,1 9,5C9,6.28 8.19,7.38 7.06,7.81C7.15,8.27 7.39,8.83 8,9.63C9,10.92 11,12.83 12,14.17C13,12.83 15,10.92 16,9.63C16.61,8.83 16.85,8.27 16.94,7.81C15.81,7.38 15,6.28 15,5A3,3 0 0,1 18,2A3,3 0 0,1 21,5C21,6.32 20.14,7.45 18.95,7.85C18.87,8.37 18.64,9 18,9.83C17,11.17 15,13.08 14,14.38C13.39,15.17 13.15,15.73 13.06,16.19C14.19,16.62 15,17.72 15,19A3,3 0 0,1 12,22A3,3 0 0,1 9,19C9,17.72 9.81,16.62 10.94,16.19C10.85,15.73 10.61,15.17 10,14.38C9,13.08 7,11.17 6,9.83C5.36,9 5.13,8.37 5.05,7.85C3.86,7.45 3,6.32 3,5A3,3 0 0,1 6,2M6,4A1,1 0 0,0 5,5A1,1 0 0,0 6,6A1,1 0 0,0 7,5A1,1 0 0,0 6,4M18,4A1,1 0 0,0 17,5A1,1 0 0,0 18,6A1,1 0 0,0 19,5A1,1 0 0,0 18,4M12,18A1,1 0 0,0 11,19A1,1 0 0,0 12,20A1,1 0 0,0 13,19A1,1 0 0,0 12,18Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class CheckIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class ClockIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class CloseIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class CommitIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M17,12C17,14.42 15.28,16.44 13,16.9V21H11V16.9C8.72,16.44 7,14.42 7,12C7,9.58 8.72,7.56 11,7.1V3H13V7.1C15.28,7.56 17,9.58 17,12M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M17,12C17,14.42 15.28,16.44 13,16.9V21H11V16.9C8.72,16.44 7,14.42 7,12C7,9.58 8.72,7.56 11,7.1V3H13V7.1C15.28,7.56 17,9.58 17,12M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class DeployIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M19,18H6A4,4 0 0,1 2,14A4,4 0 0,1 6,10H6.71C7.37,7.69 9.5,6 12,6A5.5,5.5 0 0,1 17.5,11.5V12H19A3,3 0 0,1 22,15A3,3 0 0,1 19,18M19.35,10.03C18.67,6.59 15.64,4 12,4C9.11,4 6.6,5.64 5.35,8.03C2.34,8.36 0,10.9 0,14A6,6 0 0,0 6,20H19A5,5 0 0,0 24,15C24,12.36 21.95,10.22 19.35,10.03Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M19,18H6A4,4 0 0,1 2,14A4,4 0 0,1 6,10H6.71C7.37,7.69 9.5,6 12,6A5.5,5.5 0 0,1 17.5,11.5V12H19A3,3 0 0,1 22,15A3,3 0 0,1 19,18M19.35,10.03C18.67,6.59 15.64,4 12,4C9.11,4 6.6,5.64 5.35,8.03C2.34,8.36 0,10.9 0,14A6,6 0 0,0 6,20H19A5,5 0 0,0 24,15C24,12.36 21.95,10.22 19.35,10.03Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class ExpandIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
|
||||
<path d="M0-.75h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
|
||||
<path d="M0-.75h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,25 +21,25 @@ import TagIcon from "./tag";
|
|||
import TimelapseIcon from "./timelapse";
|
||||
|
||||
export {
|
||||
BackIcon,
|
||||
BranchIcon,
|
||||
CheckIcon,
|
||||
CloseIcon,
|
||||
ClockIcon,
|
||||
CommitIcon,
|
||||
DeployIcon,
|
||||
ExpandIcon,
|
||||
LaunchIcon,
|
||||
LinkIcon,
|
||||
MenuIcon,
|
||||
MergeIcon,
|
||||
PauseIcon,
|
||||
PlayIcon,
|
||||
RefreshIcon,
|
||||
RemoveIcon,
|
||||
ScheduleIcon,
|
||||
StarIcon,
|
||||
SyncIcon,
|
||||
TagIcon,
|
||||
TimelapseIcon,
|
||||
BackIcon,
|
||||
BranchIcon,
|
||||
CheckIcon,
|
||||
CloseIcon,
|
||||
ClockIcon,
|
||||
CommitIcon,
|
||||
DeployIcon,
|
||||
ExpandIcon,
|
||||
LaunchIcon,
|
||||
LinkIcon,
|
||||
MenuIcon,
|
||||
MergeIcon,
|
||||
PauseIcon,
|
||||
PlayIcon,
|
||||
RefreshIcon,
|
||||
RemoveIcon,
|
||||
ScheduleIcon,
|
||||
StarIcon,
|
||||
SyncIcon,
|
||||
TagIcon,
|
||||
TimelapseIcon,
|
||||
};
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class LaunchIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class LinkIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class MenuIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class MergeIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M5.41,21L6.12,17H2.12L2.47,15H6.47L7.53,9H3.53L3.88,7H7.88L8.59,3H10.59L9.88,7H15.88L16.59,3H18.59L17.88,7H21.88L21.53,9H17.53L16.47,15H20.47L20.12,17H16.12L15.41,21H13.41L14.12,17H8.12L7.41,21H5.41M9.53,9L8.47,15H14.47L15.53,9H9.53Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M5.41,21L6.12,17H2.12L2.47,15H6.47L7.53,9H3.53L3.88,7H7.88L8.59,3H10.59L9.88,7H15.88L16.59,3H18.59L17.88,7H21.88L21.53,9H17.53L16.47,15H20.47L20.12,17H16.12L15.41,21H13.41L14.12,17H8.12L7.41,21H5.41M9.53,9L8.47,15H14.47L15.53,9H9.53Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// <svg class={this.props.className} viewBox="0 0 54.5 68">
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class PauseIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class PlayIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M8 5v14l11-7z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M8 5v14l11-7z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class RefreshIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class CheckIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 13H5v-2h14v2z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 13H5v-2h14v2z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class ReportIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0 .72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0 .72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class ScheduleIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class StarIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
{this.props.filled === true ? (
|
||||
<path d="M256 372.686L380.83 448l-33.021-142.066L458 210.409l-145.267-12.475L256 64l-56.743 133.934L54 210.409l110.192 95.525L131.161 448z" />
|
||||
) : (
|
||||
<path d="M458 210.409l-145.267-12.476L256 64l-56.743 133.934L54 210.409l110.192 95.524L131.161 448 256 372.686 380.83 448l-33.021-142.066L458 210.409zM272.531 345.286L256 335.312l-16.53 9.973-59.988 36.191 15.879-68.296 4.369-18.79-14.577-12.637-52.994-45.939 69.836-5.998 19.206-1.65 7.521-17.75 27.276-64.381 27.27 64.379 7.52 17.751 19.208 1.65 69.846 5.998-52.993 45.939-14.576 12.636 4.367 18.788 15.875 68.299-59.984-36.189z" />
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
{this.props.filled === true ? (
|
||||
<path d="M256 372.686L380.83 448l-33.021-142.066L458 210.409l-145.267-12.475L256 64l-56.743 133.934L54 210.409l110.192 95.525L131.161 448z" />
|
||||
) : (
|
||||
<path d="M458 210.409l-145.267-12.476L256 64l-56.743 133.934L54 210.409l110.192 95.524L131.161 448 256 372.686 380.83 448l-33.021-142.066L458 210.409zM272.531 345.286L256 335.312l-16.53 9.973-59.988 36.191 15.879-68.296 4.369-18.79-14.577-12.637-52.994-45.939 69.836-5.998 19.206-1.65 7.521-17.75 27.276-64.381 27.27 64.379 7.52 17.751 19.208 1.65 69.846 5.998-52.993 45.939-14.576 12.636 4.367 18.788 15.875 68.299-59.984-36.189z" />
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class SyncIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class TagIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M5.5,7A1.5,1.5 0 0,0 7,5.5A1.5,1.5 0 0,0 5.5,4A1.5,1.5 0 0,0 4,5.5A1.5,1.5 0 0,0 5.5,7M21.41,11.58C21.77,11.94 22,12.44 22,13C22,13.55 21.78,14.05 21.41,14.41L14.41,21.41C14.05,21.77 13.55,22 13,22C12.45,22 11.95,21.77 11.58,21.41L2.59,12.41C2.22,12.05 2,11.55 2,11V4C2,2.89 2.89,2 4,2H11C11.55,2 12.05,2.22 12.41,2.58L21.41,11.58M13,20L20,13L11.5,4.5L4.5,11.5L13,20Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||
<path d="M5.5,7A1.5,1.5 0 0,0 7,5.5A1.5,1.5 0 0,0 5.5,4A1.5,1.5 0 0,0 4,5.5A1.5,1.5 0 0,0 5.5,7M21.41,11.58C21.77,11.94 22,12.44 22,13C22,13.55 21.78,14.05 21.41,14.41L14.41,21.41C14.05,21.77 13.55,22 13,22C12.45,22 11.95,21.77 11.58,21.41L2.59,12.41C2.22,12.05 2,11.55 2,11V4C2,2.89 2.89,2 4,2H11C11.55,2 12.05,2.22 12.41,2.58L21.41,11.58M13,20L20,13L11.5,4.5L4.5,11.5L13,20Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class TimelapseIcon extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M16.24 7.76C15.07 6.59 13.54 6 12 6v6l-4.24 4.24c2.34 2.34 6.14 2.34 8.49 0 2.34-2.34 2.34-6.14-.01-8.48zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg
|
||||
className={this.props.className}
|
||||
width={this.props.size || 24}
|
||||
height={this.props.size || 24}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M16.24 7.76C15.07 6.59 13.54 6 12 6v6l-4.24 4.24c2.34 2.34 6.14 2.34 8.49 0 2.34-2.34 2.34-6.14-.01-8.48zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
export default class Logo extends Component {
|
||||
render() {
|
||||
return (
|
||||
<svg viewBox="0 0 50 62.5" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M15.872,0.468c1.148,1.088,1.582,2.188,2.855,2.337l0.036,0.007c-0.588,0.606-1.089,1.402-1.443,2.423c-0.379,1.096-0.488,2.285-0.614,3.659c-0.189,2.046-0.401,4.364-1.556,7.269 c-2.486,6.258-1.119,11.631,0.332,17.317c0.664,2.604,1.348,5.297,1.642,8.107c0.035,0.355,0.287,0.652,0.633,0.744 c0.346,0.095,0.709-0.035,0.922-0.323c0.227-0.313,0.524-0.797,0.86-1.424c0.84,3.323,1.355,6.131,1.783,8.697 c0.126,0.73,1.048,0.973,1.517,0.41c2.881-3.463,3.763-8.636,2.184-12.674c0.459-2.433,1.402-4.45,2.398-6.583 c0.536-1.15,1.08-2.318,1.55-3.566c0.228-0.084,0.569-0.314,0.791-0.441l1.706-0.981l-0.256,1.052 c-0.112,0.461,0.171,0.929,0.635,1.04c0.457,0.118,0.93-0.173,1.043-0.632l0.68-2.858l1.285-2.95 c0.19-0.436-0.009-0.943-0.446-1.135c-0.44-0.189-0.947,0.01-1.135,0.448l-1.152,2.669l-2.383,1.372 c0.235-0.932,0.414-1.919,0.508-2.981c0.432-4.859-0.718-9.074-3.066-11.266c-0.163-0.157-0.208-0.281-0.247-0.26 c0.095-0.119,0.249-0.26,0.358-0.374c2.283-1.693,6.047-0.147,8.319,0.751c0.589,0.231,0.876-0.338,0.316-0.67 c-1.949-1.154-5.948-4.197-8.188-6.194c-0.313-0.275-0.527-0.607-0.89-0.913c-2.415-4.266-8.168-1.764-10.885-2.252 C15.862,0.275,15.798,0.396,15.872,0.468 M26.852,6.367c-0.059,1.242-0.603,1.8-0.999,2.208c-0.218,0.224-0.427,0.436-0.525,0.738 c-0.236,0.714,0.008,1.51,0.66,2.143c1.974,1.84,2.925,5.527,2.538,9.861c-0.291,3.287-1.448,5.762-2.671,8.384 c-1.031,2.207-2.096,4.489-2.577,7.259c-0.027,0.161-0.01,0.33,0.056,0.481c1.021,2.433,1.135,6.196-0.672,9.46 c-0.461-2.553-1.053-5.385-1.97-8.712c1.964-4.488,4.203-11.75,2.919-17.668c-0.325-1.497-1.304-3.276-2.387-4.207 c-0.208-0.179-0.402-0.237-0.495-0.167c-0.084,0.061-0.151,0.238-0.062,0.444c0.55,1.266,0.879,2.599,1.226,4.276 c1.125,5.443-0.956,12.49-2.835,16.782l-0.116,0.259l-0.457,0.982c-0.356-2.014-0.849-3.95-1.33-5.839 c-1.379-5.407-2.679-10.516-0.401-16.255c1.247-3.137,1.483-5.692,1.672-7.746c0.116-1.263,0.216-2.355,0.526-3.252 c0.905-2.605,3.062-3.178,4.744-2.852C25.328,3.262,26.936,4.539,26.852,6.367z M23.984,6.988c0.617,0.204,1.283-0.131,1.487-0.75 c0.202-0.617-0.134-1.283-0.751-1.487c-0.618-0.204-1.285,0.134-1.487,0.751C23.029,6.12,23.366,6.786,23.984,6.988z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<svg viewBox="0 0 50 62.5" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M15.872,0.468c1.148,1.088,1.582,2.188,2.855,2.337l0.036,0.007c-0.588,0.606-1.089,1.402-1.443,2.423c-0.379,1.096-0.488,2.285-0.614,3.659c-0.189,2.046-0.401,4.364-1.556,7.269 c-2.486,6.258-1.119,11.631,0.332,17.317c0.664,2.604,1.348,5.297,1.642,8.107c0.035,0.355,0.287,0.652,0.633,0.744 c0.346,0.095,0.709-0.035,0.922-0.323c0.227-0.313,0.524-0.797,0.86-1.424c0.84,3.323,1.355,6.131,1.783,8.697 c0.126,0.73,1.048,0.973,1.517,0.41c2.881-3.463,3.763-8.636,2.184-12.674c0.459-2.433,1.402-4.45,2.398-6.583 c0.536-1.15,1.08-2.318,1.55-3.566c0.228-0.084,0.569-0.314,0.791-0.441l1.706-0.981l-0.256,1.052 c-0.112,0.461,0.171,0.929,0.635,1.04c0.457,0.118,0.93-0.173,1.043-0.632l0.68-2.858l1.285-2.95 c0.19-0.436-0.009-0.943-0.446-1.135c-0.44-0.189-0.947,0.01-1.135,0.448l-1.152,2.669l-2.383,1.372 c0.235-0.932,0.414-1.919,0.508-2.981c0.432-4.859-0.718-9.074-3.066-11.266c-0.163-0.157-0.208-0.281-0.247-0.26 c0.095-0.119,0.249-0.26,0.358-0.374c2.283-1.693,6.047-0.147,8.319,0.751c0.589,0.231,0.876-0.338,0.316-0.67 c-1.949-1.154-5.948-4.197-8.188-6.194c-0.313-0.275-0.527-0.607-0.89-0.913c-2.415-4.266-8.168-1.764-10.885-2.252 C15.862,0.275,15.798,0.396,15.872,0.468 M26.852,6.367c-0.059,1.242-0.603,1.8-0.999,2.208c-0.218,0.224-0.427,0.436-0.525,0.738 c-0.236,0.714,0.008,1.51,0.66,2.143c1.974,1.84,2.925,5.527,2.538,9.861c-0.291,3.287-1.448,5.762-2.671,8.384 c-1.031,2.207-2.096,4.489-2.577,7.259c-0.027,0.161-0.01,0.33,0.056,0.481c1.021,2.433,1.135,6.196-0.672,9.46 c-0.461-2.553-1.053-5.385-1.97-8.712c1.964-4.488,4.203-11.75,2.919-17.668c-0.325-1.497-1.304-3.276-2.387-4.207 c-0.208-0.179-0.402-0.237-0.495-0.167c-0.084,0.061-0.151,0.238-0.062,0.444c0.55,1.266,0.879,2.599,1.226,4.276 c1.125,5.443-0.956,12.49-2.835,16.782l-0.116,0.259l-0.457,0.982c-0.356-2.014-0.849-3.95-1.33-5.839 c-1.379-5.407-2.679-10.516-0.401-16.255c1.247-3.137,1.483-5.692,1.672-7.746c0.116-1.263,0.216-2.355,0.526-3.252 c0.905-2.605,3.062-3.178,4.744-2.852C25.328,3.262,26.936,4.539,26.852,6.367z M23.984,6.988c0.617,0.204,1.283-0.131,1.487-0.75 c0.202-0.617-0.134-1.283-0.751-1.487c-0.618-0.204-1.285,0.134-1.487,0.751C23.029,6.12,23.366,6.786,23.984,6.988z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,28 +5,28 @@ import PropTypes from "prop-types";
|
|||
import styles from "./menu.less";
|
||||
|
||||
export default class Menu extends Component {
|
||||
propTypes = { items: PropTypes.array, right: PropTypes.any };
|
||||
render() {
|
||||
const items = this.props.items;
|
||||
const right = this.props.right ? (
|
||||
<div className={styles.right}>{this.props.right}</div>
|
||||
) : null;
|
||||
return (
|
||||
<section className={styles.root}>
|
||||
<div className={styles.left}>
|
||||
{items.map(i => (
|
||||
<Link
|
||||
key={i.to + i.label}
|
||||
to={i.to}
|
||||
exact={true}
|
||||
activeClassName={styles["link-active"]}
|
||||
>
|
||||
{i.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
{right}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
propTypes = { items: PropTypes.array, right: PropTypes.any };
|
||||
render() {
|
||||
const items = this.props.items;
|
||||
const right = this.props.right ? (
|
||||
<div className={styles.right}>{this.props.right}</div>
|
||||
) : null;
|
||||
return (
|
||||
<section className={styles.root}>
|
||||
<div className={styles.left}>
|
||||
{items.map(i => (
|
||||
<Link
|
||||
key={i.to + i.label}
|
||||
to={i.to}
|
||||
exact={true}
|
||||
activeClassName={styles["link-active"]}
|
||||
>
|
||||
{i.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
{right}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,38 +4,38 @@ import CloseIcon from "shared/components/icons/close";
|
|||
import { CSSTransitionGroup } from "react-transition-group";
|
||||
|
||||
export class Snackbar extends React.Component {
|
||||
render() {
|
||||
const { message } = this.props;
|
||||
render() {
|
||||
const { message } = this.props;
|
||||
|
||||
let classes = [styles.snackbar];
|
||||
if (message) {
|
||||
classes.push(styles.open);
|
||||
}
|
||||
let classes = [styles.snackbar];
|
||||
if (message) {
|
||||
classes.push(styles.open);
|
||||
}
|
||||
|
||||
const content = message ? (
|
||||
<div className={classes.join(" ")} key={message}>
|
||||
<div>{message}</div>
|
||||
<button onClick={this.props.onClose}>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
</div>
|
||||
) : null;
|
||||
const content = message ? (
|
||||
<div className={classes.join(" ")} key={message}>
|
||||
<div>{message}</div>
|
||||
<button onClick={this.props.onClose}>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<CSSTransitionGroup
|
||||
transitionName="slideup"
|
||||
transitionEnterTimeout={200}
|
||||
transitionLeaveTimeout={200}
|
||||
transitionAppearTimeout={200}
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
className={classes.root}
|
||||
>
|
||||
{content}
|
||||
</CSSTransitionGroup>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<CSSTransitionGroup
|
||||
transitionName="slideup"
|
||||
transitionEnterTimeout={200}
|
||||
transitionLeaveTimeout={200}
|
||||
transitionAppearTimeout={200}
|
||||
transitionAppear={true}
|
||||
transitionEnter={true}
|
||||
transitionLeave={true}
|
||||
className={classes.root}
|
||||
>
|
||||
{content}
|
||||
</CSSTransitionGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// const SnackbarContent = ({ children, ...props }) => {
|
||||
|
|
|
@ -1,100 +1,100 @@
|
|||
import React, { Component } from "react";
|
||||
import classnames from "classnames";
|
||||
import {
|
||||
STATUS_BLOCKED,
|
||||
STATUS_DECLINED,
|
||||
STATUS_ERROR,
|
||||
STATUS_FAILURE,
|
||||
STATUS_KILLED,
|
||||
STATUS_PENDING,
|
||||
STATUS_RUNNING,
|
||||
STATUS_SKIPPED,
|
||||
STATUS_STARTED,
|
||||
STATUS_SUCCESS,
|
||||
STATUS_BLOCKED,
|
||||
STATUS_DECLINED,
|
||||
STATUS_ERROR,
|
||||
STATUS_FAILURE,
|
||||
STATUS_KILLED,
|
||||
STATUS_PENDING,
|
||||
STATUS_RUNNING,
|
||||
STATUS_SKIPPED,
|
||||
STATUS_STARTED,
|
||||
STATUS_SUCCESS,
|
||||
} from "shared/constants/status";
|
||||
import style from "./status.less";
|
||||
|
||||
import {
|
||||
CheckIcon,
|
||||
CloseIcon,
|
||||
ClockIcon,
|
||||
RefreshIcon,
|
||||
RemoveIcon,
|
||||
CheckIcon,
|
||||
CloseIcon,
|
||||
ClockIcon,
|
||||
RefreshIcon,
|
||||
RemoveIcon,
|
||||
} from "./icons/index";
|
||||
|
||||
const defaultIconSize = 15;
|
||||
|
||||
const statusLabel = status => {
|
||||
switch (status) {
|
||||
case STATUS_BLOCKED:
|
||||
return "Pending Approval";
|
||||
case STATUS_DECLINED:
|
||||
return "Declined";
|
||||
case STATUS_ERROR:
|
||||
return "Error";
|
||||
case STATUS_FAILURE:
|
||||
return "Failure";
|
||||
case STATUS_KILLED:
|
||||
return "Cancelled";
|
||||
case STATUS_PENDING:
|
||||
return "Pending";
|
||||
case STATUS_RUNNING:
|
||||
return "Running";
|
||||
case STATUS_SKIPPED:
|
||||
return "Skipped";
|
||||
case STATUS_STARTED:
|
||||
return "Running";
|
||||
case STATUS_SUCCESS:
|
||||
return "Successful";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
switch (status) {
|
||||
case STATUS_BLOCKED:
|
||||
return "Pending Approval";
|
||||
case STATUS_DECLINED:
|
||||
return "Declined";
|
||||
case STATUS_ERROR:
|
||||
return "Error";
|
||||
case STATUS_FAILURE:
|
||||
return "Failure";
|
||||
case STATUS_KILLED:
|
||||
return "Cancelled";
|
||||
case STATUS_PENDING:
|
||||
return "Pending";
|
||||
case STATUS_RUNNING:
|
||||
return "Running";
|
||||
case STATUS_SKIPPED:
|
||||
return "Skipped";
|
||||
case STATUS_STARTED:
|
||||
return "Running";
|
||||
case STATUS_SUCCESS:
|
||||
return "Successful";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const renderIcon = (status, size) => {
|
||||
switch (status) {
|
||||
case STATUS_SKIPPED:
|
||||
return <RemoveIcon size={size} />;
|
||||
case STATUS_PENDING:
|
||||
return <ClockIcon size={size} />;
|
||||
case STATUS_RUNNING:
|
||||
case STATUS_STARTED:
|
||||
return <RefreshIcon size={size} />;
|
||||
case STATUS_SUCCESS:
|
||||
return <CheckIcon size={size} />;
|
||||
default:
|
||||
return <CloseIcon size={size} />;
|
||||
}
|
||||
switch (status) {
|
||||
case STATUS_SKIPPED:
|
||||
return <RemoveIcon size={size} />;
|
||||
case STATUS_PENDING:
|
||||
return <ClockIcon size={size} />;
|
||||
case STATUS_RUNNING:
|
||||
case STATUS_STARTED:
|
||||
return <RefreshIcon size={size} />;
|
||||
case STATUS_SUCCESS:
|
||||
return <CheckIcon size={size} />;
|
||||
default:
|
||||
return <CloseIcon size={size} />;
|
||||
}
|
||||
};
|
||||
|
||||
export default class Status extends Component {
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.status !== nextProps.status;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props.status !== nextProps.status;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { status } = this.props;
|
||||
const icon = renderIcon(status, defaultIconSize);
|
||||
const classes = classnames(style.root, style[status]);
|
||||
return <div className={classes}>{icon}</div>;
|
||||
}
|
||||
render() {
|
||||
const { status } = this.props;
|
||||
const icon = renderIcon(status, defaultIconSize);
|
||||
const classes = classnames(style.root, style[status]);
|
||||
return <div className={classes}>{icon}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export const StatusLabel = ({ status }) => {
|
||||
return (
|
||||
<div className={classnames(style.label, style[status])}>
|
||||
<div>{statusLabel(status)}</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={classnames(style.label, style[status])}>
|
||||
<div>{statusLabel(status)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const StatusText = ({ status, text }) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames(style.label, style[status])}
|
||||
style="text-transform: capitalize;padding: 5px 10px;"
|
||||
>
|
||||
<div>{text}</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className={classnames(style.label, style[status])}
|
||||
style="text-transform: capitalize;padding: 5px 10px;"
|
||||
>
|
||||
<div>{text}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,9 +4,9 @@ import classnames from "classnames";
|
|||
import styles from "./status_number.less";
|
||||
|
||||
export default class StatusNumber extends Component {
|
||||
render() {
|
||||
const { status, number } = this.props;
|
||||
const className = classnames(styles.root, styles[status]);
|
||||
return <div className={className}>{number}</div>;
|
||||
}
|
||||
render() {
|
||||
const { status, number } = this.props;
|
||||
const className = classnames(styles.root, styles[status]);
|
||||
return <div className={className}>{number}</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@ import Icon from "./icons/refresh";
|
|||
import styles from "./sync.less";
|
||||
|
||||
export const Message = () => {
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.alert}>
|
||||
<div>
|
||||
<Icon />
|
||||
</div>
|
||||
<div>Account synchronization in progress</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.alert}>
|
||||
<div>
|
||||
<Icon />
|
||||
</div>
|
||||
<div>Account synchronization in progress</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -10,14 +10,14 @@ const STATUS_STARTED = "started";
|
|||
const STATUS_SUCCESS = "success";
|
||||
|
||||
export {
|
||||
STATUS_BLOCKED,
|
||||
STATUS_DECLINED,
|
||||
STATUS_ERROR,
|
||||
STATUS_FAILURE,
|
||||
STATUS_KILLED,
|
||||
STATUS_PENDING,
|
||||
STATUS_RUNNING,
|
||||
STATUS_SKIPPED,
|
||||
STATUS_SUCCESS,
|
||||
STATUS_STARTED,
|
||||
STATUS_BLOCKED,
|
||||
STATUS_DECLINED,
|
||||
STATUS_ERROR,
|
||||
STATUS_FAILURE,
|
||||
STATUS_KILLED,
|
||||
STATUS_PENDING,
|
||||
STATUS_RUNNING,
|
||||
STATUS_SKIPPED,
|
||||
STATUS_SUCCESS,
|
||||
STATUS_STARTED,
|
||||
};
|
||||
|
|
|
@ -13,26 +13,26 @@ import { STATUS_PENDING, STATUS_RUNNING } from "shared/constants/status";
|
|||
* @param {number|string} number - The build number.
|
||||
*/
|
||||
export const fetchBuild = (tree, client, owner, name, number) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
tree.unset(["builds", "loaded"]);
|
||||
client
|
||||
.getBuild(owner, name, number)
|
||||
.then(build => {
|
||||
const path = ["builds", "data", slug, build.number];
|
||||
tree.unset(["builds", "loaded"]);
|
||||
client
|
||||
.getBuild(owner, name, number)
|
||||
.then(build => {
|
||||
const path = ["builds", "data", slug, build.number];
|
||||
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, build);
|
||||
} else {
|
||||
tree.set(path, build);
|
||||
}
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, build);
|
||||
} else {
|
||||
tree.set(path, build);
|
||||
}
|
||||
|
||||
tree.set(["builds", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["builds", "loaded"], true);
|
||||
tree.set(["builds", "error"], error);
|
||||
});
|
||||
tree.set(["builds", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["builds", "loaded"], true);
|
||||
tree.set(["builds", "error"], error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -45,33 +45,33 @@ export const fetchBuild = (tree, client, owner, name, number) => {
|
|||
* @param {string} name - The repository name.
|
||||
*/
|
||||
export const fetchBuildList = (tree, client, owner, name, page = 1) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
tree.unset(["builds", "loaded"]);
|
||||
tree.unset(["builds", "error"]);
|
||||
tree.unset(["builds", "loaded"]);
|
||||
tree.unset(["builds", "error"]);
|
||||
|
||||
client
|
||||
.getBuildList(owner, name, { page: page })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
results.map(build => {
|
||||
list[build.number] = build;
|
||||
});
|
||||
client
|
||||
.getBuildList(owner, name, { page: page })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
results.map(build => {
|
||||
list[build.number] = build;
|
||||
});
|
||||
|
||||
const path = ["builds", "data", slug];
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, list);
|
||||
} else {
|
||||
tree.set(path, list);
|
||||
}
|
||||
const path = ["builds", "data", slug];
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, list);
|
||||
} else {
|
||||
tree.set(path, list);
|
||||
}
|
||||
|
||||
tree.unset(["builds", "error"]);
|
||||
tree.set(["builds", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["builds", "error"], error);
|
||||
tree.set(["builds", "loaded"], true);
|
||||
});
|
||||
tree.unset(["builds", "error"]);
|
||||
tree.set(["builds", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["builds", "error"], error);
|
||||
tree.set(["builds", "loaded"], true);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -85,14 +85,14 @@ export const fetchBuildList = (tree, client, owner, name, page = 1) => {
|
|||
* @param {number} proc - The process number.
|
||||
*/
|
||||
export const cancelBuild = (tree, client, owner, repo, build, proc) => {
|
||||
client
|
||||
.cancelBuild(owner, repo, build, proc)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully cancelled your build");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to cancel your build");
|
||||
});
|
||||
client
|
||||
.cancelBuild(owner, repo, build, proc)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully cancelled your build");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to cancel your build");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -105,14 +105,14 @@ export const cancelBuild = (tree, client, owner, repo, build, proc) => {
|
|||
* @param {number} build - The build number.
|
||||
*/
|
||||
export const restartBuild = (tree, client, owner, repo, build) => {
|
||||
client
|
||||
.restartBuild(owner, repo, build, { fork: true })
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully restarted your build");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to restart your build");
|
||||
});
|
||||
client
|
||||
.restartBuild(owner, repo, build, { fork: true })
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully restarted your build");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to restart your build");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -125,14 +125,14 @@ export const restartBuild = (tree, client, owner, repo, build) => {
|
|||
* @param {number} build - The build number.
|
||||
*/
|
||||
export const approveBuild = (tree, client, owner, repo, build) => {
|
||||
client
|
||||
.approveBuild(owner, repo, build)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully processed your approval decision");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to process your approval decision");
|
||||
});
|
||||
client
|
||||
.approveBuild(owner, repo, build)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully processed your approval decision");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to process your approval decision");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -145,14 +145,14 @@ export const approveBuild = (tree, client, owner, repo, build) => {
|
|||
* @param {number} build - The build number.
|
||||
*/
|
||||
export const declineBuild = (tree, client, owner, repo, build) => {
|
||||
client
|
||||
.declineBuild(owner, repo, build)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully processed your decline decision");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to process your decline decision");
|
||||
});
|
||||
client
|
||||
.declineBuild(owner, repo, build)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully processed your decline decision");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to process your decline decision");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -163,7 +163,7 @@ export const declineBuild = (tree, client, owner, repo, build) => {
|
|||
* @returns {number}
|
||||
*/
|
||||
export const compareBuild = (a, b) => {
|
||||
return b.number - a.number;
|
||||
return b.number - a.number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -173,7 +173,7 @@ export const compareBuild = (a, b) => {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export const assertBuildFinished = build => {
|
||||
return build.status !== STATUS_RUNNING && build.status !== STATUS_PENDING;
|
||||
return build.status !== STATUS_RUNNING && build.status !== STATUS_PENDING;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -183,5 +183,5 @@ export const assertBuildFinished = build => {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export const assertBuildMatrix = build => {
|
||||
return build && build.procs && build.procs.length > 1;
|
||||
return build && build.procs && build.procs.length > 1;
|
||||
};
|
||||
|
|
|
@ -6,24 +6,24 @@
|
|||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export const fetchFeed = (tree, client) => {
|
||||
client
|
||||
.getBuildFeed({ latest: true })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
let sorted = results.sort(compareFeedItem);
|
||||
sorted.map(repo => {
|
||||
list[repo.full_name] = repo;
|
||||
});
|
||||
if (sorted && sorted.length > 0) {
|
||||
tree.set(["feed", "latest"], sorted[0]);
|
||||
}
|
||||
tree.set(["feed", "loaded"], true);
|
||||
tree.set(["feed", "data"], list);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["feed", "loaded"], true);
|
||||
tree.set(["feed", "error"], error);
|
||||
});
|
||||
client
|
||||
.getBuildFeed({ latest: true })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
let sorted = results.sort(compareFeedItem);
|
||||
sorted.map(repo => {
|
||||
list[repo.full_name] = repo;
|
||||
});
|
||||
if (sorted && sorted.length > 0) {
|
||||
tree.set(["feed", "latest"], sorted[0]);
|
||||
}
|
||||
tree.set(["feed", "loaded"], true);
|
||||
tree.set(["feed", "data"], list);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["feed", "loaded"], true);
|
||||
tree.set(["feed", "error"], error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -34,11 +34,11 @@ export const fetchFeed = (tree, client) => {
|
|||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export function fetchFeedOnce(tree, client) {
|
||||
if (fetchFeedOnce.fired) {
|
||||
return;
|
||||
}
|
||||
fetchFeedOnce.fired = true;
|
||||
return fetchFeed(tree, client);
|
||||
if (fetchFeedOnce.fired) {
|
||||
return;
|
||||
}
|
||||
fetchFeedOnce.fired = true;
|
||||
return fetchFeed(tree, client);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,18 +49,18 @@ export function fetchFeedOnce(tree, client) {
|
|||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export const subscribeToFeed = (tree, client) => {
|
||||
return client.on(data => {
|
||||
const { repo, build } = data;
|
||||
return client.on(data => {
|
||||
const { repo, build } = data;
|
||||
|
||||
if (tree.exists("feed", "data", repo.full_name)) {
|
||||
const cursor = tree.select(["feed", "data", repo.full_name]);
|
||||
cursor.merge(build);
|
||||
}
|
||||
if (tree.exists("feed", "data", repo.full_name)) {
|
||||
const cursor = tree.select(["feed", "data", repo.full_name]);
|
||||
cursor.merge(build);
|
||||
}
|
||||
|
||||
if (tree.exists("builds", "data", repo.full_name)) {
|
||||
tree.set(["builds", "data", repo.full_name, build.number], build);
|
||||
}
|
||||
});
|
||||
if (tree.exists("builds", "data", repo.full_name)) {
|
||||
tree.set(["builds", "data", repo.full_name, build.number], build);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -71,11 +71,11 @@ export const subscribeToFeed = (tree, client) => {
|
|||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export function subscribeToFeedOnce(tree, client) {
|
||||
if (subscribeToFeedOnce.fired) {
|
||||
return;
|
||||
}
|
||||
subscribeToFeedOnce.fired = true;
|
||||
return subscribeToFeed(tree, client);
|
||||
if (subscribeToFeedOnce.fired) {
|
||||
return;
|
||||
}
|
||||
subscribeToFeedOnce.fired = true;
|
||||
return subscribeToFeed(tree, client);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +85,7 @@ export function subscribeToFeedOnce(tree, client) {
|
|||
* @returns {number}
|
||||
*/
|
||||
export const compareFeedItem = (a, b) => {
|
||||
return (
|
||||
(b.started_at || b.created_at || -1) - (a.started_at || a.created_at || -1)
|
||||
);
|
||||
return (
|
||||
(b.started_at || b.created_at || -1) - (a.started_at || a.created_at || -1)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
import { repositorySlug } from "./repository";
|
||||
|
||||
export function subscribeToLogs(tree, client, owner, repo, build, proc) {
|
||||
if (subscribeToLogs.ws) {
|
||||
subscribeToLogs.ws.close();
|
||||
}
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const init = { data: [] };
|
||||
if (subscribeToLogs.ws) {
|
||||
subscribeToLogs.ws.close();
|
||||
}
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const init = { data: [] };
|
||||
|
||||
tree.set(["logs", "data", slug, build, proc.pid], init);
|
||||
tree.set(["logs", "data", slug, build, proc.pid], init);
|
||||
|
||||
subscribeToLogs.ws = client.stream(owner, repo, build, proc.ppid, item => {
|
||||
if (item.proc === proc.name) {
|
||||
tree.push(["logs", "data", slug, build, proc.pid, "data"], item);
|
||||
}
|
||||
});
|
||||
subscribeToLogs.ws = client.stream(owner, repo, build, proc.ppid, item => {
|
||||
if (item.proc === proc.name) {
|
||||
tree.push(["logs", "data", slug, build, proc.pid, "data"], item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchLogs(tree, client, owner, repo, build, proc) {
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const init = {
|
||||
data: [],
|
||||
loading: true,
|
||||
};
|
||||
const slug = repositorySlug(owner, repo);
|
||||
const init = {
|
||||
data: [],
|
||||
loading: true,
|
||||
};
|
||||
|
||||
tree.set(["logs", "data", slug, build, proc], init);
|
||||
tree.set(["logs", "data", slug, build, proc], init);
|
||||
|
||||
client
|
||||
.getLogs(owner, repo, build, proc)
|
||||
.then(results => {
|
||||
tree.set(["logs", "data", slug, build, proc, "data"], results || []);
|
||||
tree.set(["logs", "data", slug, build, proc, "loading"], false);
|
||||
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
||||
})
|
||||
.catch(() => {
|
||||
tree.set(["logs", "data", slug, build, proc, "loading"], false);
|
||||
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
||||
});
|
||||
client
|
||||
.getLogs(owner, repo, build, proc)
|
||||
.then(results => {
|
||||
tree.set(["logs", "data", slug, build, proc, "data"], results || []);
|
||||
tree.set(["logs", "data", slug, build, proc, "loading"], false);
|
||||
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
||||
})
|
||||
.catch(() => {
|
||||
tree.set(["logs", "data", slug, build, proc, "loading"], false);
|
||||
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,5 +45,5 @@ export function fetchLogs(tree, client, owner, repo, build, proc) {
|
|||
* @param {boolean} follow - Follow the logs.
|
||||
*/
|
||||
export const toggleLogs = (tree, follow) => {
|
||||
tree.set(["logs", "follow"], follow);
|
||||
tree.set(["logs", "follow"], follow);
|
||||
};
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* @param {string} message - The message text.
|
||||
*/
|
||||
export const displayMessage = (tree, message) => {
|
||||
tree.set(["message", "text"], message);
|
||||
tree.set(["message", "text"], message);
|
||||
|
||||
setTimeout(() => {
|
||||
hideMessage(tree);
|
||||
}, 5000);
|
||||
setTimeout(() => {
|
||||
hideMessage(tree);
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -18,5 +18,5 @@ export const displayMessage = (tree, message) => {
|
|||
* @param {Object} tree - The drone state tree.
|
||||
*/
|
||||
export const hideMessage = tree => {
|
||||
tree.unset(["message", "text"]);
|
||||
tree.unset(["message", "text"]);
|
||||
};
|
||||
|
|
|
@ -9,20 +9,20 @@ import { STATUS_PENDING, STATUS_RUNNING } from "shared/constants/status";
|
|||
* @returns {Object}
|
||||
*/
|
||||
export const findChildProcess = (tree, pid) => {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
const parent = tree[i];
|
||||
// eslint-disable-next-line
|
||||
if (parent.pid == pid) {
|
||||
return parent;
|
||||
}
|
||||
for (var ii = 0; ii < parent.children.length; ii++) {
|
||||
const child = parent.children[ii];
|
||||
// eslint-disable-next-line
|
||||
if (child.pid == pid) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
const parent = tree[i];
|
||||
// eslint-disable-next-line
|
||||
if (parent.pid == pid) {
|
||||
return parent;
|
||||
}
|
||||
for (var ii = 0; ii < parent.children.length; ii++) {
|
||||
const child = parent.children[ii];
|
||||
// eslint-disable-next-line
|
||||
if (child.pid == pid) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ export const findChildProcess = (tree, pid) => {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export const assertProcFinished = proc => {
|
||||
return proc.state !== STATUS_RUNNING && proc.state !== STATUS_PENDING;
|
||||
return proc.state !== STATUS_RUNNING && proc.state !== STATUS_PENDING;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -42,5 +42,5 @@ export const assertProcFinished = proc => {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export const assertProcRunning = proc => {
|
||||
return proc.state === STATUS_RUNNING;
|
||||
return proc.state === STATUS_RUNNING;
|
||||
};
|
||||
|
|
|
@ -11,19 +11,19 @@ import { repositorySlug } from "./repository";
|
|||
* @param {string} name - The repository name.
|
||||
*/
|
||||
export const fetchRegistryList = (tree, client, owner, name) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
tree.unset(["registry", "loaded"]);
|
||||
tree.unset(["registry", "error"]);
|
||||
tree.unset(["registry", "loaded"]);
|
||||
tree.unset(["registry", "error"]);
|
||||
|
||||
client.getRegistryList(owner, name).then(results => {
|
||||
let list = {};
|
||||
results.map(registry => {
|
||||
list[registry.address] = registry;
|
||||
});
|
||||
tree.set(["registry", "data", slug], list);
|
||||
tree.set(["registry", "loaded"], true);
|
||||
});
|
||||
client.getRegistryList(owner, name).then(results => {
|
||||
let list = {};
|
||||
results.map(registry => {
|
||||
list[registry.address] = registry;
|
||||
});
|
||||
tree.set(["registry", "data", slug], list);
|
||||
tree.set(["registry", "loaded"], true);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -37,17 +37,17 @@ export const fetchRegistryList = (tree, client, owner, name) => {
|
|||
* @param {Object} registry - The registry hostname.
|
||||
*/
|
||||
export const createRegistry = (tree, client, owner, name, registry) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
client
|
||||
.createRegistry(owner, name, registry)
|
||||
.then(result => {
|
||||
tree.set(["registry", "data", slug, registry.address], result);
|
||||
displayMessage(tree, "Successfully stored the registry credentials");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to store the registry credentials");
|
||||
});
|
||||
client
|
||||
.createRegistry(owner, name, registry)
|
||||
.then(result => {
|
||||
tree.set(["registry", "data", slug, registry.address], result);
|
||||
displayMessage(tree, "Successfully stored the registry credentials");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to store the registry credentials");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,15 +61,15 @@ export const createRegistry = (tree, client, owner, name, registry) => {
|
|||
* @param {Object} registry - The registry hostname.
|
||||
*/
|
||||
export const deleteRegistry = (tree, client, owner, name, registry) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
client
|
||||
.deleteRegistry(owner, name, registry)
|
||||
.then(result => {
|
||||
tree.unset(["registry", "data", slug, registry]);
|
||||
displayMessage(tree, "Successfully deleted the registry credentials");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to delete the registry credentials");
|
||||
});
|
||||
client
|
||||
.deleteRegistry(owner, name, registry)
|
||||
.then(result => {
|
||||
tree.unset(["registry", "data", slug, registry]);
|
||||
displayMessage(tree, "Successfully deleted the registry credentials");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to delete the registry credentials");
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,19 +11,19 @@ import { fetchFeed } from "shared/utils/feed";
|
|||
* @param {string} name - The repository name.
|
||||
*/
|
||||
export const fetchRepository = (tree, client, owner, name) => {
|
||||
tree.unset(["repo", "error"]);
|
||||
tree.unset(["repo", "loaded"]);
|
||||
tree.unset(["repo", "error"]);
|
||||
tree.unset(["repo", "loaded"]);
|
||||
|
||||
client
|
||||
.getRepo(owner, name)
|
||||
.then(repo => {
|
||||
tree.set(["repos", "data", repo.full_name], repo);
|
||||
tree.set(["repo", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["repo", "error"], error);
|
||||
tree.set(["repo", "loaded"], true);
|
||||
});
|
||||
client
|
||||
.getRepo(owner, name)
|
||||
.then(repo => {
|
||||
tree.set(["repos", "data", repo.full_name], repo);
|
||||
tree.set(["repo", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["repo", "error"], error);
|
||||
tree.set(["repo", "loaded"], true);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -34,30 +34,30 @@ export const fetchRepository = (tree, client, owner, name) => {
|
|||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export const fetchRepostoryList = (tree, client) => {
|
||||
tree.unset(["repos", "loaded"]);
|
||||
tree.unset(["repos", "error"]);
|
||||
tree.unset(["repos", "loaded"]);
|
||||
tree.unset(["repos", "error"]);
|
||||
|
||||
client
|
||||
.getRepoList({ all: true })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
results.map(repo => {
|
||||
list[repo.full_name] = repo;
|
||||
});
|
||||
client
|
||||
.getRepoList({ all: true })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
results.map(repo => {
|
||||
list[repo.full_name] = repo;
|
||||
});
|
||||
|
||||
const path = ["repos", "data"];
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, list);
|
||||
} else {
|
||||
tree.set(path, list);
|
||||
}
|
||||
const path = ["repos", "data"];
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, list);
|
||||
} else {
|
||||
tree.set(path, list);
|
||||
}
|
||||
|
||||
tree.set(["repos", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["repos", "loaded"], true);
|
||||
tree.set(["repos", "error"], error);
|
||||
});
|
||||
tree.set(["repos", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
tree.set(["repos", "loaded"], true);
|
||||
tree.set(["repos", "error"], error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -68,32 +68,32 @@ export const fetchRepostoryList = (tree, client) => {
|
|||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export const syncRepostoryList = (tree, client) => {
|
||||
tree.unset(["repos", "loaded"]);
|
||||
tree.unset(["repos", "error"]);
|
||||
tree.unset(["repos", "loaded"]);
|
||||
tree.unset(["repos", "error"]);
|
||||
|
||||
client
|
||||
.getRepoList({ all: true, flush: true })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
results.map(repo => {
|
||||
list[repo.full_name] = repo;
|
||||
});
|
||||
client
|
||||
.getRepoList({ all: true, flush: true })
|
||||
.then(results => {
|
||||
let list = {};
|
||||
results.map(repo => {
|
||||
list[repo.full_name] = repo;
|
||||
});
|
||||
|
||||
const path = ["repos", "data"];
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, list);
|
||||
} else {
|
||||
tree.set(path, list);
|
||||
}
|
||||
const path = ["repos", "data"];
|
||||
if (tree.exists(path)) {
|
||||
tree.deepMerge(path, list);
|
||||
} else {
|
||||
tree.set(path, list);
|
||||
}
|
||||
|
||||
displayMessage(tree, "Successfully synchronized your repository list");
|
||||
tree.set(["repos", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
displayMessage(tree, "Failed to synchronize your repository list");
|
||||
tree.set(["repos", "loaded"], true);
|
||||
tree.set(["repos", "error"], error);
|
||||
});
|
||||
displayMessage(tree, "Successfully synchronized your repository list");
|
||||
tree.set(["repos", "loaded"], true);
|
||||
})
|
||||
.catch(error => {
|
||||
displayMessage(tree, "Failed to synchronize your repository list");
|
||||
tree.set(["repos", "loaded"], true);
|
||||
tree.set(["repos", "error"], error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -107,15 +107,15 @@ export const syncRepostoryList = (tree, client) => {
|
|||
* @param {Object} data - The repository updates.
|
||||
*/
|
||||
export const updateRepository = (tree, client, owner, name, data) => {
|
||||
client
|
||||
.updateRepo(owner, name, data)
|
||||
.then(repo => {
|
||||
tree.set(["repos", "data", repo.full_name], repo);
|
||||
displayMessage(tree, "Successfully updated the repository settings");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to update the repository settings");
|
||||
});
|
||||
client
|
||||
.updateRepo(owner, name, data)
|
||||
.then(repo => {
|
||||
tree.set(["repos", "data", repo.full_name], repo);
|
||||
displayMessage(tree, "Successfully updated the repository settings");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to update the repository settings");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -128,16 +128,16 @@ export const updateRepository = (tree, client, owner, name, data) => {
|
|||
* @param {string} name - The repository name.
|
||||
*/
|
||||
export const enableRepository = (tree, client, owner, name) => {
|
||||
client
|
||||
.activateRepo(owner, name)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully activated your repository");
|
||||
tree.set(["repos", "data", result.full_name, "active"], true);
|
||||
fetchFeed(tree, client);
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to activate your repository");
|
||||
});
|
||||
client
|
||||
.activateRepo(owner, name)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully activated your repository");
|
||||
tree.set(["repos", "data", result.full_name, "active"], true);
|
||||
fetchFeed(tree, client);
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to activate your repository");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -150,16 +150,16 @@ export const enableRepository = (tree, client, owner, name) => {
|
|||
* @param {string} name - The repository name.
|
||||
*/
|
||||
export const disableRepository = (tree, client, owner, name) => {
|
||||
client
|
||||
.deleteRepo(owner, name)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully disabled your repository");
|
||||
tree.set(["repos", "data", result.full_name, "active"], false);
|
||||
fetchFeed(tree, client);
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to disabled your repository");
|
||||
});
|
||||
client
|
||||
.deleteRepo(owner, name)
|
||||
.then(result => {
|
||||
displayMessage(tree, "Successfully disabled your repository");
|
||||
tree.set(["repos", "data", result.full_name, "active"], false);
|
||||
fetchFeed(tree, client);
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to disabled your repository");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -170,9 +170,9 @@ export const disableRepository = (tree, client, owner, name) => {
|
|||
* @returns {number}
|
||||
*/
|
||||
export const compareRepository = (a, b) => {
|
||||
if (a.full_name < b.full_name) return -1;
|
||||
if (a.full_name > b.full_name) return 1;
|
||||
return 0;
|
||||
if (a.full_name < b.full_name) return -1;
|
||||
if (a.full_name > b.full_name) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -182,5 +182,5 @@ export const compareRepository = (a, b) => {
|
|||
* @param {string} name - The process name.
|
||||
*/
|
||||
export const repositorySlug = (owner, name) => {
|
||||
return `${owner}/${name}`;
|
||||
return `${owner}/${name}`;
|
||||
};
|
||||
|
|
|
@ -11,19 +11,19 @@ import { repositorySlug } from "./repository";
|
|||
* @param {string} name - The repository name.
|
||||
*/
|
||||
export const fetchSecretList = (tree, client, owner, name) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
tree.unset(["secrets", "loaded"]);
|
||||
tree.unset(["secrets", "error"]);
|
||||
tree.unset(["secrets", "loaded"]);
|
||||
tree.unset(["secrets", "error"]);
|
||||
|
||||
client.getSecretList(owner, name).then(results => {
|
||||
let list = {};
|
||||
results.map(secret => {
|
||||
list[secret.name] = secret;
|
||||
});
|
||||
tree.set(["secrets", "data", slug], list);
|
||||
tree.set(["secrets", "loaded"], true);
|
||||
});
|
||||
client.getSecretList(owner, name).then(results => {
|
||||
let list = {};
|
||||
results.map(secret => {
|
||||
list[secret.name] = secret;
|
||||
});
|
||||
tree.set(["secrets", "data", slug], list);
|
||||
tree.set(["secrets", "loaded"], true);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -37,17 +37,17 @@ export const fetchSecretList = (tree, client, owner, name) => {
|
|||
* @param {Object} secret - The secret object.
|
||||
*/
|
||||
export const createSecret = (tree, client, owner, name, secret) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
client
|
||||
.createSecret(owner, name, secret)
|
||||
.then(result => {
|
||||
tree.set(["secrets", "data", slug, secret.name], result);
|
||||
displayMessage(tree, "Successfully added the secret");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to create the secret");
|
||||
});
|
||||
client
|
||||
.createSecret(owner, name, secret)
|
||||
.then(result => {
|
||||
tree.set(["secrets", "data", slug, secret.name], result);
|
||||
displayMessage(tree, "Successfully added the secret");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to create the secret");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,15 +61,15 @@ export const createSecret = (tree, client, owner, name, secret) => {
|
|||
* @param {string} secret - The secret name.
|
||||
*/
|
||||
export const deleteSecret = (tree, client, owner, name, secret) => {
|
||||
const slug = repositorySlug(owner, name);
|
||||
const slug = repositorySlug(owner, name);
|
||||
|
||||
client
|
||||
.deleteSecret(owner, name, secret)
|
||||
.then(result => {
|
||||
tree.unset(["secrets", "data", slug, secret]);
|
||||
displayMessage(tree, "Successfully removed the secret");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to remove the secret");
|
||||
});
|
||||
client
|
||||
.deleteSecret(owner, name, secret)
|
||||
.then(result => {
|
||||
tree.unset(["secrets", "data", slug, secret]);
|
||||
displayMessage(tree, "Successfully removed the secret");
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to remove the secret");
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { displayMessage } from "./message";
|
||||
|
||||
/**
|
||||
* Generates a personal access token and stores the results in
|
||||
* the state tree.
|
||||
* Generates a personal access token and stores the results in
|
||||
* the state tree.
|
||||
*
|
||||
* @param {Object} tree - The drone state tree.
|
||||
* @param {Object} client - The drone client.
|
||||
*/
|
||||
export const generateToken = (tree, client) => {
|
||||
client
|
||||
.getToken()
|
||||
.then(token => {
|
||||
tree.set(["token"], token);
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to retrieve your personal access token");
|
||||
});
|
||||
client
|
||||
.getToken()
|
||||
.then(token => {
|
||||
tree.set(["token"], token);
|
||||
})
|
||||
.catch(() => {
|
||||
displayMessage(tree, "Failed to retrieve your personal access token");
|
||||
});
|
||||
};
|
||||
|
|
713
web/vendor/drone-js/index.js
vendored
713
web/vendor/drone-js/index.js
vendored
|
@ -1,306 +1,431 @@
|
|||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["exports"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(exports);
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports);
|
||||
global.index = mod.exports;
|
||||
}
|
||||
})(this, function (exports) {
|
||||
"use strict";
|
||||
(function(global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["exports"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(exports);
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports);
|
||||
global.index = mod.exports;
|
||||
}
|
||||
})(this, function(exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
function _classCallCheck(instance, Constructor) {
|
||||
if (!(instance instanceof Constructor)) {
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
}
|
||||
function _classCallCheck(instance, Constructor) {
|
||||
if (!(instance instanceof Constructor)) {
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
}
|
||||
|
||||
var _createClass = function () {
|
||||
function defineProperties(target, props) {
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var descriptor = props[i];
|
||||
descriptor.enumerable = descriptor.enumerable || false;
|
||||
descriptor.configurable = true;
|
||||
if ("value" in descriptor) descriptor.writable = true;
|
||||
Object.defineProperty(target, descriptor.key, descriptor);
|
||||
}
|
||||
}
|
||||
var _createClass = (function() {
|
||||
function defineProperties(target, props) {
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var descriptor = props[i];
|
||||
descriptor.enumerable = descriptor.enumerable || false;
|
||||
descriptor.configurable = true;
|
||||
if ("value" in descriptor) descriptor.writable = true;
|
||||
Object.defineProperty(target, descriptor.key, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return function (Constructor, protoProps, staticProps) {
|
||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||
if (staticProps) defineProperties(Constructor, staticProps);
|
||||
return Constructor;
|
||||
};
|
||||
}();
|
||||
return function(Constructor, protoProps, staticProps) {
|
||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||
if (staticProps) defineProperties(Constructor, staticProps);
|
||||
return Constructor;
|
||||
};
|
||||
})();
|
||||
|
||||
var DroneClient = function () {
|
||||
function DroneClient(server, token, csrf) {
|
||||
_classCallCheck(this, DroneClient);
|
||||
var DroneClient = (function() {
|
||||
function DroneClient(server, token, csrf) {
|
||||
_classCallCheck(this, DroneClient);
|
||||
|
||||
this.server = server || "";
|
||||
this.token = token;
|
||||
this.csrf = csrf;
|
||||
}
|
||||
this.server = server || "";
|
||||
this.token = token;
|
||||
this.csrf = csrf;
|
||||
}
|
||||
|
||||
_createClass(DroneClient, [{
|
||||
key: "getRepoList",
|
||||
value: function getRepoList(opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._get("/api/user/repos?" + query);
|
||||
}
|
||||
}, {
|
||||
key: "getRepo",
|
||||
value: function getRepo(owner, repo) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo);
|
||||
}
|
||||
}, {
|
||||
key: "activateRepo",
|
||||
value: function activateRepo(owner, repo) {
|
||||
return this._post("/api/repos/" + owner + "/" + repo);
|
||||
}
|
||||
}, {
|
||||
key: "updateRepo",
|
||||
value: function updateRepo(owner, repo, data) {
|
||||
return this._patch("/api/repos/" + owner + "/" + repo, data);
|
||||
}
|
||||
}, {
|
||||
key: "deleteRepo",
|
||||
value: function deleteRepo(owner, repo) {
|
||||
return this._delete("/api/repos/" + owner + "/" + repo);
|
||||
}
|
||||
}, {
|
||||
key: "getBuildList",
|
||||
value: function getBuildList(owner, repo, opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/builds?" + query);
|
||||
}
|
||||
}, {
|
||||
key: "getBuild",
|
||||
value: function getBuild(owner, repo, number) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/builds/" + number);
|
||||
}
|
||||
}, {
|
||||
key: "getBuildFeed",
|
||||
value: function getBuildFeed(opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._get("/api/user/feed?" + query);
|
||||
}
|
||||
}, {
|
||||
key: "cancelBuild",
|
||||
value: function cancelBuild(owner, repo, number, ppid) {
|
||||
return this._delete("/api/repos/" + owner + "/" + repo + "/builds/" + number + "/" + ppid);
|
||||
}
|
||||
}, {
|
||||
key: "approveBuild",
|
||||
value: function approveBuild(owner, repo, build) {
|
||||
return this._post("/api/repos/" + owner + "/" + repo + "/builds/" + build + "/approve");
|
||||
}
|
||||
}, {
|
||||
key: "declineBuild",
|
||||
value: function declineBuild(owner, repo, build) {
|
||||
return this._post("/api/repos/" + owner + "/" + repo + "/builds/" + build + "/decline");
|
||||
}
|
||||
}, {
|
||||
key: "restartBuild",
|
||||
value: function restartBuild(owner, repo, build, opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._post("/api/repos/" + owner + "/" + repo + "/builds/" + build + "?" + query);
|
||||
}
|
||||
}, {
|
||||
key: "getLogs",
|
||||
value: function getLogs(owner, repo, build, proc) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/logs/" + build + "/" + proc);
|
||||
}
|
||||
}, {
|
||||
key: "getArtifact",
|
||||
value: function getArtifact(owner, repo, build, proc, file) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/files/" + build + "/" + proc + "/" + file + "?raw=true");
|
||||
}
|
||||
}, {
|
||||
key: "getArtifactList",
|
||||
value: function getArtifactList(owner, repo, build) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/files/" + build);
|
||||
}
|
||||
}, {
|
||||
key: "getSecretList",
|
||||
value: function getSecretList(owner, repo) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/secrets");
|
||||
}
|
||||
}, {
|
||||
key: "createSecret",
|
||||
value: function createSecret(owner, repo, secret) {
|
||||
return this._post("/api/repos/" + owner + "/" + repo + "/secrets", secret);
|
||||
}
|
||||
}, {
|
||||
key: "deleteSecret",
|
||||
value: function deleteSecret(owner, repo, secret) {
|
||||
return this._delete("/api/repos/" + owner + "/" + repo + "/secrets/" + secret);
|
||||
}
|
||||
}, {
|
||||
key: "getRegistryList",
|
||||
value: function getRegistryList(owner, repo) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/registry");
|
||||
}
|
||||
}, {
|
||||
key: "createRegistry",
|
||||
value: function createRegistry(owner, repo, registry) {
|
||||
return this._post("/api/repos/" + owner + "/" + repo + "/registry", registry);
|
||||
}
|
||||
}, {
|
||||
key: "deleteRegistry",
|
||||
value: function deleteRegistry(owner, repo, address) {
|
||||
return this._delete("/api/repos/" + owner + "/" + repo + "/registry/" + address);
|
||||
}
|
||||
}, {
|
||||
key: "getSelf",
|
||||
value: function getSelf() {
|
||||
return this._get("/api/user");
|
||||
}
|
||||
}, {
|
||||
key: "getToken",
|
||||
value: function getToken() {
|
||||
return this._post("/api/user/token");
|
||||
}
|
||||
}, {
|
||||
key: "on",
|
||||
value: function on(callback) {
|
||||
return this._subscribe("/stream/events", callback, {
|
||||
reconnect: true
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "stream",
|
||||
value: function stream(owner, repo, build, proc, callback) {
|
||||
return this._subscribe("/stream/logs/" + owner + "/" + repo + "/" + build + "/" + proc, callback, {
|
||||
reconnect: false
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "_get",
|
||||
value: function _get(path) {
|
||||
return this._request("GET", path, null);
|
||||
}
|
||||
}, {
|
||||
key: "_post",
|
||||
value: function _post(path, data) {
|
||||
return this._request("POST", path, data);
|
||||
}
|
||||
}, {
|
||||
key: "_patch",
|
||||
value: function _patch(path, data) {
|
||||
return this._request("PATCH", path, data);
|
||||
}
|
||||
}, {
|
||||
key: "_delete",
|
||||
value: function _delete(path) {
|
||||
return this._request("DELETE", path, null);
|
||||
}
|
||||
}, {
|
||||
key: "_subscribe",
|
||||
value: function _subscribe(path, callback, opts) {
|
||||
var query = encodeQueryString({
|
||||
access_token: this.token
|
||||
});
|
||||
path = this.server ? this.server + path : path;
|
||||
path = this.token ? path + "?" + query : path;
|
||||
_createClass(
|
||||
DroneClient,
|
||||
[
|
||||
{
|
||||
key: "getRepoList",
|
||||
value: function getRepoList(opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._get("/api/user/repos?" + query);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getRepo",
|
||||
value: function getRepo(owner, repo) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "activateRepo",
|
||||
value: function activateRepo(owner, repo) {
|
||||
return this._post("/api/repos/" + owner + "/" + repo);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "updateRepo",
|
||||
value: function updateRepo(owner, repo, data) {
|
||||
return this._patch("/api/repos/" + owner + "/" + repo, data);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "deleteRepo",
|
||||
value: function deleteRepo(owner, repo) {
|
||||
return this._delete("/api/repos/" + owner + "/" + repo);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getBuildList",
|
||||
value: function getBuildList(owner, repo, opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._get(
|
||||
"/api/repos/" + owner + "/" + repo + "/builds?" + query
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getBuild",
|
||||
value: function getBuild(owner, repo, number) {
|
||||
return this._get(
|
||||
"/api/repos/" + owner + "/" + repo + "/builds/" + number
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getBuildFeed",
|
||||
value: function getBuildFeed(opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._get("/api/user/feed?" + query);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cancelBuild",
|
||||
value: function cancelBuild(owner, repo, number, ppid) {
|
||||
return this._delete(
|
||||
"/api/repos/" +
|
||||
owner +
|
||||
"/" +
|
||||
repo +
|
||||
"/builds/" +
|
||||
number +
|
||||
"/" +
|
||||
ppid
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "approveBuild",
|
||||
value: function approveBuild(owner, repo, build) {
|
||||
return this._post(
|
||||
"/api/repos/" +
|
||||
owner +
|
||||
"/" +
|
||||
repo +
|
||||
"/builds/" +
|
||||
build +
|
||||
"/approve"
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "declineBuild",
|
||||
value: function declineBuild(owner, repo, build) {
|
||||
return this._post(
|
||||
"/api/repos/" +
|
||||
owner +
|
||||
"/" +
|
||||
repo +
|
||||
"/builds/" +
|
||||
build +
|
||||
"/decline"
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "restartBuild",
|
||||
value: function restartBuild(owner, repo, build, opts) {
|
||||
var query = encodeQueryString(opts);
|
||||
return this._post(
|
||||
"/api/repos/" +
|
||||
owner +
|
||||
"/" +
|
||||
repo +
|
||||
"/builds/" +
|
||||
build +
|
||||
"?" +
|
||||
query
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getLogs",
|
||||
value: function getLogs(owner, repo, build, proc) {
|
||||
return this._get(
|
||||
"/api/repos/" + owner + "/" + repo + "/logs/" + build + "/" + proc
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getArtifact",
|
||||
value: function getArtifact(owner, repo, build, proc, file) {
|
||||
return this._get(
|
||||
"/api/repos/" +
|
||||
owner +
|
||||
"/" +
|
||||
repo +
|
||||
"/files/" +
|
||||
build +
|
||||
"/" +
|
||||
proc +
|
||||
"/" +
|
||||
file +
|
||||
"?raw=true"
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getArtifactList",
|
||||
value: function getArtifactList(owner, repo, build) {
|
||||
return this._get(
|
||||
"/api/repos/" + owner + "/" + repo + "/files/" + build
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getSecretList",
|
||||
value: function getSecretList(owner, repo) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/secrets");
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "createSecret",
|
||||
value: function createSecret(owner, repo, secret) {
|
||||
return this._post(
|
||||
"/api/repos/" + owner + "/" + repo + "/secrets",
|
||||
secret
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "deleteSecret",
|
||||
value: function deleteSecret(owner, repo, secret) {
|
||||
return this._delete(
|
||||
"/api/repos/" + owner + "/" + repo + "/secrets/" + secret
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getRegistryList",
|
||||
value: function getRegistryList(owner, repo) {
|
||||
return this._get("/api/repos/" + owner + "/" + repo + "/registry");
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "createRegistry",
|
||||
value: function createRegistry(owner, repo, registry) {
|
||||
return this._post(
|
||||
"/api/repos/" + owner + "/" + repo + "/registry",
|
||||
registry
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "deleteRegistry",
|
||||
value: function deleteRegistry(owner, repo, address) {
|
||||
return this._delete(
|
||||
"/api/repos/" + owner + "/" + repo + "/registry/" + address
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getSelf",
|
||||
value: function getSelf() {
|
||||
return this._get("/api/user");
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "getToken",
|
||||
value: function getToken() {
|
||||
return this._post("/api/user/token");
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "on",
|
||||
value: function on(callback) {
|
||||
return this._subscribe("/stream/events", callback, {
|
||||
reconnect: true
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "stream",
|
||||
value: function stream(owner, repo, build, proc, callback) {
|
||||
return this._subscribe(
|
||||
"/stream/logs/" + owner + "/" + repo + "/" + build + "/" + proc,
|
||||
callback,
|
||||
{
|
||||
reconnect: false
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "_get",
|
||||
value: function _get(path) {
|
||||
return this._request("GET", path, null);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "_post",
|
||||
value: function _post(path, data) {
|
||||
return this._request("POST", path, data);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "_patch",
|
||||
value: function _patch(path, data) {
|
||||
return this._request("PATCH", path, data);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "_delete",
|
||||
value: function _delete(path) {
|
||||
return this._request("DELETE", path, null);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "_subscribe",
|
||||
value: function _subscribe(path, callback, opts) {
|
||||
var query = encodeQueryString({
|
||||
access_token: this.token
|
||||
});
|
||||
path = this.server ? this.server + path : path;
|
||||
path = this.token ? path + "?" + query : path;
|
||||
|
||||
var events = new EventSource(path);
|
||||
events.onmessage = function (event) {
|
||||
var data = JSON.parse(event.data);
|
||||
callback(data);
|
||||
};
|
||||
if (!opts.reconnect) {
|
||||
events.onerror = function (err) {
|
||||
if (err.data === "eof") {
|
||||
events.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
return events;
|
||||
}
|
||||
}, {
|
||||
key: "_request",
|
||||
value: function _request(method, path, data) {
|
||||
var endpoint = [this.server, path].join("");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(method, endpoint, true);
|
||||
if (this.token) {
|
||||
xhr.setRequestHeader("Authorization", "Bearer " + this.token);
|
||||
}
|
||||
if (method !== "GET" && this.csrf) {
|
||||
xhr.setRequestHeader("X-CSRF-TOKEN", this.csrf);
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
xhr.onload = function () {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status >= 300) {
|
||||
var error = {
|
||||
status: xhr.status,
|
||||
message: xhr.response
|
||||
};
|
||||
if (this.onerror) {
|
||||
this.onerror(error);
|
||||
}
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
var contentType = xhr.getResponseHeader("Content-Type");
|
||||
if (contentType && contentType.startsWith("application/json")) {
|
||||
resolve(JSON.parse(xhr.response));
|
||||
} else {
|
||||
resolve(xhr.response);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
xhr.onerror = function (e) {
|
||||
reject(e);
|
||||
};
|
||||
if (data) {
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send(JSON.stringify(data));
|
||||
} else {
|
||||
xhr.send();
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}], [{
|
||||
key: "fromEnviron",
|
||||
value: function fromEnviron() {
|
||||
return new DroneClient(process && process.env && process.env.DRONE_SERVER, process && process.env && process.env.DRONE_TOKEN, process && process.env && process.env.DRONE_CSRF);
|
||||
}
|
||||
}, {
|
||||
key: "fromWindow",
|
||||
value: function fromWindow() {
|
||||
return new DroneClient(window && window.DRONE_SERVER, window && window.DRONE_TOKEN, window && window.DRONE_CSRF);
|
||||
}
|
||||
}]);
|
||||
var events = new EventSource(path);
|
||||
events.onmessage = function(event) {
|
||||
var data = JSON.parse(event.data);
|
||||
callback(data);
|
||||
};
|
||||
if (!opts.reconnect) {
|
||||
events.onerror = function(err) {
|
||||
if (err.data === "eof") {
|
||||
events.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
return events;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "_request",
|
||||
value: function _request(method, path, data) {
|
||||
var endpoint = [this.server, path].join("");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(method, endpoint, true);
|
||||
if (this.token) {
|
||||
xhr.setRequestHeader("Authorization", "Bearer " + this.token);
|
||||
}
|
||||
if (method !== "GET" && this.csrf) {
|
||||
xhr.setRequestHeader("X-CSRF-TOKEN", this.csrf);
|
||||
}
|
||||
return new Promise(
|
||||
function(resolve, reject) {
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status >= 300) {
|
||||
var error = {
|
||||
status: xhr.status,
|
||||
message: xhr.response
|
||||
};
|
||||
if (this.onerror) {
|
||||
this.onerror(error);
|
||||
}
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
var contentType = xhr.getResponseHeader("Content-Type");
|
||||
if (
|
||||
contentType &&
|
||||
contentType.startsWith("application/json")
|
||||
) {
|
||||
resolve(JSON.parse(xhr.response));
|
||||
} else {
|
||||
resolve(xhr.response);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
xhr.onerror = function(e) {
|
||||
reject(e);
|
||||
};
|
||||
if (data) {
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send(JSON.stringify(data));
|
||||
} else {
|
||||
xhr.send();
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
key: "fromEnviron",
|
||||
value: function fromEnviron() {
|
||||
return new DroneClient(
|
||||
process && process.env && process.env.DRONE_SERVER,
|
||||
process && process.env && process.env.DRONE_TOKEN,
|
||||
process && process.env && process.env.DRONE_CSRF
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "fromWindow",
|
||||
value: function fromWindow() {
|
||||
return new DroneClient(
|
||||
window && window.DRONE_SERVER,
|
||||
window && window.DRONE_TOKEN,
|
||||
window && window.DRONE_CSRF
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
return DroneClient;
|
||||
}();
|
||||
return DroneClient;
|
||||
})();
|
||||
|
||||
exports.default = DroneClient;
|
||||
exports.default = DroneClient;
|
||||
|
||||
/**
|
||||
* Encodes the values into url encoded form sorted by key.
|
||||
*
|
||||
* @param {object} query parameters in key value object.
|
||||
* @return {string} query parameter string
|
||||
*/
|
||||
var encodeQueryString = (exports.encodeQueryString = function encodeQueryString() {
|
||||
var params =
|
||||
arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
|
||||
/**
|
||||
* Encodes the values into url encoded form sorted by key.
|
||||
*
|
||||
* @param {object} query parameters in key value object.
|
||||
* @return {string} query parameter string
|
||||
*/
|
||||
var encodeQueryString = exports.encodeQueryString = function encodeQueryString() {
|
||||
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
|
||||
return params ? Object.keys(params).sort().map(function (key) {
|
||||
var val = params[key];
|
||||
return encodeURIComponent(key) + "=" + encodeURIComponent(val);
|
||||
}).join("&") : "";
|
||||
};
|
||||
});
|
||||
return params
|
||||
? Object.keys(params)
|
||||
.sort()
|
||||
.map(function(key) {
|
||||
var val = params[key];
|
||||
return encodeURIComponent(key) + "=" + encodeURIComponent(val);
|
||||
})
|
||||
.join("&")
|
||||
: "";
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,154 +7,154 @@ var HtmlWebpackPlugin = require("html-webpack-plugin");
|
|||
const ENV = process.env.NODE_ENV || "development";
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: "./src",
|
||||
vendor: [
|
||||
"ansi_up",
|
||||
"babel-polyfill",
|
||||
"baobab",
|
||||
"baobab-react",
|
||||
"classnames",
|
||||
"drone-js",
|
||||
"humanize-duration",
|
||||
"preact",
|
||||
"preact-compat",
|
||||
"query-string",
|
||||
"react-router",
|
||||
"react-router-dom",
|
||||
"react-screen-size",
|
||||
"react-timeago",
|
||||
"react-title-component",
|
||||
"react-transition-group"
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
app: "./src",
|
||||
vendor: [
|
||||
"ansi_up",
|
||||
"babel-polyfill",
|
||||
"baobab",
|
||||
"baobab-react",
|
||||
"classnames",
|
||||
"drone-js",
|
||||
"humanize-duration",
|
||||
"preact",
|
||||
"preact-compat",
|
||||
"query-string",
|
||||
"react-router",
|
||||
"react-router-dom",
|
||||
"react-screen-size",
|
||||
"react-timeago",
|
||||
"react-title-component",
|
||||
"react-transition-group"
|
||||
]
|
||||
},
|
||||
|
||||
// where to dump the output of a production build
|
||||
output: {
|
||||
publicPath: "/",
|
||||
path: path.join(__dirname, "dist/files"),
|
||||
filename: "static/bundle.[chunkhash].js"
|
||||
},
|
||||
// where to dump the output of a production build
|
||||
output: {
|
||||
publicPath: "/",
|
||||
path: path.join(__dirname, "dist/files"),
|
||||
filename: "static/bundle.[chunkhash].js"
|
||||
},
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
client: path.resolve(__dirname, "src/client/"),
|
||||
config: path.resolve(__dirname, "src/config/"),
|
||||
components: path.resolve(__dirname, "src/components/"),
|
||||
layouts: path.resolve(__dirname, "src/layouts/"),
|
||||
pages: path.resolve(__dirname, "src/pages/"),
|
||||
screens: path.resolve(__dirname, "src/screens/"),
|
||||
shared: path.resolve(__dirname, "src/shared/"),
|
||||
resolve: {
|
||||
alias: {
|
||||
client: path.resolve(__dirname, "src/client/"),
|
||||
config: path.resolve(__dirname, "src/config/"),
|
||||
components: path.resolve(__dirname, "src/components/"),
|
||||
layouts: path.resolve(__dirname, "src/layouts/"),
|
||||
pages: path.resolve(__dirname, "src/pages/"),
|
||||
screens: path.resolve(__dirname, "src/screens/"),
|
||||
shared: path.resolve(__dirname, "src/shared/"),
|
||||
|
||||
react: "preact-compat/dist/preact-compat",
|
||||
"react-dom": "preact-compat/dist/preact-compat",
|
||||
"create-react-class": "preact-compat/lib/create-react-class"
|
||||
}
|
||||
},
|
||||
react: "preact-compat/dist/preact-compat",
|
||||
"react-dom": "preact-compat/dist/preact-compat",
|
||||
"create-react-class": "preact-compat/lib/create-react-class"
|
||||
}
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?/i,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader"
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?/i,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader"
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.(less|css)$/,
|
||||
loader: "style-loader"
|
||||
},
|
||||
{
|
||||
test: /\.(less|css)$/,
|
||||
loader: "style-loader"
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.(less|css)$/,
|
||||
loader: "css-loader",
|
||||
query: {
|
||||
modules: true,
|
||||
localIdentName: "[name]__[local]___[hash:base64:5]"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(less|css)$/,
|
||||
loader: "css-loader",
|
||||
query: {
|
||||
modules: true,
|
||||
localIdentName: "[name]__[local]___[hash:base64:5]"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.(less|css)$/,
|
||||
loader: "less-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(less|css)$/,
|
||||
loader: "less-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: "vendor",
|
||||
filename: "static/vendor.[hash].js"
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
favicon: "src/public/favicon.svg",
|
||||
template: "src/index.html"
|
||||
})
|
||||
].concat(
|
||||
ENV === "production"
|
||||
? [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
output: {
|
||||
comments: false
|
||||
},
|
||||
exclude: [/bundle/],
|
||||
compress: {
|
||||
unsafe_comps: true,
|
||||
properties: true,
|
||||
keep_fargs: false,
|
||||
pure_getters: true,
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
warnings: false,
|
||||
screw_ie8: true,
|
||||
sequences: true,
|
||||
dead_code: true,
|
||||
drop_debugger: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
drop_console: true
|
||||
}
|
||||
})
|
||||
]
|
||||
: [
|
||||
new webpack.DefinePlugin({
|
||||
// drone server uses authorization cookies, but the client can
|
||||
// optionally source the authorization token from the environment.
|
||||
// this should be used for the test server only.
|
||||
"window.DRONE_TOKEN": JSON.stringify(process.env.DRONE_TOKEN),
|
||||
"window.DRONE_SERVER": JSON.stringify(process.env.DRONE_SERVER),
|
||||
plugins: [
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: "vendor",
|
||||
filename: "static/vendor.[hash].js"
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
favicon: "src/public/favicon.svg",
|
||||
template: "src/index.html"
|
||||
})
|
||||
].concat(
|
||||
ENV === "production"
|
||||
? [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
output: {
|
||||
comments: false
|
||||
},
|
||||
exclude: [/bundle/],
|
||||
compress: {
|
||||
unsafe_comps: true,
|
||||
properties: true,
|
||||
keep_fargs: false,
|
||||
pure_getters: true,
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
warnings: false,
|
||||
screw_ie8: true,
|
||||
sequences: true,
|
||||
dead_code: true,
|
||||
drop_debugger: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
drop_console: true
|
||||
}
|
||||
})
|
||||
]
|
||||
: [
|
||||
new webpack.DefinePlugin({
|
||||
// drone server uses authorization cookies, but the client can
|
||||
// optionally source the authorization token from the environment.
|
||||
// this should be used for the test server only.
|
||||
"window.DRONE_TOKEN": JSON.stringify(process.env.DRONE_TOKEN),
|
||||
"window.DRONE_SERVER": JSON.stringify(process.env.DRONE_SERVER),
|
||||
|
||||
// drone server provides the currently authenticated user in the
|
||||
// index.html file. For testing purposes we simulate this and provides
|
||||
// a dummy user object.
|
||||
"window.DRONE_USER": {
|
||||
login: JSON.stringify("octocat"),
|
||||
avatar_url: JSON.stringify(
|
||||
"https://avatars3.githubusercontent.com/u/583231"
|
||||
)
|
||||
}
|
||||
})
|
||||
]
|
||||
),
|
||||
// drone server provides the currently authenticated user in the
|
||||
// index.html file. For testing purposes we simulate this and provides
|
||||
// a dummy user object.
|
||||
"window.DRONE_USER": {
|
||||
login: JSON.stringify("octocat"),
|
||||
avatar_url: JSON.stringify(
|
||||
"https://avatars3.githubusercontent.com/u/583231"
|
||||
)
|
||||
}
|
||||
})
|
||||
]
|
||||
),
|
||||
|
||||
devServer: {
|
||||
port: process.env.PORT || 9999,
|
||||
devServer: {
|
||||
port: process.env.PORT || 9999,
|
||||
|
||||
// serve up any static files from src/
|
||||
contentBase: path.join(__dirname, "src"),
|
||||
// serve up any static files from src/
|
||||
contentBase: path.join(__dirname, "src"),
|
||||
|
||||
// enable gzip compression:
|
||||
compress: true,
|
||||
// enable gzip compression:
|
||||
compress: true,
|
||||
|
||||
// enable pushState() routing, as used by preact-router et al:
|
||||
historyApiFallback: true
|
||||
}
|
||||
// enable pushState() routing, as used by preact-router et al:
|
||||
historyApiFallback: true
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue