mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 20:01:02 +00:00
Ran npx prettier --write "**/*.js" "*.js"
This commit is contained in:
parent
a5733075d6
commit
12279686e8
85 changed files with 3428 additions and 3318 deletions
|
@ -1,38 +1,34 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"extends": [
|
extends: [
|
||||||
"standard",
|
"standard",
|
||||||
"plugin:jest/recommended",
|
"plugin:jest/recommended",
|
||||||
"plugin:react/recommended",
|
"plugin:react/recommended",
|
||||||
"prettier",
|
"prettier",
|
||||||
"prettier/react"
|
"prettier/react"
|
||||||
],
|
],
|
||||||
"plugins": [
|
plugins: ["react", "jest", "prettier"],
|
||||||
"react",
|
parser: "babel-eslint",
|
||||||
"jest",
|
parserOptions: {
|
||||||
"prettier"
|
ecmaVersion: 2016,
|
||||||
],
|
sourceType: "module",
|
||||||
"parser": "babel-eslint",
|
ecmaFeatures: {
|
||||||
"parserOptions": {
|
jsx: true
|
||||||
"ecmaVersion": 2016,
|
}
|
||||||
"sourceType": "module",
|
},
|
||||||
"ecmaFeatures": {
|
env: {
|
||||||
"jsx": true
|
es6: true,
|
||||||
}
|
browser: true,
|
||||||
},
|
node: true,
|
||||||
"env": {
|
"jest/globals": true
|
||||||
"es6": true,
|
},
|
||||||
"browser": true,
|
rules: {
|
||||||
"node": true,
|
"react/prop-types": 1,
|
||||||
"jest/globals": true
|
"prettier/prettier": [
|
||||||
},
|
"error",
|
||||||
"rules": {
|
{
|
||||||
"react/prop-types": 1,
|
trailingComma: "all",
|
||||||
"prettier/prettier": [
|
useTabs: true
|
||||||
"error",
|
}
|
||||||
{
|
]
|
||||||
"trailingComma": "all",
|
}
|
||||||
"useTabs": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export const drone = (client, Component) => {
|
export const drone = (client, Component) => {
|
||||||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
const component = class extends React.Component {
|
const component = class extends React.Component {
|
||||||
getChildContext() {
|
getChildContext() {
|
||||||
return {
|
return {
|
||||||
drone: client,
|
drone: client
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <Component {...this.state} {...this.props} />;
|
return <Component {...this.state} {...this.props} />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
component.childContextTypes = {
|
component.childContextTypes = {
|
||||||
drone: (props, propName) => {},
|
drone: (props, propName) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const inject = Component => {
|
export const inject = Component => {
|
||||||
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
const component = class extends React.Component {
|
const component = class extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
this.props.drone = this.context.drone;
|
this.props.drone = this.context.drone;
|
||||||
return <Component {...this.state} {...this.props} />;
|
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 sync = window.DRONE_SYNC;
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
follow: false,
|
follow: false,
|
||||||
language: "en-US",
|
language: "en-US",
|
||||||
|
|
||||||
user: {
|
user: {
|
||||||
data: user,
|
data: user,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
loaded: true,
|
loaded: true,
|
||||||
syncing: sync,
|
syncing: sync
|
||||||
},
|
},
|
||||||
|
|
||||||
feed: {
|
feed: {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
data: {},
|
data: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
repos: {
|
repos: {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
data: {},
|
data: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
secrets: {
|
secrets: {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
data: {},
|
data: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
registry: {
|
registry: {
|
||||||
error: undefined,
|
error: undefined,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
data: {},
|
data: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
builds: {
|
builds: {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
data: {},
|
data: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
logs: {
|
logs: {
|
||||||
follow: false,
|
follow: false,
|
||||||
loading: true,
|
loading: true,
|
||||||
error: false,
|
error: false,
|
||||||
data: {},
|
data: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
token: {
|
token: {
|
||||||
value: undefined,
|
value: undefined,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
loading: false,
|
loading: false
|
||||||
},
|
},
|
||||||
|
|
||||||
message: {
|
message: {
|
||||||
show: false,
|
show: false,
|
||||||
text: undefined,
|
text: undefined,
|
||||||
error: false,
|
error: false
|
||||||
},
|
},
|
||||||
|
|
||||||
location: {
|
location: {
|
||||||
protocol: window.location.protocol,
|
protocol: window.location.protocol,
|
||||||
host: window.location.host,
|
host: window.location.host
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const tree = new Baobab(state);
|
const tree = new Baobab(state);
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
window.tree = tree;
|
window.tree = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default tree;
|
export default tree;
|
||||||
|
|
|
@ -5,8 +5,8 @@ import { render } from "react-dom";
|
||||||
let root;
|
let root;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
let App = require("./screens/drone").default;
|
let App = require("./screens/drone").default;
|
||||||
root = render(<App />, document.body, root);
|
root = render(<App />, document.body, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -16,37 +16,37 @@ import { BrowserRouter, Route, Switch } from "react-router-dom";
|
||||||
import styles from "./drone.less";
|
import styles from "./drone.less";
|
||||||
|
|
||||||
if (module.hot) {
|
if (module.hot) {
|
||||||
require("preact/devtools");
|
require("preact/devtools");
|
||||||
}
|
}
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<div>
|
<div>
|
||||||
<Title />
|
<Title />
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/" exact={true} component={RedirectRoot} />
|
<Route path="/" exact={true} component={RedirectRoot} />
|
||||||
<Route path="/login/form" exact={true} component={LoginForm} />
|
<Route path="/login/form" exact={true} component={LoginForm} />
|
||||||
<Route path="/login/error" exact={true} component={LoginError} />
|
<Route path="/login/error" exact={true} component={LoginError} />
|
||||||
<Route path="/" exact={false} component={Layout} />
|
<Route path="/" exact={false} component={Layout} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tree.exists(["user", "data"])) {
|
if (tree.exists(["user", "data"])) {
|
||||||
fetchFeedOnce(tree, client);
|
fetchFeedOnce(tree, client);
|
||||||
subscribeToFeedOnce(tree, client);
|
subscribeToFeedOnce(tree, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
client.onerror = error => {
|
client.onerror = error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
if (error.status === 401) {
|
if (error.status === 401) {
|
||||||
tree.unset(["user", "data"]);
|
tree.unset(["user", "data"]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default root(tree, drone(client, App));
|
export default root(tree, drone(client, App));
|
||||||
|
|
|
@ -8,48 +8,48 @@ import styles from "./list.less";
|
||||||
import { StarIcon } from "shared/components/icons/index";
|
import { StarIcon } from "shared/components/icons/index";
|
||||||
|
|
||||||
export const List = ({ children }) => (
|
export const List = ({ children }) => (
|
||||||
<div className={styles.list}>{children}</div>
|
<div className={styles.list}>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export class Item extends Component {
|
export class Item extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.handleFave = this.handleFave.bind(this);
|
this.handleFave = this.handleFave.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFave(e) {
|
handleFave(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.onFave(this.props.item.full_name);
|
this.props.onFave(this.props.item.full_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { item, faved } = this.props;
|
const { item, faved } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.item}>
|
<div className={styles.item}>
|
||||||
<div onClick={this.handleFave}>
|
<div onClick={this.handleFave}>
|
||||||
<StarIcon filled={faved} size={16} className={styles.star} />
|
<StarIcon filled={faved} size={16} className={styles.star} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<div className={styles.title}>{item.full_name}</div>
|
<div className={styles.title}>{item.full_name}</div>
|
||||||
<div className={styles.icon}>
|
<div className={styles.icon}>
|
||||||
{item.status ? <Status status={item.status} /> : <noscript />}
|
{item.status ? <Status status={item.status} /> : <noscript />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.body}>
|
<div className={styles.body}>
|
||||||
<BuildTime
|
<BuildTime
|
||||||
start={item.started_at || item.created_at}
|
start={item.started_at || item.created_at}
|
||||||
finish={item.finished_at}
|
finish={item.finished_at}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.item !== nextProps.item || this.props.faved !== nextProps.faved
|
this.props.item !== nextProps.item || this.props.faved !== nextProps.faved
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,173 +14,169 @@ import style from "./index.less";
|
||||||
import Collapsible from "react-collapsible";
|
import Collapsible from "react-collapsible";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
return { feed: ["feed"] };
|
return { feed: ["feed"] };
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class Sidebar extends Component {
|
export default class Sidebar extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
starred: JSON.parse(localStorage.getItem("starred") || "[]"),
|
starred: JSON.parse(localStorage.getItem("starred") || "[]"),
|
||||||
starredOpen: (localStorage.getItem("starredOpen") || "true") === "true",
|
starredOpen: (localStorage.getItem("starredOpen") || "true") === "true",
|
||||||
reposOpen: (localStorage.getItem("reposOpen") || "true") === "true",
|
reposOpen: (localStorage.getItem("reposOpen") || "true") === "true"
|
||||||
});
|
});
|
||||||
|
|
||||||
this.handleFilter = this.handleFilter.bind(this);
|
this.handleFilter = this.handleFilter.bind(this);
|
||||||
this.toggleStarred = this.toggleItem.bind(this, "starredOpen");
|
this.toggleStarred = this.toggleItem.bind(this, "starredOpen");
|
||||||
this.toggleAll = this.toggleItem.bind(this, "reposOpen");
|
this.toggleAll = this.toggleItem.bind(this, "reposOpen");
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.feed !== nextProps.feed ||
|
this.props.feed !== nextProps.feed ||
|
||||||
this.state.filter !== nextState.filter ||
|
this.state.filter !== nextState.filter ||
|
||||||
this.state.starred.length !== nextState.starred.length
|
this.state.starred.length !== nextState.starred.length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFilter(e) {
|
handleFilter(e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
filter: e.target.value,
|
filter: e.target.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleItem = item => {
|
toggleItem = item => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return { [item]: !state[item] };
|
return { [item]: !state[item] };
|
||||||
});
|
});
|
||||||
|
|
||||||
localStorage.setItem(item, this.state[item]);
|
localStorage.setItem(item, this.state[item]);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderFeed = (list, renderStarred) => {
|
renderFeed = (list, renderStarred) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<List>{list.map(item => this.renderItem(item, renderStarred))}</List>
|
<List>{list.map(item => this.renderItem(item, renderStarred))}</List>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = (item, renderStarred) => {
|
renderItem = (item, renderStarred) => {
|
||||||
const starred = this.state.starred;
|
const starred = this.state.starred;
|
||||||
if (renderStarred && !starred.includes(item.full_name)) {
|
if (renderStarred && !starred.includes(item.full_name)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Link to={`/${item.full_name}`} key={item.full_name}>
|
<Link to={`/${item.full_name}`} key={item.full_name}>
|
||||||
<Item
|
<Item
|
||||||
item={item}
|
item={item}
|
||||||
onFave={this.onFave}
|
onFave={this.onFave}
|
||||||
faved={starred.includes(item.full_name)}
|
faved={starred.includes(item.full_name)}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onFave = fullName => {
|
onFave = fullName => {
|
||||||
if (!this.state.starred.includes(fullName)) {
|
if (!this.state.starred.includes(fullName)) {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
const list = state.starred.concat(fullName);
|
const list = state.starred.concat(fullName);
|
||||||
return { starred: list };
|
return { starred: list };
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
const list = state.starred.filter(v => v !== fullName);
|
const list = state.starred.filter(v => v !== fullName);
|
||||||
return { starred: list };
|
return { starred: list };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("starred", JSON.stringify(this.state.starred));
|
localStorage.setItem("starred", JSON.stringify(this.state.starred));
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { feed } = this.props;
|
const { feed } = this.props;
|
||||||
const { filter } = this.state;
|
const { filter } = this.state;
|
||||||
|
|
||||||
const list = feed.data ? Object.values(feed.data) : [];
|
const list = feed.data ? Object.values(feed.data) : [];
|
||||||
|
|
||||||
const filterFunc = item => {
|
const filterFunc = item => {
|
||||||
return !filter || item.full_name.indexOf(filter) !== -1;
|
return !filter || item.full_name.indexOf(filter) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const filtered = list.filter(filterFunc).sort(compareFeedItem);
|
const filtered = list.filter(filterFunc).sort(compareFeedItem);
|
||||||
const starredOpen = this.state.starredOpen;
|
const starredOpen = this.state.starredOpen;
|
||||||
const reposOpen = this.state.reposOpen;
|
const reposOpen = this.state.reposOpen;
|
||||||
return (
|
return (
|
||||||
<div className={style.feed}>
|
<div className={style.feed}>
|
||||||
{LOGO}
|
{LOGO}
|
||||||
<Collapsible
|
<Collapsible
|
||||||
trigger="Starred"
|
trigger="Starred"
|
||||||
triggerTagName="div"
|
triggerTagName="div"
|
||||||
transitionTime={200}
|
transitionTime={200}
|
||||||
open={starredOpen}
|
open={starredOpen}
|
||||||
onOpen={this.toggleStarred}
|
onOpen={this.toggleStarred}
|
||||||
onClose={this.toggleStarred}
|
onClose={this.toggleStarred}
|
||||||
triggerOpenedClassName={style.Collapsible__trigger}
|
triggerOpenedClassName={style.Collapsible__trigger}
|
||||||
triggerClassName={style.Collapsible__trigger}
|
triggerClassName={style.Collapsible__trigger}
|
||||||
>
|
>
|
||||||
{feed.loaded === false ? (
|
{feed.loaded === false
|
||||||
LOADING
|
? LOADING
|
||||||
) : feed.error ? (
|
: feed.error
|
||||||
ERROR
|
? ERROR
|
||||||
) : list.length === 0 ? (
|
: list.length === 0
|
||||||
EMPTY
|
? EMPTY
|
||||||
) : (
|
: this.renderFeed(list, true)}
|
||||||
this.renderFeed(list, true)
|
</Collapsible>
|
||||||
)}
|
<Collapsible
|
||||||
</Collapsible>
|
trigger="Repos"
|
||||||
<Collapsible
|
triggerTagName="div"
|
||||||
trigger="Repos"
|
transitionTime={200}
|
||||||
triggerTagName="div"
|
open={reposOpen}
|
||||||
transitionTime={200}
|
onOpen={this.toggleAll}
|
||||||
open={reposOpen}
|
onClose={this.toggleAll}
|
||||||
onOpen={this.toggleAll}
|
triggerOpenedClassName={style.Collapsible__trigger}
|
||||||
onClose={this.toggleAll}
|
triggerClassName={style.Collapsible__trigger}
|
||||||
triggerOpenedClassName={style.Collapsible__trigger}
|
>
|
||||||
triggerClassName={style.Collapsible__trigger}
|
<input
|
||||||
>
|
type="text"
|
||||||
<input
|
placeholder="Search …"
|
||||||
type="text"
|
onChange={this.handleFilter}
|
||||||
placeholder="Search …"
|
/>
|
||||||
onChange={this.handleFilter}
|
{feed.loaded === false
|
||||||
/>
|
? LOADING
|
||||||
{feed.loaded === false ? (
|
: feed.error
|
||||||
LOADING
|
? ERROR
|
||||||
) : feed.error ? (
|
: list.length === 0
|
||||||
ERROR
|
? EMPTY
|
||||||
) : list.length === 0 ? (
|
: filtered.length > 0
|
||||||
EMPTY
|
? this.renderFeed(filtered.sort(compareFeedItem), false)
|
||||||
) : filtered.length > 0 ? (
|
: NO_MATCHES}
|
||||||
this.renderFeed(filtered.sort(compareFeedItem), false)
|
</Collapsible>
|
||||||
) : (
|
</div>
|
||||||
NO_MATCHES
|
);
|
||||||
)}
|
}
|
||||||
</Collapsible>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOGO = (
|
const LOGO = (
|
||||||
<div className={style.brand}>
|
<div className={style.brand}>
|
||||||
<DroneIcon />
|
<DroneIcon />
|
||||||
<p>
|
<p>
|
||||||
Woodpecker<span style="margin-left: 4px;">{window.DRONE_VERSION}</span>
|
Woodpecker<span style="margin-left: 4px;">{window.DRONE_VERSION}</span>
|
||||||
<br />
|
<br />
|
||||||
<span>
|
<span>
|
||||||
<a
|
<a
|
||||||
href="https://woodpecker.laszlo.cloud"
|
href="https://woodpecker.laszlo.cloud"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const LOADING = <div className={style.message}>Loading</div>;
|
const LOADING = <div className={style.message}>Loading</div>;
|
||||||
|
@ -190,7 +186,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 NO_MATCHES = <div className={style.message}>No results found</div>;
|
||||||
|
|
||||||
const ERROR = (
|
const ERROR = (
|
||||||
<div className={style.message}>
|
<div className={style.message}>
|
||||||
Oops. It looks like there was a problem loading your feed
|
Oops. It looks like there was a problem loading your feed
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,198 +30,195 @@ import { Drawer, DOCK_RIGHT } from "shared/components/drawer/drawer";
|
||||||
import styles from "./layout.less";
|
import styles from "./layout.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
return {
|
return {
|
||||||
user: ["user"],
|
user: ["user"],
|
||||||
message: ["message"],
|
message: ["message"],
|
||||||
sidebar: ["sidebar"],
|
sidebar: ["sidebar"],
|
||||||
menu: ["menu"],
|
menu: ["menu"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapScreenSizeToProps = screenSize => {
|
const mapScreenSizeToProps = screenSize => {
|
||||||
return {
|
return {
|
||||||
isTablet: screenSize["small"],
|
isTablet: screenSize["small"],
|
||||||
isMobile: screenSize["mobile"],
|
isMobile: screenSize["mobile"],
|
||||||
isDesktop: screenSize["> small"],
|
isDesktop: screenSize["> small"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
@connectScreenSize(mapScreenSizeToProps)
|
@connectScreenSize(mapScreenSizeToProps)
|
||||||
export default class Default extends Component {
|
export default class Default extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.state = {
|
this.state = {
|
||||||
menu: false,
|
menu: false,
|
||||||
feed: false,
|
feed: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.openMenu = this.openMenu.bind(this);
|
this.openMenu = this.openMenu.bind(this);
|
||||||
this.closeMenu = this.closeMenu.bind(this);
|
this.closeMenu = this.closeMenu.bind(this);
|
||||||
this.closeSnackbar = this.closeSnackbar.bind(this);
|
this.closeSnackbar = this.closeSnackbar.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.location !== this.props.location) {
|
if (nextProps.location !== this.props.location) {
|
||||||
this.closeMenu(true);
|
this.closeMenu(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openMenu() {
|
openMenu() {
|
||||||
this.props.dispatch(tree => {
|
this.props.dispatch(tree => {
|
||||||
tree.set(["menu"], true);
|
tree.set(["menu"], true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
closeMenu() {
|
closeMenu() {
|
||||||
this.props.dispatch(tree => {
|
this.props.dispatch(tree => {
|
||||||
tree.set(["menu"], false);
|
tree.set(["menu"], false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { user, message, menu } = this.props;
|
const { user, message, menu } = this.props;
|
||||||
|
|
||||||
const classes = classnames(!user || !user.data ? styles.guest : null);
|
const classes = classnames(!user || !user.data ? styles.guest : null);
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path={"/"} component={Feed} />
|
<Route path={"/"} component={Feed} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.center}>
|
<div className={styles.center}>
|
||||||
{!user || !user.data ? (
|
{!user || !user.data ? (
|
||||||
<a
|
<a
|
||||||
href={"/login?url=" + window.location.href}
|
href={"/login?url=" + window.location.href}
|
||||||
target="_self"
|
target="_self"
|
||||||
className={styles.login}
|
className={styles.login}
|
||||||
>
|
>
|
||||||
Click to Login
|
Click to Login
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<noscript />
|
<noscript />
|
||||||
)}
|
)}
|
||||||
<div className={styles.title}>
|
<div className={styles.title}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/account/repos" component={UserRepoTitle} />
|
<Route path="/account/repos" component={UserRepoTitle} />
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={BuildLogsTitle}
|
component={BuildLogsTitle}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/:build(\d*)"
|
path="/:owner/:repo/:build(\d*)"
|
||||||
component={BuildLogsTitle}
|
component={BuildLogsTitle}
|
||||||
/>
|
/>
|
||||||
<Route path="/:owner/:repo" component={RepoHeader} />
|
<Route path="/:owner/:repo" component={RepoHeader} />
|
||||||
</Switch>
|
</Switch>
|
||||||
{user && user.data ? (
|
{user && user.data ? (
|
||||||
<div className={styles.avatar}>
|
<div className={styles.avatar}>
|
||||||
<img src={user.data.avatar_url} />
|
<img src={user.data.avatar_url} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
undefined
|
undefined
|
||||||
)}
|
)}
|
||||||
{user && user.data ? (
|
{user && user.data ? (
|
||||||
<button onClick={this.openMenu}>
|
<button onClick={this.openMenu}>
|
||||||
<MenuIcon />
|
<MenuIcon />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<noscript />
|
<noscript />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.menu}>
|
<div className={styles.menu}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Route
|
||||||
path="/account/repos"
|
path="/account/repos"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={UserReposMenu}
|
component={UserReposMenu}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route path="/account/" exact={false} component={undefined} />
|
||||||
path="/account/"
|
BuildMenu
|
||||||
exact={false}
|
<Route
|
||||||
component={undefined}
|
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||||
/>BuildMenu
|
exact={true}
|
||||||
<Route
|
component={BuildMenu}
|
||||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
/>
|
||||||
exact={true}
|
<Route
|
||||||
component={BuildMenu}
|
path="/:owner/:repo/:build(\d*)"
|
||||||
/>
|
exact={true}
|
||||||
<Route
|
component={BuildMenu}
|
||||||
path="/:owner/:repo/:build(\d*)"
|
/>
|
||||||
exact={true}
|
<Route path="/:owner/:repo" exact={false} component={RepoMenu} />
|
||||||
component={BuildMenu}
|
</Switch>
|
||||||
/>
|
</div>
|
||||||
<Route path="/:owner/:repo" exact={false} component={RepoMenu} />
|
|
||||||
</Switch>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/account/token" exact={true} component={UserTokens} />
|
<Route path="/account/token" exact={true} component={UserTokens} />
|
||||||
<Route path="/account/repos" exact={true} component={UserRepos} />
|
<Route path="/account/repos" exact={true} component={UserRepos} />
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/settings/secrets"
|
path="/:owner/:repo/settings/secrets"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={RepoSecrets}
|
component={RepoSecrets}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/settings/registry"
|
path="/:owner/:repo/settings/registry"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={RepoRegistry}
|
component={RepoRegistry}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/settings"
|
path="/:owner/:repo/settings"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={RepoSettings}
|
component={RepoSettings}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/:build(\d*)"
|
path="/:owner/:repo/:build(\d*)"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={BuildLogs}
|
component={BuildLogs}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
path="/:owner/:repo/:build(\d*)/:proc(\d*)"
|
||||||
exact={true}
|
exact={true}
|
||||||
component={BuildLogs}
|
component={BuildLogs}
|
||||||
/>
|
/>
|
||||||
<Route path="/:owner/:repo" exact={true} component={RepoBuilds} />
|
<Route path="/:owner/:repo" exact={true} component={RepoBuilds} />
|
||||||
<Route path="/" exact={true} component={RedirectRoot} />
|
<Route path="/" exact={true} component={RedirectRoot} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Snackbar message={message.text} onClose={this.closeSnackbar} />
|
<Snackbar message={message.text} onClose={this.closeSnackbar} />
|
||||||
|
|
||||||
<Drawer onClick={this.closeMenu} position={DOCK_RIGHT} open={menu}>
|
<Drawer onClick={this.closeMenu} position={DOCK_RIGHT} open={menu}>
|
||||||
<section>
|
<section>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<Link to="/account/repos">Repositories</Link>
|
<Link to="/account/repos">Repositories</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link to="/account/token">Token</Link>
|
<Link to="/account/token">Token</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="/logout" target="_self">
|
<a href="/logout" target="_self">
|
||||||
Logout
|
Logout
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeSnackbar() {
|
closeSnackbar() {
|
||||||
this.props.dispatch(tree => {
|
this.props.dispatch(tree => {
|
||||||
tree.unset(["message", "text"]);
|
tree.unset(["message", "text"]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,28 +7,28 @@ import styles from "./index.less";
|
||||||
const DEFAULT_ERROR = "The system failed to process your Login request.";
|
const DEFAULT_ERROR = "The system failed to process your Login request.";
|
||||||
|
|
||||||
class Error extends Component {
|
class Error extends Component {
|
||||||
render() {
|
render() {
|
||||||
const parsed = queryString.parse(window.location.search);
|
const parsed = queryString.parse(window.location.search);
|
||||||
let error = DEFAULT_ERROR;
|
let error = DEFAULT_ERROR;
|
||||||
|
|
||||||
switch (parsed.code || parsed.error) {
|
switch (parsed.code || parsed.error) {
|
||||||
case "oauth_error":
|
case "oauth_error":
|
||||||
break;
|
break;
|
||||||
case "access_denied":
|
case "access_denied":
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<div className={styles.alert}>
|
<div className={styles.alert}>
|
||||||
<div>
|
<div>
|
||||||
<Icon />
|
<Icon />
|
||||||
</div>
|
</div>
|
||||||
<div>{error}</div>
|
<div>{error}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Error;
|
export default Error;
|
||||||
|
|
|
@ -3,19 +3,19 @@ import React from "react";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const LoginForm = props => (
|
const LoginForm = props => (
|
||||||
<div className={styles.login}>
|
<div className={styles.login}>
|
||||||
<form method="post" action="/authorize">
|
<form method="post" action="/authorize">
|
||||||
<p>Login with your version control system username and password.</p>
|
<p>Login with your version control system username and password.</p>
|
||||||
<input
|
<input
|
||||||
placeholder="Username"
|
placeholder="Username"
|
||||||
name="username"
|
name="username"
|
||||||
type="text"
|
type="text"
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
/>
|
/>
|
||||||
<input placeholder="Password" name="password" type="password" />
|
<input placeholder="Password" name="password" type="password" />
|
||||||
<input value="Login" type="submit" />
|
<input value="Login" type="submit" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default LoginForm;
|
export default LoginForm;
|
||||||
|
|
|
@ -4,38 +4,38 @@ import { branch } from "baobab-react/higher-order";
|
||||||
import { Message } from "shared/components/sync";
|
import { Message } from "shared/components/sync";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
return {
|
return {
|
||||||
feed: ["feed"],
|
feed: ["feed"],
|
||||||
user: ["user", "data"],
|
user: ["user", "data"],
|
||||||
syncing: ["user", "syncing"],
|
syncing: ["user", "syncing"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class RedirectRoot extends Component {
|
export default class RedirectRoot extends Component {
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { user } = nextProps;
|
const { user } = nextProps;
|
||||||
if (!user && window) {
|
if (!user && window) {
|
||||||
window.location.href = "/login?url=" + window.location.href;
|
window.location.href = "/login?url=" + window.location.href;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { user, syncing } = this.props;
|
const { user, syncing } = this.props;
|
||||||
const { latest, loaded } = this.props.feed;
|
const { latest, loaded } = this.props.feed;
|
||||||
|
|
||||||
return !loaded && syncing ? (
|
return !loaded && syncing ? (
|
||||||
<Message />
|
<Message />
|
||||||
) : !loaded ? (
|
) : !loaded ? (
|
||||||
undefined
|
undefined
|
||||||
) : !user ? (
|
) : !user ? (
|
||||||
undefined
|
undefined
|
||||||
) : !latest ? (
|
) : !latest ? (
|
||||||
<Redirect to="/account/repos" />
|
<Redirect to="/account/repos" />
|
||||||
) : !latest.number ? (
|
) : !latest.number ? (
|
||||||
<Redirect to={`/${latest.full_name}`} />
|
<Redirect to={`/${latest.full_name}`} />
|
||||||
) : (
|
) : (
|
||||||
<Redirect to={`/${latest.full_name}/${latest.number}`} />
|
<Redirect to={`/${latest.full_name}/${latest.number}`} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ import React from "react";
|
||||||
import style from "./approval.less";
|
import style from "./approval.less";
|
||||||
|
|
||||||
export const Approval = ({ onapprove, ondecline }) => (
|
export const Approval = ({ onapprove, ondecline }) => (
|
||||||
<div className={style.root}>
|
<div className={style.root}>
|
||||||
<p>Pipeline execution is blocked pending administrator approval</p>
|
<p>Pipeline execution is blocked pending administrator approval</p>
|
||||||
<button onClick={onapprove}>Approve</button>
|
<button onClick={onapprove}>Approve</button>
|
||||||
<button onClick={ondecline}>Decline</button>
|
<button onClick={ondecline}>Decline</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,36 +7,36 @@ import { StatusLabel } from "shared/components/status";
|
||||||
import styles from "./details.less";
|
import styles from "./details.less";
|
||||||
|
|
||||||
export class Details extends Component {
|
export class Details extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { build } = this.props;
|
const { build } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
<StatusLabel status={build.status} />
|
<StatusLabel status={build.status} />
|
||||||
|
|
||||||
<section className={styles.message} style={{ whiteSpace: "pre-line" }}>
|
<section className={styles.message} style={{ whiteSpace: "pre-line" }}>
|
||||||
{build.message}
|
{build.message}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<BuildTime
|
<BuildTime
|
||||||
start={build.started_at || build.created_at}
|
start={build.started_at || build.created_at}
|
||||||
finish={build.finished_at}
|
finish={build.finished_at}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<BuildMeta
|
<BuildMeta
|
||||||
link={build.link_url}
|
link={build.link_url}
|
||||||
event={build.event}
|
event={build.event}
|
||||||
commit={build.commit}
|
commit={build.commit}
|
||||||
branch={build.branch}
|
branch={build.branch}
|
||||||
target={build.deploy_to}
|
target={build.deploy_to}
|
||||||
refspec={build.refspec}
|
refspec={build.refspec}
|
||||||
refs={build.ref}
|
refs={build.ref}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,46 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export class Elapsed extends Component {
|
export class Elapsed extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
elapsed: 0,
|
elapsed: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this.tick = this.tick.bind(this);
|
this.tick = this.tick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.timer = setInterval(this.tick, 1000);
|
this.timer = setInterval(this.tick, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
tick() {
|
tick() {
|
||||||
const { start } = this.props;
|
const { start } = this.props;
|
||||||
const stop = ~~(Date.now() / 1000);
|
const stop = ~~(Date.now() / 1000);
|
||||||
this.setState({
|
this.setState({
|
||||||
elapsed: stop - start,
|
elapsed: stop - start
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { elapsed } = this.state;
|
const { elapsed } = this.state;
|
||||||
const date = new Date(null);
|
const date = new Date(null);
|
||||||
date.setSeconds(elapsed);
|
date.setSeconds(elapsed);
|
||||||
return (
|
return (
|
||||||
<time>
|
<time>
|
||||||
{!elapsed ? (
|
{!elapsed
|
||||||
undefined
|
? undefined
|
||||||
) : elapsed > 3600 ? (
|
: elapsed > 3600
|
||||||
date.toISOString().substr(11, 8)
|
? date.toISOString().substr(11, 8)
|
||||||
) : (
|
: date.toISOString().substr(14, 5)}
|
||||||
date.toISOString().substr(14, 5)
|
</time>
|
||||||
)}
|
);
|
||||||
</time>
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -53,11 +51,11 @@ export class Elapsed extends Component {
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
export const formatTime = (end, start) => {
|
export const formatTime = (end, start) => {
|
||||||
const diff = end - start;
|
const diff = end - start;
|
||||||
const date = new Date(null);
|
const date = new Date(null);
|
||||||
date.setSeconds(diff);
|
date.setSeconds(diff);
|
||||||
|
|
||||||
return diff > 3600
|
return diff > 3600
|
||||||
? date.toISOString().substr(11, 8)
|
? date.toISOString().substr(11, 8)
|
||||||
: date.toISOString().substr(14, 5);
|
: date.toISOString().substr(14, 5);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,69 +8,69 @@ import { default as Status, StatusText } from "shared/components/status";
|
||||||
import styles from "./procs.less";
|
import styles from "./procs.less";
|
||||||
|
|
||||||
const renderEnviron = data => {
|
const renderEnviron = data => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{data[0]}={data[1]}
|
{data[0]}={data[1]}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProcListHolder = ({ vars, renderName, children }) => (
|
const ProcListHolder = ({ vars, renderName, children }) => (
|
||||||
<div className={styles.list}>
|
<div className={styles.list}>
|
||||||
{renderName && vars.name !== "drone" ? (
|
{renderName && vars.name !== "drone" ? (
|
||||||
<div>
|
<div>
|
||||||
<StatusText status={vars.state} text={vars.name} />
|
<StatusText status={vars.state} text={vars.name} />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{vars.environ ? (
|
{vars.environ ? (
|
||||||
<div>
|
<div>
|
||||||
<StatusText
|
<StatusText
|
||||||
status={vars.state}
|
status={vars.state}
|
||||||
text={Object.entries(vars.environ).map(renderEnviron)}
|
text={Object.entries(vars.environ).map(renderEnviron)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export class ProcList extends Component {
|
export class ProcList extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { repo, build, rootProc, selectedProc, renderName } = this.props;
|
const { repo, build, rootProc, selectedProc, renderName } = this.props;
|
||||||
return (
|
return (
|
||||||
<ProcListHolder vars={rootProc} renderName={renderName}>
|
<ProcListHolder vars={rootProc} renderName={renderName}>
|
||||||
{this.props.rootProc.children.map(function(child) {
|
{this.props.rootProc.children.map(function(child) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
to={`/${repo.full_name}/${build.number}/${child.pid}`}
|
to={`/${repo.full_name}/${build.number}/${child.pid}`}
|
||||||
key={`${repo.full_name}-${build.number}-${child.pid}`}
|
key={`${repo.full_name}-${build.number}-${child.pid}`}
|
||||||
>
|
>
|
||||||
<ProcListItem
|
<ProcListItem
|
||||||
key={child.pid}
|
key={child.pid}
|
||||||
name={child.name}
|
name={child.name}
|
||||||
start={child.start_time}
|
start={child.start_time}
|
||||||
finish={child.end_time}
|
finish={child.end_time}
|
||||||
state={child.state}
|
state={child.state}
|
||||||
selected={child.pid === selectedProc.pid}
|
selected={child.pid === selectedProc.pid}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ProcListHolder>
|
</ProcListHolder>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProcListItem = ({ name, start, finish, state, selected }) => (
|
export const ProcListItem = ({ name, start, finish, state, selected }) => (
|
||||||
<div className={classnames(styles.item, selected ? styles.selected : null)}>
|
<div className={classnames(styles.item, selected ? styles.selected : null)}>
|
||||||
<h3>{name}</h3>
|
<h3>{name}</h3>
|
||||||
{finish ? (
|
{finish ? (
|
||||||
<time>{formatTime(finish, start)}</time>
|
<time>{formatTime(finish, start)}</time>
|
||||||
) : (
|
) : (
|
||||||
<Elapsed start={start} />
|
<Elapsed start={start} />
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<Status status={state} />
|
<Status status={state} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { Link } from "react-router-dom";
|
||||||
|
|
||||||
import { fetchBuild, approveBuild, declineBuild } from "shared/utils/build";
|
import { fetchBuild, approveBuild, declineBuild } from "shared/utils/build";
|
||||||
import {
|
import {
|
||||||
STATUS_BLOCKED,
|
STATUS_BLOCKED,
|
||||||
STATUS_DECLINED,
|
STATUS_DECLINED,
|
||||||
STATUS_ERROR,
|
STATUS_ERROR
|
||||||
} from "shared/constants/status";
|
} from "shared/constants/status";
|
||||||
|
|
||||||
import { findChildProcess } from "shared/utils/proc";
|
import { findChildProcess } from "shared/utils/proc";
|
||||||
|
@ -23,235 +23,233 @@ import Output from "./logs";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo, build } = props.match.params;
|
const { owner, repo, build } = props.match.params;
|
||||||
const slug = `${owner}/${repo}`;
|
const slug = `${owner}/${repo}`;
|
||||||
const number = parseInt(build);
|
const number = parseInt(build);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
repo: ["repos", "data", slug],
|
repo: ["repos", "data", slug],
|
||||||
build: ["builds", "data", slug, number],
|
build: ["builds", "data", slug, number]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class BuildLogs extends Component {
|
export default class BuildLogs extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleApprove = this.handleApprove.bind(this);
|
this.handleApprove = this.handleApprove.bind(this);
|
||||||
this.handleDecline = this.handleDecline.bind(this);
|
this.handleDecline = this.handleDecline.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.synchronize(this.props);
|
this.synchronize(this.props);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleApprove() {
|
handleApprove() {
|
||||||
const { repo, build, drone } = this.props;
|
const { repo, build, drone } = this.props;
|
||||||
this.props.dispatch(
|
this.props.dispatch(
|
||||||
approveBuild,
|
approveBuild,
|
||||||
drone,
|
drone,
|
||||||
repo.owner,
|
repo.owner,
|
||||||
repo.name,
|
repo.name,
|
||||||
build.number,
|
build.number
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDecline() {
|
handleDecline() {
|
||||||
const { repo, build, drone } = this.props;
|
const { repo, build, drone } = this.props;
|
||||||
this.props.dispatch(
|
this.props.dispatch(
|
||||||
declineBuild,
|
declineBuild,
|
||||||
drone,
|
drone,
|
||||||
repo.owner,
|
repo.owner,
|
||||||
repo.name,
|
repo.name,
|
||||||
build.number,
|
build.number
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUpdate(nextProps) {
|
componentWillUpdate(nextProps) {
|
||||||
if (this.props.match.url !== nextProps.match.url) {
|
if (this.props.match.url !== nextProps.match.url) {
|
||||||
this.synchronize(nextProps);
|
this.synchronize(nextProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronize(props) {
|
synchronize(props) {
|
||||||
if (!props.repo) {
|
if (!props.repo) {
|
||||||
this.props.dispatch(
|
this.props.dispatch(
|
||||||
fetchRepository,
|
fetchRepository,
|
||||||
props.drone,
|
props.drone,
|
||||||
props.match.params.owner,
|
props.match.params.owner,
|
||||||
props.match.params.repo,
|
props.match.params.repo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!props.build || !props.build.procs) {
|
if (!props.build || !props.build.procs) {
|
||||||
this.props.dispatch(
|
this.props.dispatch(
|
||||||
fetchBuild,
|
fetchBuild,
|
||||||
props.drone,
|
props.drone,
|
||||||
props.match.params.owner,
|
props.match.params.owner,
|
||||||
props.match.params.repo,
|
props.match.params.repo,
|
||||||
props.match.params.build,
|
props.match.params.build
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return this.props !== nextProps;
|
return this.props !== nextProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { repo, build } = this.props;
|
const { repo, build } = this.props;
|
||||||
|
|
||||||
if (!build || !repo) {
|
if (!build || !repo) {
|
||||||
return this.renderLoading();
|
return this.renderLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (build.status === STATUS_DECLINED || build.status === STATUS_ERROR) {
|
if (build.status === STATUS_DECLINED || build.status === STATUS_ERROR) {
|
||||||
return this.renderError();
|
return this.renderError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (build.status === STATUS_BLOCKED) {
|
if (build.status === STATUS_BLOCKED) {
|
||||||
return this.renderBlocked();
|
return this.renderBlocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!build.procs) {
|
if (!build.procs) {
|
||||||
return this.renderLoading();
|
return this.renderLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.renderSimple();
|
return this.renderSimple();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLoading() {
|
renderLoading() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.host}>
|
<div className={styles.host}>
|
||||||
<div className={styles.columns}>
|
<div className={styles.columns}>
|
||||||
<div className={styles.right}>Loading ...</div>
|
<div className={styles.right}>Loading ...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBlocked() {
|
renderBlocked() {
|
||||||
const { build } = this.props;
|
const { build } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.host}>
|
<div className={styles.host}>
|
||||||
<div className={styles.columns}>
|
<div className={styles.columns}>
|
||||||
<div className={styles.right}>
|
<div className={styles.right}>
|
||||||
<Details build={build} />
|
<Details build={build} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
<Approval
|
<Approval
|
||||||
onapprove={this.handleApprove}
|
onapprove={this.handleApprove}
|
||||||
ondecline={this.handleDecline}
|
ondecline={this.handleDecline}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError() {
|
renderError() {
|
||||||
const { build } = this.props;
|
const { build } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.host}>
|
<div className={styles.host}>
|
||||||
<div className={styles.columns}>
|
<div className={styles.columns}>
|
||||||
<div className={styles.right}>
|
<div className={styles.right}>
|
||||||
<Details build={build} />
|
<Details build={build} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
<div className={styles.logerror}>
|
<div className={styles.logerror}>
|
||||||
{build.status === STATUS_ERROR ? (
|
{build.status === STATUS_ERROR
|
||||||
build.error
|
? build.error
|
||||||
) : (
|
: "Pipeline execution was declined"}
|
||||||
"Pipeline execution was declined"
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
</div>
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
highlightedLine() {
|
highlightedLine() {
|
||||||
if (location.hash.startsWith("#L")) {
|
if (location.hash.startsWith("#L")) {
|
||||||
return parseInt(location.hash.substr(2)) - 1;
|
return parseInt(location.hash.substr(2)) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSimple() {
|
renderSimple() {
|
||||||
// if (nextProps.build.procs[0].children !== undefined){
|
// if (nextProps.build.procs[0].children !== undefined){
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const { repo, build, match } = this.props;
|
const { repo, build, match } = this.props;
|
||||||
const selectedProc = match.params.proc
|
const selectedProc = match.params.proc
|
||||||
? findChildProcess(build.procs, match.params.proc)
|
? findChildProcess(build.procs, match.params.proc)
|
||||||
: build.procs[0].children[0];
|
: build.procs[0].children[0];
|
||||||
const selectedProcParent = findChildProcess(build.procs, selectedProc.ppid);
|
const selectedProcParent = findChildProcess(build.procs, selectedProc.ppid);
|
||||||
const highlighted = this.highlightedLine();
|
const highlighted = this.highlightedLine();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.host}>
|
<div className={styles.host}>
|
||||||
<div className={styles.columns}>
|
<div className={styles.columns}>
|
||||||
<div className={styles.right}>
|
<div className={styles.right}>
|
||||||
<Details build={build} />
|
<Details build={build} />
|
||||||
<section className={styles.sticky}>
|
<section className={styles.sticky}>
|
||||||
{build.procs.map(function(rootProc) {
|
{build.procs.map(function(rootProc) {
|
||||||
return (
|
return (
|
||||||
<div style="padding-bottom: 50px;" key={rootProc.pid}>
|
<div style="padding-bottom: 50px;" key={rootProc.pid}>
|
||||||
<ProcList
|
<ProcList
|
||||||
key={rootProc.pid}
|
key={rootProc.pid}
|
||||||
repo={repo}
|
repo={repo}
|
||||||
build={build}
|
build={build}
|
||||||
rootProc={rootProc}
|
rootProc={rootProc}
|
||||||
selectedProc={selectedProc}
|
selectedProc={selectedProc}
|
||||||
renderName={build.procs.length > 1}
|
renderName={build.procs.length > 1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
{selectedProc && selectedProc.error ? (
|
{selectedProc && selectedProc.error ? (
|
||||||
<div className={styles.logerror}>{selectedProc.error}</div>
|
<div className={styles.logerror}>{selectedProc.error}</div>
|
||||||
) : null}
|
) : null}
|
||||||
{selectedProcParent && selectedProcParent.error ? (
|
{selectedProcParent && selectedProcParent.error ? (
|
||||||
<div className={styles.logerror}>{selectedProcParent.error}</div>
|
<div className={styles.logerror}>{selectedProcParent.error}</div>
|
||||||
) : null}
|
) : null}
|
||||||
<Output
|
<Output
|
||||||
match={this.props.match}
|
match={this.props.match}
|
||||||
build={this.props.build}
|
build={this.props.build}
|
||||||
proc={selectedProc}
|
proc={selectedProc}
|
||||||
highlighted={highlighted}
|
highlighted={highlighted}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BuildLogsTitle extends Component {
|
export class BuildLogsTitle extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { owner, repo, build } = this.props.match.params;
|
const { owner, repo, build } = this.props.match.params;
|
||||||
return (
|
return (
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
elements={[
|
elements={[
|
||||||
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
||||||
{owner} / {repo}
|
{owner} / {repo}
|
||||||
</Link>,
|
</Link>,
|
||||||
SEPARATOR,
|
SEPARATOR,
|
||||||
<Link
|
<Link
|
||||||
to={`/${owner}/${repo}/${build}`}
|
to={`/${owner}/${repo}/${build}`}
|
||||||
key={`${owner}-${repo}-${build}`}
|
key={`${owner}-${repo}-${build}`}
|
||||||
>
|
>
|
||||||
{build}
|
{build}
|
||||||
</Link>,
|
</Link>
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ export const Top = () => <div className={styles.top} />;
|
||||||
export const Bottom = () => <div className={styles.bottom} />;
|
export const Bottom = () => <div className={styles.bottom} />;
|
||||||
|
|
||||||
export const scrollToTop = () => {
|
export const scrollToTop = () => {
|
||||||
document.querySelector(`.${styles.top}`).scrollIntoView();
|
document.querySelector(`.${styles.top}`).scrollIntoView();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scrollToBottom = () => {
|
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;
|
formatter.use_classes = true;
|
||||||
|
|
||||||
class Term extends Component {
|
class Term extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { lines, exitcode, highlighted } = this.props;
|
const { lines, exitcode, highlighted } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={style.term}>
|
<div className={style.term}>
|
||||||
{lines.map(line => renderTermLine(line, highlighted))}
|
{lines.map(line => renderTermLine(line, highlighted))}
|
||||||
{exitcode !== undefined ? renderExitCode(exitcode) : undefined}
|
{exitcode !== undefined ? renderExitCode(exitcode) : undefined}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.lines !== nextProps.lines ||
|
this.props.lines !== nextProps.lines ||
|
||||||
this.props.exitcode !== nextProps.exitcode ||
|
this.props.exitcode !== nextProps.exitcode ||
|
||||||
this.props.highlighted !== nextProps.highlighted
|
this.props.highlighted !== nextProps.highlighted
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TermLine extends Component {
|
class TermLine extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { line, highlighted } = this.props;
|
const { line, highlighted } = this.props;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={highlighted === line.pos ? style.highlight : style.line}
|
className={highlighted === line.pos ? style.highlight : style.line}
|
||||||
key={line.pos}
|
key={line.pos}
|
||||||
ref={highlighted === line.pos ? ref => (this.ref = ref) : null}
|
ref={highlighted === line.pos ? ref => (this.ref = ref) : null}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Link to={`#L${line.pos + 1}`} key={line.pos + 1}>
|
<Link to={`#L${line.pos + 1}`} key={line.pos + 1}>
|
||||||
{line.pos + 1}
|
{line.pos + 1}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div dangerouslySetInnerHTML={{ __html: this.colored }} />
|
<div dangerouslySetInnerHTML={{ __html: this.colored }} />
|
||||||
<div>{line.time || 0}s</div>
|
<div>{line.time || 0}s</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.ref !== undefined) {
|
if (this.ref !== undefined) {
|
||||||
scrollToRef(this.ref);
|
scrollToRef(this.ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get colored() {
|
get colored() {
|
||||||
return formatter.ansi_to_html(this.props.line.out || "");
|
return formatter.ansi_to_html(this.props.line.out || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.line.out !== nextProps.line.out ||
|
this.props.line.out !== nextProps.line.out ||
|
||||||
this.props.highlighted !== nextProps.highlighted
|
this.props.highlighted !== nextProps.highlighted
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderTermLine = (line, highlighted) => {
|
const renderTermLine = (line, highlighted) => {
|
||||||
return <TermLine line={line} highlighted={highlighted} />;
|
return <TermLine line={line} highlighted={highlighted} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderExitCode = code => {
|
const renderExitCode = code => {
|
||||||
return <div className={style.exitcode}>exit code {code}</div>;
|
return <div className={style.exitcode}>exit code {code}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TermError = () => {
|
const TermError = () => {
|
||||||
return (
|
return (
|
||||||
<div className={style.error}>
|
<div className={style.error}>
|
||||||
Oops. There was a problem loading the logs.
|
Oops. There was a problem loading the logs.
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TermLoading = () => {
|
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);
|
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";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo, build } = props.match.params;
|
const { owner, repo, build } = props.match.params;
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
const number = parseInt(build);
|
const number = parseInt(build);
|
||||||
const pid = parseInt(props.proc.pid);
|
const pid = parseInt(props.proc.pid);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
logs: ["logs", "data", slug, number, pid, "data"],
|
logs: ["logs", "data", slug, number, pid, "data"],
|
||||||
eof: ["logs", "data", slug, number, pid, "eof"],
|
eof: ["logs", "data", slug, number, pid, "eof"],
|
||||||
loading: ["logs", "data", slug, number, pid, "loading"],
|
loading: ["logs", "data", slug, number, pid, "loading"],
|
||||||
error: ["logs", "data", slug, number, pid, "error"],
|
error: ["logs", "data", slug, number, pid, "error"],
|
||||||
follow: ["logs", "follow"],
|
follow: ["logs", "follow"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class Output extends Component {
|
export default class Output extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.handleFollow = this.handleFollow.bind(this);
|
this.handleFollow = this.handleFollow.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
if (this.props.proc) {
|
if (this.props.proc) {
|
||||||
this.componentWillUpdate(this.props);
|
this.componentWillUpdate(this.props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUpdate(nextProps) {
|
componentWillUpdate(nextProps) {
|
||||||
const { loading, logs, eof, error } = nextProps;
|
const { loading, logs, eof, error } = nextProps;
|
||||||
const routeChange = this.props.match.url !== nextProps.match.url;
|
const routeChange = this.props.match.url !== nextProps.match.url;
|
||||||
|
|
||||||
if (loading || error || (logs && eof)) {
|
if (loading || error || (logs && eof)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assertProcFinished(nextProps.proc)) {
|
if (assertProcFinished(nextProps.proc)) {
|
||||||
return this.props.dispatch(
|
return this.props.dispatch(
|
||||||
fetchLogs,
|
fetchLogs,
|
||||||
nextProps.drone,
|
nextProps.drone,
|
||||||
nextProps.match.params.owner,
|
nextProps.match.params.owner,
|
||||||
nextProps.match.params.repo,
|
nextProps.match.params.repo,
|
||||||
nextProps.build.number,
|
nextProps.build.number,
|
||||||
nextProps.proc.pid,
|
nextProps.proc.pid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assertProcRunning(nextProps.proc) && (!logs || routeChange)) {
|
if (assertProcRunning(nextProps.proc) && (!logs || routeChange)) {
|
||||||
this.props.dispatch(
|
this.props.dispatch(
|
||||||
subscribeToLogs,
|
subscribeToLogs,
|
||||||
nextProps.drone,
|
nextProps.drone,
|
||||||
nextProps.match.params.owner,
|
nextProps.match.params.owner,
|
||||||
nextProps.match.params.repo,
|
nextProps.match.params.repo,
|
||||||
nextProps.build.number,
|
nextProps.build.number,
|
||||||
nextProps.proc,
|
nextProps.proc
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
if (this.props.follow) {
|
if (this.props.follow) {
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFollow() {
|
handleFollow() {
|
||||||
this.props.dispatch(toggleLogs, !this.props.follow);
|
this.props.dispatch(toggleLogs, !this.props.follow);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { logs, error, proc, loading, follow, highlighted } = this.props;
|
const { logs, error, proc, loading, follow, highlighted } = this.props;
|
||||||
|
|
||||||
if (loading || !proc) {
|
if (loading || !proc) {
|
||||||
return <Term.Loading />;
|
return <Term.Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <Term.Error />;
|
return <Term.Error />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Top />
|
<Top />
|
||||||
<Term
|
<Term
|
||||||
lines={logs || []}
|
lines={logs || []}
|
||||||
highlighted={highlighted}
|
highlighted={highlighted}
|
||||||
exitcode={assertProcFinished(proc) ? proc.exit_code : undefined}
|
exitcode={assertProcFinished(proc) ? proc.exit_code : undefined}
|
||||||
/>
|
/>
|
||||||
<Bottom />
|
<Bottom />
|
||||||
<Actions
|
<Actions
|
||||||
running={assertProcRunning(proc)}
|
running={assertProcRunning(proc)}
|
||||||
following={follow}
|
following={follow}
|
||||||
onfollow={this.handleFollow}
|
onfollow={this.handleFollow}
|
||||||
onunfollow={this.handleFollow}
|
onunfollow={this.handleFollow}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,25 +119,25 @@ export default class Output extends Component {
|
||||||
* to follow, unfollow, scroll to top and scroll to bottom.
|
* to follow, unfollow, scroll to top and scroll to bottom.
|
||||||
*/
|
*/
|
||||||
const Actions = ({ following, running, onfollow, onunfollow }) => (
|
const Actions = ({ following, running, onfollow, onunfollow }) => (
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
{running && !following ? (
|
{running && !following ? (
|
||||||
<button onClick={onfollow} className={styles.follow}>
|
<button onClick={onfollow} className={styles.follow}>
|
||||||
<PlayIcon />
|
<PlayIcon />
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{running && following ? (
|
{running && following ? (
|
||||||
<button onClick={onunfollow} className={styles.unfollow}>
|
<button onClick={onunfollow} className={styles.unfollow}>
|
||||||
<PauseIcon />
|
<PauseIcon />
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<button onClick={scrollToTop} className={styles.bottom}>
|
<button onClick={scrollToTop} className={styles.bottom}>
|
||||||
<ExpandIcon />
|
<ExpandIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button onClick={scrollToBottom} className={styles.top}>
|
<button onClick={scrollToBottom} className={styles.top}>
|
||||||
<ExpandIcon />
|
<ExpandIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,69 +10,69 @@ import { branch } from "baobab-react/higher-order";
|
||||||
import { inject } from "config/client/inject";
|
import { inject } from "config/client/inject";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo, build } = props.match.params;
|
const { owner, repo, build } = props.match.params;
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
const number = parseInt(build);
|
const number = parseInt(build);
|
||||||
return {
|
return {
|
||||||
repo: ["repos", "data", slug],
|
repo: ["repos", "data", slug],
|
||||||
build: ["builds", "data", slug, number],
|
build: ["builds", "data", slug, number]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class BuildMenu extends Component {
|
export default class BuildMenu extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleCancel = this.handleCancel.bind(this);
|
this.handleCancel = this.handleCancel.bind(this);
|
||||||
this.handleRestart = this.handleRestart.bind(this);
|
this.handleRestart = this.handleRestart.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRestart() {
|
handleRestart() {
|
||||||
const { dispatch, drone, repo, build } = this.props;
|
const { dispatch, drone, repo, build } = this.props;
|
||||||
dispatch(restartBuild, drone, repo.owner, repo.name, build.number);
|
dispatch(restartBuild, drone, repo.owner, repo.name, build.number);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
const { dispatch, drone, repo, build, match } = this.props;
|
const { dispatch, drone, repo, build, match } = this.props;
|
||||||
const proc = findChildProcess(build.procs, match.params.proc || 2);
|
const proc = findChildProcess(build.procs, match.params.proc || 2);
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
cancelBuild,
|
cancelBuild,
|
||||||
drone,
|
drone,
|
||||||
repo.owner,
|
repo.owner,
|
||||||
repo.name,
|
repo.name,
|
||||||
build.number,
|
build.number,
|
||||||
proc.ppid,
|
proc.ppid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { build } = this.props;
|
const { build } = this.props;
|
||||||
|
|
||||||
const rightSide = !build ? (
|
const rightSide = !build ? (
|
||||||
undefined
|
undefined
|
||||||
) : (
|
) : (
|
||||||
<section>
|
<section>
|
||||||
{build.status === "pending" || build.status === "running" ? (
|
{build.status === "pending" || build.status === "running" ? (
|
||||||
<button onClick={this.handleCancel}>
|
<button onClick={this.handleCancel}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
<span>Cancel</span>
|
<span>Cancel</span>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button onClick={this.handleRestart}>
|
<button onClick={this.handleRestart}>
|
||||||
<RefreshIcon />
|
<RefreshIcon />
|
||||||
<span>Restart Build</span>
|
<span>Restart Build</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<RepoMenu {...this.props} right={rightSide} />
|
<RepoMenu {...this.props} right={rightSide} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,48 +8,48 @@ import BuildMeta from "shared/components/build_event";
|
||||||
import styles from "./list.less";
|
import styles from "./list.less";
|
||||||
|
|
||||||
export const List = ({ children }) => (
|
export const List = ({ children }) => (
|
||||||
<div className={styles.list}>{children}</div>
|
<div className={styles.list}>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export class Item extends Component {
|
export class Item extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { build } = this.props;
|
const { build } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.item}>
|
<div className={styles.item}>
|
||||||
<div className={styles.icon}>
|
<div className={styles.icon}>
|
||||||
<img src={build.author_avatar} />
|
<img src={build.author_avatar} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.body}>
|
<div className={styles.body}>
|
||||||
<h3>{build.message.split("\n")[0]}</h3>
|
<h3>{build.message.split("\n")[0]}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.meta}>
|
<div className={styles.meta}>
|
||||||
<BuildMeta
|
<BuildMeta
|
||||||
link={build.link_url}
|
link={build.link_url}
|
||||||
event={build.event}
|
event={build.event}
|
||||||
commit={build.commit}
|
commit={build.commit}
|
||||||
branch={build.branch}
|
branch={build.branch}
|
||||||
target={build.deploy_to}
|
target={build.deploy_to}
|
||||||
refspec={build.refspec}
|
refspec={build.refspec}
|
||||||
refs={build.ref}
|
refs={build.ref}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.break} />
|
<div className={styles.break} />
|
||||||
|
|
||||||
<div className={styles.time}>
|
<div className={styles.time}>
|
||||||
<BuildTime
|
<BuildTime
|
||||||
start={build.started_at || build.created_at}
|
start={build.started_at || build.created_at}
|
||||||
finish={build.finished_at}
|
finish={build.finished_at}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.status}>
|
<div className={styles.status}>
|
||||||
<StatusNumber status={build.status} number={build.number} />
|
<StatusNumber status={build.status} number={build.number} />
|
||||||
<Status status={build.status} />
|
<Status status={build.status} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,18 @@ import { Link } from "react-router-dom";
|
||||||
import Breadcrumb from "shared/components/breadcrumb";
|
import Breadcrumb from "shared/components/breadcrumb";
|
||||||
|
|
||||||
export default class Header extends Component {
|
export default class Header extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { owner, repo } = this.props.match.params;
|
const { owner, repo } = this.props.match.params;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
elements={[
|
elements={[
|
||||||
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
<Link to={`/${owner}/${repo}`} key={`${owner}-${repo}`}>
|
||||||
{owner} / {repo}
|
{owner} / {repo}
|
||||||
</Link>,
|
</Link>
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,114 +11,114 @@ import { inject } from "config/client/inject";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo } = props.match.params;
|
const { owner, repo } = props.match.params;
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
return {
|
return {
|
||||||
repo: ["repos", "data", slug],
|
repo: ["repos", "data", slug],
|
||||||
builds: ["builds", "data", slug],
|
builds: ["builds", "data", slug],
|
||||||
loaded: ["builds", "loaded"],
|
loaded: ["builds", "loaded"],
|
||||||
error: ["builds", "error"],
|
error: ["builds", "error"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class Main extends Component {
|
export default class Main extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.fetchNextBuildPage = this.fetchNextBuildPage.bind(this);
|
this.fetchNextBuildPage = this.fetchNextBuildPage.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.synchronize(this.props);
|
this.synchronize(this.props);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.repo !== nextProps.repo ||
|
this.props.repo !== nextProps.repo ||
|
||||||
(nextProps.builds !== undefined &&
|
(nextProps.builds !== undefined &&
|
||||||
this.props.builds !== nextProps.builds) ||
|
this.props.builds !== nextProps.builds) ||
|
||||||
this.props.error !== nextProps.error ||
|
this.props.error !== nextProps.error ||
|
||||||
this.props.loaded !== nextProps.loaded
|
this.props.loaded !== nextProps.loaded
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUpdate(nextProps) {
|
componentWillUpdate(nextProps) {
|
||||||
if (this.props.match.url !== nextProps.match.url) {
|
if (this.props.match.url !== nextProps.match.url) {
|
||||||
this.synchronize(nextProps);
|
this.synchronize(nextProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.location !== prevProps.location) {
|
if (this.props.location !== prevProps.location) {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronize(props) {
|
synchronize(props) {
|
||||||
const { drone, dispatch, match, repo } = props;
|
const { drone, dispatch, match, repo } = props;
|
||||||
|
|
||||||
if (!repo) {
|
if (!repo) {
|
||||||
dispatch(fetchRepository, drone, match.params.owner, match.params.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) {
|
fetchNextBuildPage(buildList) {
|
||||||
const { drone, dispatch, match } = this.props;
|
const { drone, dispatch, match } = this.props;
|
||||||
const page = Math.floor(buildList.length / 50) + 1;
|
const page = Math.floor(buildList.length / 50) + 1;
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
fetchBuildList,
|
fetchBuildList,
|
||||||
drone,
|
drone,
|
||||||
match.params.owner,
|
match.params.owner,
|
||||||
match.params.repo,
|
match.params.repo,
|
||||||
page,
|
page
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { repo, builds, loaded, error } = this.props;
|
const { repo, builds, loaded, error } = this.props;
|
||||||
const list = Object.values(builds || {});
|
const list = Object.values(builds || {});
|
||||||
|
|
||||||
function renderBuild(build) {
|
function renderBuild(build) {
|
||||||
return (
|
return (
|
||||||
<Link to={`/${repo.full_name}/${build.number}`} key={build.number}>
|
<Link to={`/${repo.full_name}/${build.number}`} key={build.number}>
|
||||||
<Item build={build} />
|
<Item build={build} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <div>Not Found</div>;
|
return <div>Not Found</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded && list.length === 0) {
|
if (!loaded && list.length === 0) {
|
||||||
return <div>Loading</div>;
|
return <div>Loading</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!repo) {
|
if (!repo) {
|
||||||
return <div>Loading</div>;
|
return <div>Loading</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
return <div>Build list is empty</div>;
|
return <div>Build list is empty</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<List>{list.sort(compareBuild).map(renderBuild)}</List>
|
<List>{list.sort(compareBuild).map(renderBuild)}</List>
|
||||||
{list.length < repo.last_build && (
|
{list.length < repo.last_build && (
|
||||||
<button
|
<button
|
||||||
onClick={() => this.fetchNextBuildPage(list)}
|
onClick={() => this.fetchNextBuildPage(list)}
|
||||||
className={styles.more}
|
className={styles.more}
|
||||||
>
|
>
|
||||||
Show more builds
|
Show more builds
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,14 @@ import React, { Component } from "react";
|
||||||
import Menu from "shared/components/menu";
|
import Menu from "shared/components/menu";
|
||||||
|
|
||||||
export default class RepoMenu extends Component {
|
export default class RepoMenu extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { owner, repo } = this.props.match.params;
|
const { owner, repo } = this.props.match.params;
|
||||||
const menu = [
|
const menu = [
|
||||||
{ to: `/${owner}/${repo}`, label: "Builds" },
|
{ to: `/${owner}/${repo}`, label: "Builds" },
|
||||||
{ to: `/${owner}/${repo}/settings/secrets`, label: "Secrets" },
|
{ to: `/${owner}/${repo}/settings/secrets`, label: "Secrets" },
|
||||||
{ to: `/${owner}/${repo}/settings/registry`, label: "Registry" },
|
{ to: `/${owner}/${repo}/settings/registry`, label: "Registry" },
|
||||||
{ to: `/${owner}/${repo}/settings`, label: "Settings" },
|
{ to: `/${owner}/${repo}/settings`, label: "Settings" }
|
||||||
];
|
];
|
||||||
return <Menu items={menu} {...this.props} />;
|
return <Menu items={menu} {...this.props} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,79 +2,79 @@ import React, { Component } from "react";
|
||||||
import styles from "./form.less";
|
import styles from "./form.less";
|
||||||
|
|
||||||
export class Form extends Component {
|
export class Form extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
address: "",
|
address: "",
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
this._handleAddressChange = this._handleAddressChange.bind(this);
|
this._handleAddressChange = this._handleAddressChange.bind(this);
|
||||||
this._handleUsernameChange = this._handleUsernameChange.bind(this);
|
this._handleUsernameChange = this._handleUsernameChange.bind(this);
|
||||||
this._handlePasswordChange = this._handlePasswordChange.bind(this);
|
this._handlePasswordChange = this._handlePasswordChange.bind(this);
|
||||||
this._handleSubmit = this._handleSubmit.bind(this);
|
this._handleSubmit = this._handleSubmit.bind(this);
|
||||||
|
|
||||||
this.clear = this.clear.bind(this);
|
this.clear = this.clear.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleAddressChange(event) {
|
_handleAddressChange(event) {
|
||||||
this.setState({ address: event.target.value });
|
this.setState({ address: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleUsernameChange(event) {
|
_handleUsernameChange(event) {
|
||||||
this.setState({ username: event.target.value });
|
this.setState({ username: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handlePasswordChange(event) {
|
_handlePasswordChange(event) {
|
||||||
this.setState({ password: event.target.value });
|
this.setState({ password: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleSubmit() {
|
_handleSubmit() {
|
||||||
const { onsubmit } = this.props;
|
const { onsubmit } = this.props;
|
||||||
|
|
||||||
const detail = {
|
const detail = {
|
||||||
address: this.state.address,
|
address: this.state.address,
|
||||||
username: this.state.username,
|
username: this.state.username,
|
||||||
password: this.state.password,
|
password: this.state.password
|
||||||
};
|
};
|
||||||
|
|
||||||
onsubmit({ detail });
|
onsubmit({ detail });
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.setState({ address: "" });
|
this.setState({ address: "" });
|
||||||
this.setState({ username: "" });
|
this.setState({ username: "" });
|
||||||
this.setState({ password: "" });
|
this.setState({ password: "" });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.form}>
|
<div className={styles.form}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={this.state.address}
|
value={this.state.address}
|
||||||
onChange={this._handleAddressChange}
|
onChange={this._handleAddressChange}
|
||||||
placeholder="Registry Address (e.g. docker.io)"
|
placeholder="Registry Address (e.g. docker.io)"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={this.state.username}
|
value={this.state.username}
|
||||||
onChange={this._handleUsernameChange}
|
onChange={this._handleUsernameChange}
|
||||||
placeholder="Registry Username"
|
placeholder="Registry Username"
|
||||||
/>
|
/>
|
||||||
<textarea
|
<textarea
|
||||||
rows="1"
|
rows="1"
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={this._handlePasswordChange}
|
onChange={this._handlePasswordChange}
|
||||||
placeholder="Registry Password"
|
placeholder="Registry Password"
|
||||||
/>
|
/>
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
<button onClick={this._handleSubmit}>Save</button>
|
<button onClick={this._handleSubmit}>Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,14 @@ import React from "react";
|
||||||
import styles from "./list.less";
|
import styles from "./list.less";
|
||||||
|
|
||||||
export const List = ({ children }) => (
|
export const List = ({ children }) => (
|
||||||
<div className={styles.list}>{children}</div>
|
<div className={styles.list}>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const Item = props => (
|
export const Item = props => (
|
||||||
<div className={styles.item} key={props.name}>
|
<div className={styles.item} key={props.name}>
|
||||||
<div>{props.name}</div>
|
<div>{props.name}</div>
|
||||||
<div>
|
<div>
|
||||||
<button onClick={props.ondelete}>delete</button>
|
<button onClick={props.ondelete}>delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,9 +2,9 @@ import React, { Component } from "react";
|
||||||
|
|
||||||
import { repositorySlug } from "shared/utils/repository";
|
import { repositorySlug } from "shared/utils/repository";
|
||||||
import {
|
import {
|
||||||
fetchRegistryList,
|
fetchRegistryList,
|
||||||
createRegistry,
|
createRegistry,
|
||||||
deleteRegistry,
|
deleteRegistry
|
||||||
} from "shared/utils/registry";
|
} from "shared/utils/registry";
|
||||||
|
|
||||||
import { branch } from "baobab-react/higher-order";
|
import { branch } from "baobab-react/higher-order";
|
||||||
|
@ -15,89 +15,89 @@ import { List, Item, Form } from "./components";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo } = props.match.params;
|
const { owner, repo } = props.match.params;
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
return {
|
return {
|
||||||
loaded: ["registry", "loaded"],
|
loaded: ["registry", "loaded"],
|
||||||
registries: ["registry", "data", slug],
|
registries: ["registry", "data", slug]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class RepoRegistry extends Component {
|
export default class RepoRegistry extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleDelete = this.handleDelete.bind(this);
|
this.handleDelete = this.handleDelete.bind(this);
|
||||||
this.handleSave = this.handleSave.bind(this);
|
this.handleSave = this.handleSave.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return this.props.registries !== nextProps.registries;
|
return this.props.registries !== nextProps.registries;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { dispatch, drone, match } = this.props;
|
const { dispatch, drone, match } = this.props;
|
||||||
const { owner, repo } = match.params;
|
const { owner, repo } = match.params;
|
||||||
dispatch(fetchRegistryList, drone, owner, repo);
|
dispatch(fetchRegistryList, drone, owner, repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSave(e) {
|
handleSave(e) {
|
||||||
const { dispatch, drone, match } = this.props;
|
const { dispatch, drone, match } = this.props;
|
||||||
const { owner, repo } = match.params;
|
const { owner, repo } = match.params;
|
||||||
const registry = {
|
const registry = {
|
||||||
address: e.detail.address,
|
address: e.detail.address,
|
||||||
username: e.detail.username,
|
username: e.detail.username,
|
||||||
password: e.detail.password,
|
password: e.detail.password
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch(createRegistry, drone, owner, repo, registry);
|
dispatch(createRegistry, drone, owner, repo, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDelete(registry) {
|
handleDelete(registry) {
|
||||||
const { dispatch, drone, match } = this.props;
|
const { dispatch, drone, match } = this.props;
|
||||||
const { owner, repo } = match.params;
|
const { owner, repo } = match.params;
|
||||||
dispatch(deleteRegistry, drone, owner, repo, registry.address);
|
dispatch(deleteRegistry, drone, owner, repo, registry.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { registries, loaded } = this.props;
|
const { registries, loaded } = this.props;
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return LOADING;
|
return LOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
{Object.keys(registries || {}).length === 0 ? EMPTY : undefined}
|
{Object.keys(registries || {}).length === 0 ? EMPTY : undefined}
|
||||||
<List>
|
<List>
|
||||||
{Object.values(registries || {}).map(renderRegistry.bind(this))}
|
{Object.values(registries || {}).map(renderRegistry.bind(this))}
|
||||||
</List>
|
</List>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.right}>
|
<div className={styles.right}>
|
||||||
<Form onsubmit={this.handleSave} />
|
<Form onsubmit={this.handleSave} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRegistry(registry) {
|
function renderRegistry(registry) {
|
||||||
return (
|
return (
|
||||||
<Item
|
<Item
|
||||||
name={registry.address}
|
name={registry.address}
|
||||||
ondelete={this.handleDelete.bind(this, registry)}
|
ondelete={this.handleDelete.bind(this, registry)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOADING = <div className={styles.loading}>Loading</div>;
|
const LOADING = <div className={styles.loading}>Loading</div>;
|
||||||
|
|
||||||
const EMPTY = (
|
const EMPTY = (
|
||||||
<div className={styles.empty}>
|
<div className={styles.empty}>
|
||||||
There are no registry credentials for this repository.
|
There are no registry credentials for this repository.
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,140 +1,140 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EVENT_PUSH,
|
EVENT_PUSH,
|
||||||
EVENT_TAG,
|
EVENT_TAG,
|
||||||
EVENT_PULL_REQUEST,
|
EVENT_PULL_REQUEST,
|
||||||
EVENT_DEPLOY,
|
EVENT_DEPLOY
|
||||||
} from "shared/constants/events";
|
} from "shared/constants/events";
|
||||||
|
|
||||||
import styles from "./form.less";
|
import styles from "./form.less";
|
||||||
|
|
||||||
export class Form extends Component {
|
export class Form extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
name: "",
|
name: "",
|
||||||
value: "",
|
value: "",
|
||||||
event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY],
|
event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY]
|
||||||
};
|
};
|
||||||
|
|
||||||
this._handleNameChange = this._handleNameChange.bind(this);
|
this._handleNameChange = this._handleNameChange.bind(this);
|
||||||
this._handleValueChange = this._handleValueChange.bind(this);
|
this._handleValueChange = this._handleValueChange.bind(this);
|
||||||
this._handleEventChange = this._handleEventChange.bind(this);
|
this._handleEventChange = this._handleEventChange.bind(this);
|
||||||
this._handleSubmit = this._handleSubmit.bind(this);
|
this._handleSubmit = this._handleSubmit.bind(this);
|
||||||
|
|
||||||
this.clear = this.clear.bind(this);
|
this.clear = this.clear.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleNameChange(event) {
|
_handleNameChange(event) {
|
||||||
this.setState({ name: event.target.value });
|
this.setState({ name: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleValueChange(event) {
|
_handleValueChange(event) {
|
||||||
this.setState({ value: event.target.value });
|
this.setState({ value: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleEventChange(event) {
|
_handleEventChange(event) {
|
||||||
const selected = this.state.event;
|
const selected = this.state.event;
|
||||||
let index;
|
let index;
|
||||||
|
|
||||||
if (event.target.checked) {
|
if (event.target.checked) {
|
||||||
selected.push(event.target.value);
|
selected.push(event.target.value);
|
||||||
} else {
|
} else {
|
||||||
index = selected.indexOf(event.target.value);
|
index = selected.indexOf(event.target.value);
|
||||||
selected.splice(index, 1);
|
selected.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ event: selected });
|
this.setState({ event: selected });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleSubmit() {
|
_handleSubmit() {
|
||||||
const { onsubmit } = this.props;
|
const { onsubmit } = this.props;
|
||||||
|
|
||||||
const detail = {
|
const detail = {
|
||||||
name: this.state.name,
|
name: this.state.name,
|
||||||
value: this.state.value,
|
value: this.state.value,
|
||||||
event: this.state.event,
|
event: this.state.event
|
||||||
};
|
};
|
||||||
|
|
||||||
onsubmit({ detail });
|
onsubmit({ detail });
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.setState({ name: "" });
|
this.setState({ name: "" });
|
||||||
this.setState({ value: "" });
|
this.setState({ value: "" });
|
||||||
this.setState({ event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY] });
|
this.setState({ event: [EVENT_PUSH, EVENT_TAG, EVENT_DEPLOY] });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let checked = this.state.event.reduce((map, event) => {
|
let checked = this.state.event.reduce((map, event) => {
|
||||||
map[event] = true;
|
map[event] = true;
|
||||||
return map;
|
return map;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.form}>
|
<div className={styles.form}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="name"
|
name="name"
|
||||||
value={this.state.name}
|
value={this.state.name}
|
||||||
placeholder="Secret Name"
|
placeholder="Secret Name"
|
||||||
onChange={this._handleNameChange}
|
onChange={this._handleNameChange}
|
||||||
/>
|
/>
|
||||||
<textarea
|
<textarea
|
||||||
rows="1"
|
rows="1"
|
||||||
name="value"
|
name="value"
|
||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
placeholder="Secret Value"
|
placeholder="Secret Value"
|
||||||
onChange={this._handleValueChange}
|
onChange={this._handleValueChange}
|
||||||
/>
|
/>
|
||||||
<section>
|
<section>
|
||||||
<h2>Events</h2>
|
<h2>Events</h2>
|
||||||
<div>
|
<div>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked[EVENT_PUSH]}
|
checked={checked[EVENT_PUSH]}
|
||||||
value={EVENT_PUSH}
|
value={EVENT_PUSH}
|
||||||
onChange={this._handleEventChange}
|
onChange={this._handleEventChange}
|
||||||
/>
|
/>
|
||||||
<span>push</span>
|
<span>push</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked[EVENT_TAG]}
|
checked={checked[EVENT_TAG]}
|
||||||
value={EVENT_TAG}
|
value={EVENT_TAG}
|
||||||
onChange={this._handleEventChange}
|
onChange={this._handleEventChange}
|
||||||
/>
|
/>
|
||||||
<span>tag</span>
|
<span>tag</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked[EVENT_PULL_REQUEST]}
|
checked={checked[EVENT_PULL_REQUEST]}
|
||||||
value={EVENT_PULL_REQUEST}
|
value={EVENT_PULL_REQUEST}
|
||||||
onChange={this._handleEventChange}
|
onChange={this._handleEventChange}
|
||||||
/>
|
/>
|
||||||
<span>pull request</span>
|
<span>pull request</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked[EVENT_DEPLOY]}
|
checked={checked[EVENT_DEPLOY]}
|
||||||
value={EVENT_DEPLOY}
|
value={EVENT_DEPLOY}
|
||||||
onChange={this._handleEventChange}
|
onChange={this._handleEventChange}
|
||||||
/>
|
/>
|
||||||
<span>deploy</span>
|
<span>deploy</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
<button onClick={this._handleSubmit}>Save</button>
|
<button onClick={this._handleSubmit}>Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,17 @@ import styles from "./list.less";
|
||||||
export const List = ({ children }) => <div>{children}</div>;
|
export const List = ({ children }) => <div>{children}</div>;
|
||||||
|
|
||||||
export const Item = props => (
|
export const Item = props => (
|
||||||
<div className={styles.item} key={props.name}>
|
<div className={styles.item} key={props.name}>
|
||||||
<div>
|
<div>
|
||||||
{props.name}
|
{props.name}
|
||||||
<ul>{props.event ? props.event.map(renderEvent) : null}</ul>
|
<ul>{props.event ? props.event.map(renderEvent) : null}</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button onClick={props.ondelete}>delete</button>
|
<button onClick={props.ondelete}>delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderEvent = event => {
|
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 { repositorySlug } from "shared/utils/repository";
|
||||||
import {
|
import {
|
||||||
fetchSecretList,
|
fetchSecretList,
|
||||||
createSecret,
|
createSecret,
|
||||||
deleteSecret,
|
deleteSecret
|
||||||
} from "shared/utils/secrets";
|
} from "shared/utils/secrets";
|
||||||
|
|
||||||
import { branch } from "baobab-react/higher-order";
|
import { branch } from "baobab-react/higher-order";
|
||||||
|
@ -15,85 +15,85 @@ import { List, Item, Form } from "./components";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo } = props.match.params;
|
const { owner, repo } = props.match.params;
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
return {
|
return {
|
||||||
loaded: ["secrets", "loaded"],
|
loaded: ["secrets", "loaded"],
|
||||||
secrets: ["secrets", "data", slug],
|
secrets: ["secrets", "data", slug]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class RepoSecrets extends Component {
|
export default class RepoSecrets extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleSave = this.handleSave.bind(this);
|
this.handleSave = this.handleSave.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return this.props.secrets !== nextProps.secrets;
|
return this.props.secrets !== nextProps.secrets;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { owner, repo } = this.props.match.params;
|
const { owner, repo } = this.props.match.params;
|
||||||
this.props.dispatch(fetchSecretList, this.props.drone, owner, repo);
|
this.props.dispatch(fetchSecretList, this.props.drone, owner, repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSave(e) {
|
handleSave(e) {
|
||||||
const { dispatch, drone, match } = this.props;
|
const { dispatch, drone, match } = this.props;
|
||||||
const { owner, repo } = match.params;
|
const { owner, repo } = match.params;
|
||||||
const secret = {
|
const secret = {
|
||||||
name: e.detail.name,
|
name: e.detail.name,
|
||||||
value: e.detail.value,
|
value: e.detail.value,
|
||||||
event: e.detail.event,
|
event: e.detail.event
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch(createSecret, drone, owner, repo, secret);
|
dispatch(createSecret, drone, owner, repo, secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDelete(secret) {
|
handleDelete(secret) {
|
||||||
const { dispatch, drone, match } = this.props;
|
const { dispatch, drone, match } = this.props;
|
||||||
const { owner, repo } = match.params;
|
const { owner, repo } = match.params;
|
||||||
dispatch(deleteSecret, drone, owner, repo, secret.name);
|
dispatch(deleteSecret, drone, owner, repo, secret.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { secrets, loaded } = this.props;
|
const { secrets, loaded } = this.props;
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return LOADING;
|
return LOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
{Object.keys(secrets || {}).length === 0 ? EMPTY : undefined}
|
{Object.keys(secrets || {}).length === 0 ? EMPTY : undefined}
|
||||||
<List>
|
<List>
|
||||||
{Object.values(secrets || {}).map(renderSecret.bind(this))}
|
{Object.values(secrets || {}).map(renderSecret.bind(this))}
|
||||||
</List>
|
</List>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.right}>
|
<div className={styles.right}>
|
||||||
<Form onsubmit={this.handleSave} />
|
<Form onsubmit={this.handleSave} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSecret(secret) {
|
function renderSecret(secret) {
|
||||||
return (
|
return (
|
||||||
<Item
|
<Item
|
||||||
name={secret.name}
|
name={secret.name}
|
||||||
event={secret.event}
|
event={secret.event}
|
||||||
ondelete={this.handleDelete.bind(this, secret)}
|
ondelete={this.handleDelete.bind(this, secret)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOADING = <div className={styles.loading}>Loading</div>;
|
const LOADING = <div className={styles.loading}>Loading</div>;
|
||||||
|
|
||||||
const EMPTY = (
|
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 { inject } from "config/client/inject";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fetchRepository,
|
fetchRepository,
|
||||||
updateRepository,
|
updateRepository,
|
||||||
repositorySlug,
|
repositorySlug
|
||||||
} from "shared/utils/repository";
|
} from "shared/utils/repository";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
VISIBILITY_PUBLIC,
|
VISIBILITY_PUBLIC,
|
||||||
VISIBILITY_PRIVATE,
|
VISIBILITY_PRIVATE,
|
||||||
VISIBILITY_INTERNAL,
|
VISIBILITY_INTERNAL
|
||||||
} from "shared/constants/visibility";
|
} from "shared/constants/visibility";
|
||||||
|
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
const { owner, repo } = props.match.params;
|
const { owner, repo } = props.match.params;
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
return {
|
return {
|
||||||
user: ["user", "data"],
|
user: ["user", "data"],
|
||||||
repo: ["repos", "data", slug],
|
repo: ["repos", "data", slug]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class Settings extends Component {
|
export default class Settings extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handlePushChange = this.handlePushChange.bind(this);
|
this.handlePushChange = this.handlePushChange.bind(this);
|
||||||
this.handlePullChange = this.handlePullChange.bind(this);
|
this.handlePullChange = this.handlePullChange.bind(this);
|
||||||
this.handleTagChange = this.handleTagChange.bind(this);
|
this.handleTagChange = this.handleTagChange.bind(this);
|
||||||
this.handleDeployChange = this.handleDeployChange.bind(this);
|
this.handleDeployChange = this.handleDeployChange.bind(this);
|
||||||
this.handleTrustedChange = this.handleTrustedChange.bind(this);
|
this.handleTrustedChange = this.handleTrustedChange.bind(this);
|
||||||
this.handleProtectedChange = this.handleProtectedChange.bind(this);
|
this.handleProtectedChange = this.handleProtectedChange.bind(this);
|
||||||
this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
|
this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
|
||||||
this.handleTimeoutChange = this.handleTimeoutChange.bind(this);
|
this.handleTimeoutChange = this.handleTimeoutChange.bind(this);
|
||||||
this.handlePathChange = this.handlePathChange.bind(this);
|
this.handlePathChange = this.handlePathChange.bind(this);
|
||||||
this.handleFallbackChange = this.handleFallbackChange.bind(this);
|
this.handleFallbackChange = this.handleFallbackChange.bind(this);
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return this.props.repo !== nextProps.repo;
|
return this.props.repo !== nextProps.repo;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { drone, dispatch, match, repo } = this.props;
|
const { drone, dispatch, match, repo } = this.props;
|
||||||
|
|
||||||
if (!repo) {
|
if (!repo) {
|
||||||
dispatch(fetchRepository, drone, match.params.owner, match.params.repo);
|
dispatch(fetchRepository, drone, match.params.owner, match.params.repo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { repo } = this.props;
|
const { repo } = this.props;
|
||||||
|
|
||||||
if (!repo) {
|
if (!repo) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<section>
|
<section>
|
||||||
<h2>Pipeline Path</h2>
|
<h2>Pipeline Path</h2>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={repo.config_file}
|
value={repo.config_file}
|
||||||
onBlur={this.handlePathChange}
|
onBlur={this.handlePathChange}
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.fallback}
|
checked={repo.fallback}
|
||||||
onChange={this.handleFallbackChange}
|
onChange={this.handleFallbackChange}
|
||||||
/>
|
/>
|
||||||
<span>Fallback to .drone.yml if path not exists</span>
|
<span>Fallback to .drone.yml if path not exists</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Repository Hooks</h2>
|
<h2>Repository Hooks</h2>
|
||||||
<div>
|
<div>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.allow_push}
|
checked={repo.allow_push}
|
||||||
onChange={this.handlePushChange}
|
onChange={this.handlePushChange}
|
||||||
/>
|
/>
|
||||||
<span>push</span>
|
<span>push</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.allow_pr}
|
checked={repo.allow_pr}
|
||||||
onChange={this.handlePullChange}
|
onChange={this.handlePullChange}
|
||||||
/>
|
/>
|
||||||
<span>pull request</span>
|
<span>pull request</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.allow_tags}
|
checked={repo.allow_tags}
|
||||||
onChange={this.handleTagChange}
|
onChange={this.handleTagChange}
|
||||||
/>
|
/>
|
||||||
<span>tag</span>
|
<span>tag</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.allow_deploys}
|
checked={repo.allow_deploys}
|
||||||
onChange={this.handleDeployChange}
|
onChange={this.handleDeployChange}
|
||||||
/>
|
/>
|
||||||
<span>deployment</span>
|
<span>deployment</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Project Settings</h2>
|
<h2>Project Settings</h2>
|
||||||
<div>
|
<div>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.gated}
|
checked={repo.gated}
|
||||||
onChange={this.handleProtectedChange}
|
onChange={this.handleProtectedChange}
|
||||||
/>
|
/>
|
||||||
<span>Protected</span>
|
<span>Protected</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={repo.trusted}
|
checked={repo.trusted}
|
||||||
onChange={this.handleTrustedChange}
|
onChange={this.handleTrustedChange}
|
||||||
/>
|
/>
|
||||||
<span>Trusted</span>
|
<span>Trusted</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Project Visibility</h2>
|
<h2>Project Visibility</h2>
|
||||||
<div>
|
<div>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="visibility"
|
name="visibility"
|
||||||
value="public"
|
value="public"
|
||||||
checked={repo.visibility === VISIBILITY_PUBLIC}
|
checked={repo.visibility === VISIBILITY_PUBLIC}
|
||||||
onChange={this.handleVisibilityChange}
|
onChange={this.handleVisibilityChange}
|
||||||
/>
|
/>
|
||||||
<span>Public</span>
|
<span>Public</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="visibility"
|
name="visibility"
|
||||||
value="private"
|
value="private"
|
||||||
checked={repo.visibility === VISIBILITY_PRIVATE}
|
checked={repo.visibility === VISIBILITY_PRIVATE}
|
||||||
onChange={this.handleVisibilityChange}
|
onChange={this.handleVisibilityChange}
|
||||||
/>
|
/>
|
||||||
<span>Private</span>
|
<span>Private</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="visibility"
|
name="visibility"
|
||||||
value="internal"
|
value="internal"
|
||||||
checked={repo.visibility === VISIBILITY_INTERNAL}
|
checked={repo.visibility === VISIBILITY_INTERNAL}
|
||||||
onChange={this.handleVisibilityChange}
|
onChange={this.handleVisibilityChange}
|
||||||
/>
|
/>
|
||||||
<span>Internal</span>
|
<span>Internal</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Timeout</h2>
|
<h2>Timeout</h2>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={repo.timeout}
|
value={repo.timeout}
|
||||||
onBlur={this.handleTimeoutChange}
|
onBlur={this.handleTimeoutChange}
|
||||||
/>
|
/>
|
||||||
<span className={styles.minutes}>minutes</span>
|
<span className={styles.minutes}>minutes</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePushChange(e) {
|
handlePushChange(e) {
|
||||||
this.handleChange("allow_push", e.target.checked);
|
this.handleChange("allow_push", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePullChange(e) {
|
handlePullChange(e) {
|
||||||
this.handleChange("allow_pr", e.target.checked);
|
this.handleChange("allow_pr", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTagChange(e) {
|
handleTagChange(e) {
|
||||||
this.handleChange("allow_tag", e.target.checked);
|
this.handleChange("allow_tag", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeployChange(e) {
|
handleDeployChange(e) {
|
||||||
this.handleChange("allow_deploy", e.target.checked);
|
this.handleChange("allow_deploy", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTrustedChange(e) {
|
handleTrustedChange(e) {
|
||||||
this.handleChange("trusted", e.target.checked);
|
this.handleChange("trusted", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleProtectedChange(e) {
|
handleProtectedChange(e) {
|
||||||
this.handleChange("gated", e.target.checked);
|
this.handleChange("gated", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleVisibilityChange(e) {
|
handleVisibilityChange(e) {
|
||||||
this.handleChange("visibility", e.target.value);
|
this.handleChange("visibility", e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTimeoutChange(e) {
|
handleTimeoutChange(e) {
|
||||||
this.handleChange("timeout", parseInt(e.target.value));
|
this.handleChange("timeout", parseInt(e.target.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePathChange(e) {
|
handlePathChange(e) {
|
||||||
this.handleChange("config_file", e.target.value);
|
this.handleChange("config_file", e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFallbackChange(e) {
|
handleFallbackChange(e) {
|
||||||
this.handleChange("fallback", e.target.checked);
|
this.handleChange("fallback", e.target.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange(prop, value) {
|
handleChange(prop, value) {
|
||||||
const { dispatch, drone, repo } = this.props;
|
const { dispatch, drone, repo } = this.props;
|
||||||
let data = {};
|
let data = {};
|
||||||
data[prop] = value;
|
data[prop] = value;
|
||||||
dispatch(updateRepository, drone, repo.owner, repo.name, data);
|
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
|
// @see https://github.com/yannickcr/eslint-plugin-react/issues/512
|
||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
export default function() {
|
export default function() {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/account/tokens" exact={true} component={accountTitle} />
|
<Route path="/account/tokens" exact={true} component={accountTitle} />
|
||||||
<Route path="/account/repos" exact={true} component={accountRepos} />
|
<Route path="/account/repos" exact={true} component={accountRepos} />
|
||||||
<Route path="/login" exact={false} component={loginTitle} />
|
<Route path="/login" exact={false} component={loginTitle} />
|
||||||
<Route path="/:owner/:repo" exact={false} component={repoTitle} />
|
<Route path="/:owner/:repo" exact={false} component={repoTitle} />
|
||||||
<Route path="/" exact={false} component={defautTitle} />
|
<Route path="/" exact={false} component={defautTitle} />
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const accountTitle = () => <Title render="Tokens | drone" />;
|
const accountTitle = () => <Title render="Tokens | drone" />;
|
||||||
|
@ -23,7 +23,7 @@ const accountRepos = () => <Title render="Repositories | drone" />;
|
||||||
const loginTitle = () => <Title render="Login | drone" />;
|
const loginTitle = () => <Title render="Login | drone" />;
|
||||||
|
|
||||||
const repoTitle = ({ match }) => (
|
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" />;
|
const defautTitle = () => <Title render="Welcome | drone" />;
|
||||||
|
|
|
@ -7,34 +7,34 @@ import { Switch } from "./switch";
|
||||||
import styles from "./list.less";
|
import styles from "./list.less";
|
||||||
|
|
||||||
export const List = ({ children }) => (
|
export const List = ({ children }) => (
|
||||||
<div className={styles.list}>{children}</div>
|
<div className={styles.list}>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export class Item extends Component {
|
export class Item extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { owner, name, active, link, onchange } = this.props;
|
const { owner, name, active, link, onchange } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.item}>
|
<div className={styles.item}>
|
||||||
<div>
|
<div>
|
||||||
{owner}/{name}
|
{owner}/{name}
|
||||||
</div>
|
</div>
|
||||||
<div className={active ? styles.active : styles.inactive}>
|
<div className={active ? styles.active : styles.inactive}>
|
||||||
<Link to={link}>
|
<Link to={link}>
|
||||||
<LaunchIcon />
|
<LaunchIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Switch onchange={onchange} checked={active} />
|
<Switch onchange={onchange} checked={active} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return (
|
return (
|
||||||
this.props.owner !== nextProps.owner ||
|
this.props.owner !== nextProps.owner ||
|
||||||
this.props.name !== nextProps.name ||
|
this.props.name !== nextProps.name ||
|
||||||
this.props.active !== nextProps.active
|
this.props.active !== nextProps.active
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@ import React, { Component } from "react";
|
||||||
import styles from "./switch.less";
|
import styles from "./switch.less";
|
||||||
|
|
||||||
export class Switch extends Component {
|
export class Switch extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { checked, onchange } = this.props;
|
const { checked, onchange } = this.props;
|
||||||
return (
|
return (
|
||||||
<label className={styles.switch}>
|
<label className={styles.switch}>
|
||||||
<input type="checkbox" checked={checked} onChange={onchange} />
|
<input type="checkbox" checked={checked} onChange={onchange} />
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { branch } from "baobab-react/higher-order";
|
||||||
import { inject } from "config/client/inject";
|
import { inject } from "config/client/inject";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fetchRepostoryList,
|
fetchRepostoryList,
|
||||||
disableRepository,
|
disableRepository,
|
||||||
enableRepository,
|
enableRepository
|
||||||
} from "shared/utils/repository";
|
} from "shared/utils/repository";
|
||||||
|
|
||||||
import { List, Item } from "./components";
|
import { List, Item } from "./components";
|
||||||
|
@ -15,105 +15,105 @@ import Breadcrumb, { SEPARATOR } from "shared/components/breadcrumb";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
return {
|
return {
|
||||||
repos: ["repos", "data"],
|
repos: ["repos", "data"],
|
||||||
loaded: ["repos", "loaded"],
|
loaded: ["repos", "loaded"],
|
||||||
error: ["repos", "error"],
|
error: ["repos", "error"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class UserRepos extends Component {
|
export default class UserRepos extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleFilter = this.handleFilter.bind(this);
|
this.handleFilter = this.handleFilter.bind(this);
|
||||||
this.renderItem = this.renderItem.bind(this);
|
this.renderItem = this.renderItem.bind(this);
|
||||||
this.handleToggle = this.handleToggle.bind(this);
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFilter(e) {
|
handleFilter(e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
search: e.target.value,
|
search: e.target.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleToggle(repo, e) {
|
handleToggle(repo, e) {
|
||||||
const { dispatch, drone } = this.props;
|
const { dispatch, drone } = this.props;
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
dispatch(enableRepository, drone, repo.owner, repo.name);
|
dispatch(enableRepository, drone, repo.owner, repo.name);
|
||||||
} else {
|
} else {
|
||||||
dispatch(disableRepository, drone, repo.owner, repo.name);
|
dispatch(disableRepository, drone, repo.owner, repo.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
if (!this._dispatched) {
|
if (!this._dispatched) {
|
||||||
this._dispatched = true;
|
this._dispatched = true;
|
||||||
this.props.dispatch(fetchRepostoryList, this.props.drone);
|
this.props.dispatch(fetchRepostoryList, this.props.drone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.repos !== nextProps.repos ||
|
this.props.repos !== nextProps.repos ||
|
||||||
this.state.search !== nextState.search
|
this.state.search !== nextState.search
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { repos, loaded, error } = this.props;
|
const { repos, loaded, error } = this.props;
|
||||||
const { search } = this.state;
|
const { search } = this.state;
|
||||||
const list = Object.values(repos || {});
|
const list = Object.values(repos || {});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return LOADING;
|
return LOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
const filter = repo => {
|
const filter = repo => {
|
||||||
return !search || repo.full_name.indexOf(search) !== -1;
|
return !search || repo.full_name.indexOf(search) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const filtered = list.filter(filter);
|
const filtered = list.filter(filter);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.search}>
|
<div className={styles.search}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Search …"
|
placeholder="Search …"
|
||||||
onChange={this.handleFilter}
|
onChange={this.handleFilter}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
{filtered.length === 0 ? NO_MATCHES : null}
|
{filtered.length === 0 ? NO_MATCHES : null}
|
||||||
<List>{list.filter(filter).map(this.renderItem)}</List>
|
<List>{list.filter(filter).map(this.renderItem)}</List>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem(repo) {
|
renderItem(repo) {
|
||||||
return (
|
return (
|
||||||
<Item
|
<Item
|
||||||
key={repo.full_name}
|
key={repo.full_name}
|
||||||
owner={repo.owner}
|
owner={repo.owner}
|
||||||
name={repo.name}
|
name={repo.name}
|
||||||
active={repo.active}
|
active={repo.active}
|
||||||
link={`/${repo.full_name}`}
|
link={`/${repo.full_name}`}
|
||||||
onchange={this.handleToggle.bind(this, repo)}
|
onchange={this.handleToggle.bind(this, repo)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOADING = <div>Loading</div>;
|
const LOADING = <div>Loading</div>;
|
||||||
|
@ -126,12 +126,12 @@ const ERROR = <div>Error</div>;
|
||||||
|
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
export class UserRepoTitle extends Component {
|
export class UserRepoTitle extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
elements={[<span>Account</span>, SEPARATOR, <span>Repositories</span>]}
|
elements={[<span>Account</span>, SEPARATOR, <span>Repositories</span>]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* eslint-enable react/jsx-key */
|
/* eslint-enable react/jsx-key */
|
||||||
|
|
|
@ -6,36 +6,36 @@ import { SyncIcon } from "shared/components/icons";
|
||||||
import Menu from "shared/components/menu";
|
import Menu from "shared/components/menu";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
return {
|
return {
|
||||||
repos: ["repos"],
|
repos: ["repos"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class UserReposMenu extends Component {
|
export default class UserReposMenu extends Component {
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.handleClick = this.handleClick.bind(this);
|
this.handleClick = this.handleClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick() {
|
handleClick() {
|
||||||
const { dispatch, drone } = this.props;
|
const { dispatch, drone } = this.props;
|
||||||
dispatch(syncRepostoryList, drone);
|
dispatch(syncRepostoryList, drone);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loaded } = this.props.repos;
|
const { loaded } = this.props.repos;
|
||||||
const right = (
|
const right = (
|
||||||
<section>
|
<section>
|
||||||
<button disabled={!loaded} onClick={this.handleClick}>
|
<button disabled={!loaded} onClick={this.handleClick}>
|
||||||
<SyncIcon />
|
<SyncIcon />
|
||||||
<span>Synchronize</span>
|
<span>Synchronize</span>
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <Menu items={[]} right={right} />;
|
return <Menu items={[]} right={right} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,53 +6,55 @@ import { inject } from "config/client/inject";
|
||||||
import styles from "./index.less";
|
import styles from "./index.less";
|
||||||
|
|
||||||
const binding = (props, context) => {
|
const binding = (props, context) => {
|
||||||
return {
|
return {
|
||||||
location: ["location"],
|
location: ["location"],
|
||||||
token: ["token"],
|
token: ["token"]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject
|
@inject
|
||||||
@branch(binding)
|
@branch(binding)
|
||||||
export default class Tokens extends Component {
|
export default class Tokens extends Component {
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.props.location !== nextProps.location ||
|
this.props.location !== nextProps.location ||
|
||||||
this.props.token !== nextProps.token
|
this.props.token !== nextProps.token
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { drone, dispatch } = this.props;
|
const { drone, dispatch } = this.props;
|
||||||
|
|
||||||
dispatch(generateToken, drone);
|
dispatch(generateToken, drone);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { location, token } = this.props;
|
const { location, token } = this.props;
|
||||||
|
|
||||||
if (!location || !token) {
|
if (!location || !token) {
|
||||||
return <div>Loading</div>;
|
return <div>Loading</div>;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<h2>Your Personal Token:</h2>
|
<h2>Your Personal Token:</h2>
|
||||||
<pre>{token}</pre>
|
<pre>{token}</pre>
|
||||||
<h2>Example API Usage:</h2>
|
<h2>Example API Usage:</h2>
|
||||||
<pre>{usageWithCURL(location, token)}</pre>
|
<pre>{usageWithCURL(location, token)}</pre>
|
||||||
<h2>Example CLI Usage:</h2>
|
<h2>Example CLI Usage:</h2>
|
||||||
<pre>{usageWithCLI(location, token)}</pre>
|
<pre>{usageWithCLI(location, token)}</pre>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const usageWithCURL = (location, token) => {
|
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) => {
|
const usageWithCLI = (location, token) => {
|
||||||
return `export DRONE_SERVER=${location.protocol}//${location.host}
|
return `export DRONE_SERVER=${location.protocol}//${location.host}
|
||||||
export DRONE_TOKEN=${token}
|
export DRONE_TOKEN=${token}
|
||||||
|
|
||||||
drone info`;
|
drone info`;
|
||||||
|
|
|
@ -3,30 +3,30 @@ import { mount } from "enzyme";
|
||||||
|
|
||||||
import Status from "../status";
|
import Status from "../status";
|
||||||
import {
|
import {
|
||||||
STATUS_FAILURE,
|
STATUS_FAILURE,
|
||||||
STATUS_RUNNING,
|
STATUS_RUNNING,
|
||||||
STATUS_SUCCESS,
|
STATUS_SUCCESS
|
||||||
} from "shared/constants/status";
|
} from "shared/constants/status";
|
||||||
|
|
||||||
jest.dontMock("../status");
|
jest.dontMock("../status");
|
||||||
|
|
||||||
describe("Status component", () => {
|
describe("Status component", () => {
|
||||||
test("updates on status change", () => {
|
test("updates on status change", () => {
|
||||||
const status = mount(<Status status={STATUS_FAILURE} />);
|
const status = mount(<Status status={STATUS_FAILURE} />);
|
||||||
const instance = status.instance();
|
const instance = status.instance();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
instance.shouldComponentUpdate({ status: STATUS_FAILURE }),
|
instance.shouldComponentUpdate({ status: STATUS_FAILURE })
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
expect(
|
expect(
|
||||||
instance.shouldComponentUpdate({ status: STATUS_SUCCESS }),
|
instance.shouldComponentUpdate({ status: STATUS_SUCCESS })
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
expect(status.hasClass("failure")).toBeTruthy();
|
expect(status.hasClass("failure")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses the status as the class name", () => {
|
test("uses the status as the class name", () => {
|
||||||
const status = mount(<Status status={STATUS_RUNNING} />);
|
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";
|
import styles from "./avatar.less";
|
||||||
|
|
||||||
export default class Avatar extends Component {
|
export default class Avatar extends Component {
|
||||||
render() {
|
render() {
|
||||||
const image = this.props.image;
|
const image = this.props.image;
|
||||||
const style = {
|
const style = {
|
||||||
backgroundImage: `url(${image})`,
|
backgroundImage: `url(${image})`
|
||||||
};
|
};
|
||||||
return <div className={styles.avatar} style={style} />;
|
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.
|
// helper function to render a list item.
|
||||||
const renderItem = (element, index) => {
|
const renderItem = (element, index) => {
|
||||||
return <li key={index}>{element}</li>;
|
return <li key={index}>{element}</li>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Breadcrumb extends Component {
|
export default class Breadcrumb extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { elements } = this.props;
|
const { elements } = this.props;
|
||||||
return <ol className={style.breadcrumb}>{elements.map(renderItem)}</ol>;
|
return <ol className={style.breadcrumb}>{elements.map(renderItem)}</ol>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,68 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import {
|
import {
|
||||||
BranchIcon,
|
BranchIcon,
|
||||||
CommitIcon,
|
CommitIcon,
|
||||||
DeployIcon,
|
DeployIcon,
|
||||||
LaunchIcon,
|
LaunchIcon,
|
||||||
MergeIcon,
|
MergeIcon,
|
||||||
TagIcon,
|
TagIcon
|
||||||
} from "shared/components/icons/index";
|
} from "shared/components/icons/index";
|
||||||
import {
|
import {
|
||||||
EVENT_TAG,
|
EVENT_TAG,
|
||||||
EVENT_PULL_REQUEST,
|
EVENT_PULL_REQUEST,
|
||||||
EVENT_DEPLOY,
|
EVENT_DEPLOY
|
||||||
} from "shared/constants/events";
|
} from "shared/constants/events";
|
||||||
|
|
||||||
import styles from "./build_event.less";
|
import styles from "./build_event.less";
|
||||||
|
|
||||||
export default class BuildEvent extends Component {
|
export default class BuildEvent extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { event, branch, commit, refs, refspec, link, target } = this.props;
|
const { event, branch, commit, refs, refspec, link, target } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.host}>
|
<div className={styles.host}>
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div>
|
<div>
|
||||||
<CommitIcon />
|
<CommitIcon />
|
||||||
</div>
|
</div>
|
||||||
<div>{commit && commit.substr(0, 10)}</div>
|
<div>{commit && commit.substr(0, 10)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div>
|
<div>
|
||||||
{event === EVENT_TAG ? (
|
{event === EVENT_TAG ? (
|
||||||
<TagIcon />
|
<TagIcon />
|
||||||
) : event === EVENT_PULL_REQUEST ? (
|
) : event === EVENT_PULL_REQUEST ? (
|
||||||
<MergeIcon />
|
<MergeIcon />
|
||||||
) : event === EVENT_DEPLOY ? (
|
) : event === EVENT_DEPLOY ? (
|
||||||
<DeployIcon />
|
<DeployIcon />
|
||||||
) : (
|
) : (
|
||||||
<BranchIcon />
|
<BranchIcon />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{event === EVENT_TAG && refs ? (
|
{event === EVENT_TAG && refs
|
||||||
trimTagRef(refs)
|
? trimTagRef(refs)
|
||||||
) : event === EVENT_PULL_REQUEST && refspec ? (
|
: event === EVENT_PULL_REQUEST && refspec
|
||||||
trimMergeRef(refs)
|
? trimMergeRef(refs)
|
||||||
) : event === EVENT_DEPLOY && target ? (
|
: event === EVENT_DEPLOY && target
|
||||||
target
|
? target
|
||||||
) : (
|
: branch}
|
||||||
branch
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
<a href={link} target="_blank">
|
||||||
</div>
|
<LaunchIcon />
|
||||||
<a href={link} target="_blank">
|
</a>
|
||||||
<LaunchIcon />
|
</div>
|
||||||
</a>
|
);
|
||||||
</div>
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const trimMergeRef = ref => {
|
const trimMergeRef = ref => {
|
||||||
return ref.match(/\d/g) || ref;
|
return ref.match(/\d/g) || ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
const trimTagRef = ref => {
|
const trimTagRef = ref => {
|
||||||
return ref.startsWith("refs/tags/") ? ref.substr(10) : ref;
|
return ref.startsWith("refs/tags/") ? ref.substr(10) : ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
// push
|
// push
|
||||||
|
|
|
@ -7,31 +7,31 @@ import Duration from "./duration";
|
||||||
import styles from "./build_time.less";
|
import styles from "./build_time.less";
|
||||||
|
|
||||||
export default class Runtime extends Component {
|
export default class Runtime extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { start, finish } = this.props;
|
const { start, finish } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={styles.host}>
|
<div className={styles.host}>
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div>
|
<div>
|
||||||
<ScheduleIcon />
|
<ScheduleIcon />
|
||||||
</div>
|
</div>
|
||||||
<div>{start ? <TimeAgo date={start * 1000} /> : <span>--</span>}</div>
|
<div>{start ? <TimeAgo date={start * 1000} /> : <span>--</span>}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div>
|
<div>
|
||||||
<TimelapseIcon />
|
<TimelapseIcon />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{finish ? (
|
{finish ? (
|
||||||
<Duration start={start} finished={finish} />
|
<Duration start={start} finished={finish} />
|
||||||
) : start ? (
|
) : start ? (
|
||||||
<TimeAgo date={start * 1000} />
|
<TimeAgo date={start * 1000} />
|
||||||
) : (
|
) : (
|
||||||
<span>--</span>
|
<span>--</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,56 +7,56 @@ export const DOCK_LEFT = styles.left;
|
||||||
export const DOCK_RIGHT = styles.right;
|
export const DOCK_RIGHT = styles.right;
|
||||||
|
|
||||||
export class Drawer extends Component {
|
export class Drawer extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { open, position } = this.props;
|
const { open, position } = this.props;
|
||||||
|
|
||||||
let classes = [styles.drawer];
|
let classes = [styles.drawer];
|
||||||
if (open) {
|
if (open) {
|
||||||
classes.push(styles.open);
|
classes.push(styles.open);
|
||||||
}
|
}
|
||||||
if (position) {
|
if (position) {
|
||||||
classes.push(position);
|
classes.push(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
var child = open ? (
|
var child = open ? (
|
||||||
<div key={0} onClick={this.props.onClick} className={styles.backdrop} />
|
<div key={0} onClick={this.props.onClick} className={styles.backdrop} />
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.join(" ")}>
|
<div className={classes.join(" ")}>
|
||||||
<CSSTransitionGroup
|
<CSSTransitionGroup
|
||||||
transitionName="fade"
|
transitionName="fade"
|
||||||
transitionEnterTimeout={150}
|
transitionEnterTimeout={150}
|
||||||
transitionLeaveTimeout={150}
|
transitionLeaveTimeout={150}
|
||||||
transitionAppearTimeout={150}
|
transitionAppearTimeout={150}
|
||||||
transitionAppear={true}
|
transitionAppear={true}
|
||||||
transitionEnter={true}
|
transitionEnter={true}
|
||||||
transitionLeave={true}
|
transitionLeave={true}
|
||||||
>
|
>
|
||||||
{child}
|
{child}
|
||||||
</CSSTransitionGroup>
|
</CSSTransitionGroup>
|
||||||
<div className={styles.inner}>{this.props.children}</div>
|
<div className={styles.inner}>{this.props.children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CloseButton extends Component {
|
export class CloseButton extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<button className={styles.close} onClick={this.props.onClick}>
|
<button className={styles.close} onClick={this.props.onClick}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MenuButton extends Component {
|
export class MenuButton extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<button className={styles.close} onClick={this.props.onClick}>
|
<button className={styles.close} onClick={this.props.onClick}>
|
||||||
Show Menu
|
Show Menu
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ import humanizeDuration from "humanize-duration";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default class Duration extends React.Component {
|
export default class Duration extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const { start, finished } = this.props;
|
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";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class BackIcon extends Component {
|
export default class BackIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<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" />
|
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class BranchIcon extends Component {
|
export default class BranchIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 24 24">
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class CheckIcon extends Component {
|
export default class CheckIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<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" />
|
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class ClockIcon extends Component {
|
export default class ClockIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class CloseIcon extends Component {
|
export default class CloseIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 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="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" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class CommitIcon extends Component {
|
export default class CommitIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class DeployIcon extends Component {
|
export default class DeployIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class ExpandIcon extends Component {
|
export default class ExpandIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 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="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
|
||||||
<path d="M0-.75h24v24H0z" fill="none" />
|
<path d="M0-.75h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,25 +21,25 @@ import TagIcon from "./tag";
|
||||||
import TimelapseIcon from "./timelapse";
|
import TimelapseIcon from "./timelapse";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
BackIcon,
|
BackIcon,
|
||||||
BranchIcon,
|
BranchIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
CloseIcon,
|
CloseIcon,
|
||||||
ClockIcon,
|
ClockIcon,
|
||||||
CommitIcon,
|
CommitIcon,
|
||||||
DeployIcon,
|
DeployIcon,
|
||||||
ExpandIcon,
|
ExpandIcon,
|
||||||
LaunchIcon,
|
LaunchIcon,
|
||||||
LinkIcon,
|
LinkIcon,
|
||||||
MenuIcon,
|
MenuIcon,
|
||||||
MergeIcon,
|
MergeIcon,
|
||||||
PauseIcon,
|
PauseIcon,
|
||||||
PlayIcon,
|
PlayIcon,
|
||||||
RefreshIcon,
|
RefreshIcon,
|
||||||
RemoveIcon,
|
RemoveIcon,
|
||||||
ScheduleIcon,
|
ScheduleIcon,
|
||||||
StarIcon,
|
StarIcon,
|
||||||
SyncIcon,
|
SyncIcon,
|
||||||
TagIcon,
|
TagIcon,
|
||||||
TimelapseIcon,
|
TimelapseIcon
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class LaunchIcon extends Component {
|
export default class LaunchIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
<svg className={this.props.className} viewBox="0 0 24 24">
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class LinkIcon extends Component {
|
export default class LinkIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class MenuIcon extends Component {
|
export default class MenuIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
|
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class MergeIcon extends Component {
|
export default class MergeIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
<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" />
|
<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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// <svg class={this.props.className} viewBox="0 0 54.5 68">
|
// <svg class={this.props.className} viewBox="0 0 54.5 68">
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class PauseIcon extends Component {
|
export default class PauseIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
|
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class PlayIcon extends Component {
|
export default class PlayIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M8 5v14l11-7z" />
|
<path d="M8 5v14l11-7z" />
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class RefreshIcon extends Component {
|
export default class RefreshIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 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="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" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class CheckIcon extends Component {
|
export default class CheckIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M19 13H5v-2h14v2z" />
|
<path d="M19 13H5v-2h14v2z" />
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class ReportIcon extends Component {
|
export default class ReportIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
<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="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" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class ScheduleIcon extends Component {
|
export default class ScheduleIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 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="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="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z" />
|
<path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class StarIcon extends Component {
|
export default class StarIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
>
|
>
|
||||||
{this.props.filled === true ? (
|
{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="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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class SyncIcon extends Component {
|
export default class SyncIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
<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="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" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class TagIcon extends Component {
|
export default class TagIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg className={this.props.className} viewBox="0 0 24 24">
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class TimelapseIcon extends Component {
|
export default class TimelapseIcon extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
width={this.props.size || 24}
|
width={this.props.size || 24}
|
||||||
height={this.props.size || 24}
|
height={this.props.size || 24}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<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" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class Logo extends Component {
|
export default class Logo extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 50 62.5" preserveAspectRatio="xMidYMid">
|
<svg viewBox="0 0 50 62.5" preserveAspectRatio="xMidYMid">
|
||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
fillRule="evenodd"
|
||||||
clipRule="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"
|
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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,28 +5,28 @@ import PropTypes from "prop-types";
|
||||||
import styles from "./menu.less";
|
import styles from "./menu.less";
|
||||||
|
|
||||||
export default class Menu extends Component {
|
export default class Menu extends Component {
|
||||||
propTypes = { items: PropTypes.array, right: PropTypes.any };
|
propTypes = { items: PropTypes.array, right: PropTypes.any };
|
||||||
render() {
|
render() {
|
||||||
const items = this.props.items;
|
const items = this.props.items;
|
||||||
const right = this.props.right ? (
|
const right = this.props.right ? (
|
||||||
<div className={styles.right}>{this.props.right}</div>
|
<div className={styles.right}>{this.props.right}</div>
|
||||||
) : null;
|
) : null;
|
||||||
return (
|
return (
|
||||||
<section className={styles.root}>
|
<section className={styles.root}>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
{items.map(i => (
|
{items.map(i => (
|
||||||
<Link
|
<Link
|
||||||
key={i.to + i.label}
|
key={i.to + i.label}
|
||||||
to={i.to}
|
to={i.to}
|
||||||
exact={true}
|
exact={true}
|
||||||
activeClassName={styles["link-active"]}
|
activeClassName={styles["link-active"]}
|
||||||
>
|
>
|
||||||
{i.label}
|
{i.label}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
{right}
|
{right}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,38 +4,38 @@ import CloseIcon from "shared/components/icons/close";
|
||||||
import { CSSTransitionGroup } from "react-transition-group";
|
import { CSSTransitionGroup } from "react-transition-group";
|
||||||
|
|
||||||
export class Snackbar extends React.Component {
|
export class Snackbar extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const { message } = this.props;
|
const { message } = this.props;
|
||||||
|
|
||||||
let classes = [styles.snackbar];
|
let classes = [styles.snackbar];
|
||||||
if (message) {
|
if (message) {
|
||||||
classes.push(styles.open);
|
classes.push(styles.open);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = message ? (
|
const content = message ? (
|
||||||
<div className={classes.join(" ")} key={message}>
|
<div className={classes.join(" ")} key={message}>
|
||||||
<div>{message}</div>
|
<div>{message}</div>
|
||||||
<button onClick={this.props.onClose}>
|
<button onClick={this.props.onClose}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CSSTransitionGroup
|
<CSSTransitionGroup
|
||||||
transitionName="slideup"
|
transitionName="slideup"
|
||||||
transitionEnterTimeout={200}
|
transitionEnterTimeout={200}
|
||||||
transitionLeaveTimeout={200}
|
transitionLeaveTimeout={200}
|
||||||
transitionAppearTimeout={200}
|
transitionAppearTimeout={200}
|
||||||
transitionAppear={true}
|
transitionAppear={true}
|
||||||
transitionEnter={true}
|
transitionEnter={true}
|
||||||
transitionLeave={true}
|
transitionLeave={true}
|
||||||
className={classes.root}
|
className={classes.root}
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
</CSSTransitionGroup>
|
</CSSTransitionGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// const SnackbarContent = ({ children, ...props }) => {
|
// const SnackbarContent = ({ children, ...props }) => {
|
||||||
|
|
|
@ -1,100 +1,100 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import {
|
import {
|
||||||
STATUS_BLOCKED,
|
STATUS_BLOCKED,
|
||||||
STATUS_DECLINED,
|
STATUS_DECLINED,
|
||||||
STATUS_ERROR,
|
STATUS_ERROR,
|
||||||
STATUS_FAILURE,
|
STATUS_FAILURE,
|
||||||
STATUS_KILLED,
|
STATUS_KILLED,
|
||||||
STATUS_PENDING,
|
STATUS_PENDING,
|
||||||
STATUS_RUNNING,
|
STATUS_RUNNING,
|
||||||
STATUS_SKIPPED,
|
STATUS_SKIPPED,
|
||||||
STATUS_STARTED,
|
STATUS_STARTED,
|
||||||
STATUS_SUCCESS,
|
STATUS_SUCCESS
|
||||||
} from "shared/constants/status";
|
} from "shared/constants/status";
|
||||||
import style from "./status.less";
|
import style from "./status.less";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
CloseIcon,
|
CloseIcon,
|
||||||
ClockIcon,
|
ClockIcon,
|
||||||
RefreshIcon,
|
RefreshIcon,
|
||||||
RemoveIcon,
|
RemoveIcon
|
||||||
} from "./icons/index";
|
} from "./icons/index";
|
||||||
|
|
||||||
const defaultIconSize = 15;
|
const defaultIconSize = 15;
|
||||||
|
|
||||||
const statusLabel = status => {
|
const statusLabel = status => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case STATUS_BLOCKED:
|
case STATUS_BLOCKED:
|
||||||
return "Pending Approval";
|
return "Pending Approval";
|
||||||
case STATUS_DECLINED:
|
case STATUS_DECLINED:
|
||||||
return "Declined";
|
return "Declined";
|
||||||
case STATUS_ERROR:
|
case STATUS_ERROR:
|
||||||
return "Error";
|
return "Error";
|
||||||
case STATUS_FAILURE:
|
case STATUS_FAILURE:
|
||||||
return "Failure";
|
return "Failure";
|
||||||
case STATUS_KILLED:
|
case STATUS_KILLED:
|
||||||
return "Cancelled";
|
return "Cancelled";
|
||||||
case STATUS_PENDING:
|
case STATUS_PENDING:
|
||||||
return "Pending";
|
return "Pending";
|
||||||
case STATUS_RUNNING:
|
case STATUS_RUNNING:
|
||||||
return "Running";
|
return "Running";
|
||||||
case STATUS_SKIPPED:
|
case STATUS_SKIPPED:
|
||||||
return "Skipped";
|
return "Skipped";
|
||||||
case STATUS_STARTED:
|
case STATUS_STARTED:
|
||||||
return "Running";
|
return "Running";
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
return "Successful";
|
return "Successful";
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderIcon = (status, size) => {
|
const renderIcon = (status, size) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case STATUS_SKIPPED:
|
case STATUS_SKIPPED:
|
||||||
return <RemoveIcon size={size} />;
|
return <RemoveIcon size={size} />;
|
||||||
case STATUS_PENDING:
|
case STATUS_PENDING:
|
||||||
return <ClockIcon size={size} />;
|
return <ClockIcon size={size} />;
|
||||||
case STATUS_RUNNING:
|
case STATUS_RUNNING:
|
||||||
case STATUS_STARTED:
|
case STATUS_STARTED:
|
||||||
return <RefreshIcon size={size} />;
|
return <RefreshIcon size={size} />;
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
return <CheckIcon size={size} />;
|
return <CheckIcon size={size} />;
|
||||||
default:
|
default:
|
||||||
return <CloseIcon size={size} />;
|
return <CloseIcon size={size} />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Status extends Component {
|
export default class Status extends Component {
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return this.props.status !== nextProps.status;
|
return this.props.status !== nextProps.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status } = this.props;
|
const { status } = this.props;
|
||||||
const icon = renderIcon(status, defaultIconSize);
|
const icon = renderIcon(status, defaultIconSize);
|
||||||
const classes = classnames(style.root, style[status]);
|
const classes = classnames(style.root, style[status]);
|
||||||
return <div className={classes}>{icon}</div>;
|
return <div className={classes}>{icon}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const StatusLabel = ({ status }) => {
|
export const StatusLabel = ({ status }) => {
|
||||||
return (
|
return (
|
||||||
<div className={classnames(style.label, style[status])}>
|
<div className={classnames(style.label, style[status])}>
|
||||||
<div>{statusLabel(status)}</div>
|
<div>{statusLabel(status)}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StatusText = ({ status, text }) => {
|
export const StatusText = ({ status, text }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames(style.label, style[status])}
|
className={classnames(style.label, style[status])}
|
||||||
style="text-transform: capitalize;padding: 5px 10px;"
|
style="text-transform: capitalize;padding: 5px 10px;"
|
||||||
>
|
>
|
||||||
<div>{text}</div>
|
<div>{text}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,9 @@ import classnames from "classnames";
|
||||||
import styles from "./status_number.less";
|
import styles from "./status_number.less";
|
||||||
|
|
||||||
export default class StatusNumber extends Component {
|
export default class StatusNumber extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { status, number } = this.props;
|
const { status, number } = this.props;
|
||||||
const className = classnames(styles.root, styles[status]);
|
const className = classnames(styles.root, styles[status]);
|
||||||
return <div className={className}>{number}</div>;
|
return <div className={className}>{number}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,14 @@ import Icon from "./icons/refresh";
|
||||||
import styles from "./sync.less";
|
import styles from "./sync.less";
|
||||||
|
|
||||||
export const Message = () => {
|
export const Message = () => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<div className={styles.alert}>
|
<div className={styles.alert}>
|
||||||
<div>
|
<div>
|
||||||
<Icon />
|
<Icon />
|
||||||
</div>
|
</div>
|
||||||
<div>Account synchronization in progress</div>
|
<div>Account synchronization in progress</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,14 +10,14 @@ const STATUS_STARTED = "started";
|
||||||
const STATUS_SUCCESS = "success";
|
const STATUS_SUCCESS = "success";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
STATUS_BLOCKED,
|
STATUS_BLOCKED,
|
||||||
STATUS_DECLINED,
|
STATUS_DECLINED,
|
||||||
STATUS_ERROR,
|
STATUS_ERROR,
|
||||||
STATUS_FAILURE,
|
STATUS_FAILURE,
|
||||||
STATUS_KILLED,
|
STATUS_KILLED,
|
||||||
STATUS_PENDING,
|
STATUS_PENDING,
|
||||||
STATUS_RUNNING,
|
STATUS_RUNNING,
|
||||||
STATUS_SKIPPED,
|
STATUS_SKIPPED,
|
||||||
STATUS_SUCCESS,
|
STATUS_SUCCESS,
|
||||||
STATUS_STARTED,
|
STATUS_STARTED
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,26 +13,26 @@ import { STATUS_PENDING, STATUS_RUNNING } from "shared/constants/status";
|
||||||
* @param {number|string} number - The build number.
|
* @param {number|string} number - The build number.
|
||||||
*/
|
*/
|
||||||
export const fetchBuild = (tree, client, owner, name, number) => {
|
export const fetchBuild = (tree, client, owner, name, number) => {
|
||||||
const slug = repositorySlug(owner, name);
|
const slug = repositorySlug(owner, name);
|
||||||
|
|
||||||
tree.unset(["builds", "loaded"]);
|
tree.unset(["builds", "loaded"]);
|
||||||
client
|
client
|
||||||
.getBuild(owner, name, number)
|
.getBuild(owner, name, number)
|
||||||
.then(build => {
|
.then(build => {
|
||||||
const path = ["builds", "data", slug, build.number];
|
const path = ["builds", "data", slug, build.number];
|
||||||
|
|
||||||
if (tree.exists(path)) {
|
if (tree.exists(path)) {
|
||||||
tree.deepMerge(path, build);
|
tree.deepMerge(path, build);
|
||||||
} else {
|
} else {
|
||||||
tree.set(path, build);
|
tree.set(path, build);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.set(["builds", "loaded"], true);
|
tree.set(["builds", "loaded"], true);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
tree.set(["builds", "loaded"], true);
|
tree.set(["builds", "loaded"], true);
|
||||||
tree.set(["builds", "error"], error);
|
tree.set(["builds", "error"], error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,33 +45,33 @@ export const fetchBuild = (tree, client, owner, name, number) => {
|
||||||
* @param {string} name - The repository name.
|
* @param {string} name - The repository name.
|
||||||
*/
|
*/
|
||||||
export const fetchBuildList = (tree, client, owner, name, page = 1) => {
|
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", "loaded"]);
|
||||||
tree.unset(["builds", "error"]);
|
tree.unset(["builds", "error"]);
|
||||||
|
|
||||||
client
|
client
|
||||||
.getBuildList(owner, name, { page: page })
|
.getBuildList(owner, name, { page: page })
|
||||||
.then(results => {
|
.then(results => {
|
||||||
let list = {};
|
let list = {};
|
||||||
results.map(build => {
|
results.map(build => {
|
||||||
list[build.number] = build;
|
list[build.number] = build;
|
||||||
});
|
});
|
||||||
|
|
||||||
const path = ["builds", "data", slug];
|
const path = ["builds", "data", slug];
|
||||||
if (tree.exists(path)) {
|
if (tree.exists(path)) {
|
||||||
tree.deepMerge(path, list);
|
tree.deepMerge(path, list);
|
||||||
} else {
|
} else {
|
||||||
tree.set(path, list);
|
tree.set(path, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.unset(["builds", "error"]);
|
tree.unset(["builds", "error"]);
|
||||||
tree.set(["builds", "loaded"], true);
|
tree.set(["builds", "loaded"], true);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
tree.set(["builds", "error"], error);
|
tree.set(["builds", "error"], error);
|
||||||
tree.set(["builds", "loaded"], true);
|
tree.set(["builds", "loaded"], true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,14 +85,14 @@ export const fetchBuildList = (tree, client, owner, name, page = 1) => {
|
||||||
* @param {number} proc - The process number.
|
* @param {number} proc - The process number.
|
||||||
*/
|
*/
|
||||||
export const cancelBuild = (tree, client, owner, repo, build, proc) => {
|
export const cancelBuild = (tree, client, owner, repo, build, proc) => {
|
||||||
client
|
client
|
||||||
.cancelBuild(owner, repo, build, proc)
|
.cancelBuild(owner, repo, build, proc)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
displayMessage(tree, "Successfully cancelled your build");
|
displayMessage(tree, "Successfully cancelled your build");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to cancel your build");
|
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.
|
* @param {number} build - The build number.
|
||||||
*/
|
*/
|
||||||
export const restartBuild = (tree, client, owner, repo, build) => {
|
export const restartBuild = (tree, client, owner, repo, build) => {
|
||||||
client
|
client
|
||||||
.restartBuild(owner, repo, build, { fork: true })
|
.restartBuild(owner, repo, build, { fork: true })
|
||||||
.then(result => {
|
.then(result => {
|
||||||
displayMessage(tree, "Successfully restarted your build");
|
displayMessage(tree, "Successfully restarted your build");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to restart your build");
|
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.
|
* @param {number} build - The build number.
|
||||||
*/
|
*/
|
||||||
export const approveBuild = (tree, client, owner, repo, build) => {
|
export const approveBuild = (tree, client, owner, repo, build) => {
|
||||||
client
|
client
|
||||||
.approveBuild(owner, repo, build)
|
.approveBuild(owner, repo, build)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
displayMessage(tree, "Successfully processed your approval decision");
|
displayMessage(tree, "Successfully processed your approval decision");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to process your approval decision");
|
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.
|
* @param {number} build - The build number.
|
||||||
*/
|
*/
|
||||||
export const declineBuild = (tree, client, owner, repo, build) => {
|
export const declineBuild = (tree, client, owner, repo, build) => {
|
||||||
client
|
client
|
||||||
.declineBuild(owner, repo, build)
|
.declineBuild(owner, repo, build)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
displayMessage(tree, "Successfully processed your decline decision");
|
displayMessage(tree, "Successfully processed your decline decision");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to process your decline decision");
|
displayMessage(tree, "Failed to process your decline decision");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,7 +163,7 @@ export const declineBuild = (tree, client, owner, repo, build) => {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export const compareBuild = (a, b) => {
|
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}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export const assertBuildFinished = build => {
|
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}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export const assertBuildMatrix = build => {
|
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.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export const fetchFeed = (tree, client) => {
|
export const fetchFeed = (tree, client) => {
|
||||||
client
|
client
|
||||||
.getBuildFeed({ latest: true })
|
.getBuildFeed({ latest: true })
|
||||||
.then(results => {
|
.then(results => {
|
||||||
let list = {};
|
let list = {};
|
||||||
let sorted = results.sort(compareFeedItem);
|
let sorted = results.sort(compareFeedItem);
|
||||||
sorted.map(repo => {
|
sorted.map(repo => {
|
||||||
list[repo.full_name] = repo;
|
list[repo.full_name] = repo;
|
||||||
});
|
});
|
||||||
if (sorted && sorted.length > 0) {
|
if (sorted && sorted.length > 0) {
|
||||||
tree.set(["feed", "latest"], sorted[0]);
|
tree.set(["feed", "latest"], sorted[0]);
|
||||||
}
|
}
|
||||||
tree.set(["feed", "loaded"], true);
|
tree.set(["feed", "loaded"], true);
|
||||||
tree.set(["feed", "data"], list);
|
tree.set(["feed", "data"], list);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
tree.set(["feed", "loaded"], true);
|
tree.set(["feed", "loaded"], true);
|
||||||
tree.set(["feed", "error"], error);
|
tree.set(["feed", "error"], error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,11 +34,11 @@ export const fetchFeed = (tree, client) => {
|
||||||
* @param {Object} client - The drone client.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export function fetchFeedOnce(tree, client) {
|
export function fetchFeedOnce(tree, client) {
|
||||||
if (fetchFeedOnce.fired) {
|
if (fetchFeedOnce.fired) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetchFeedOnce.fired = true;
|
fetchFeedOnce.fired = true;
|
||||||
return fetchFeed(tree, client);
|
return fetchFeed(tree, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,18 +49,18 @@ export function fetchFeedOnce(tree, client) {
|
||||||
* @param {Object} client - The drone client.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export const subscribeToFeed = (tree, client) => {
|
export const subscribeToFeed = (tree, client) => {
|
||||||
return client.on(data => {
|
return client.on(data => {
|
||||||
const { repo, build } = data;
|
const { repo, build } = data;
|
||||||
|
|
||||||
if (tree.exists("feed", "data", repo.full_name)) {
|
if (tree.exists("feed", "data", repo.full_name)) {
|
||||||
const cursor = tree.select(["feed", "data", repo.full_name]);
|
const cursor = tree.select(["feed", "data", repo.full_name]);
|
||||||
cursor.merge(build);
|
cursor.merge(build);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tree.exists("builds", "data", repo.full_name)) {
|
if (tree.exists("builds", "data", repo.full_name)) {
|
||||||
tree.set(["builds", "data", repo.full_name, build.number], build);
|
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.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export function subscribeToFeedOnce(tree, client) {
|
export function subscribeToFeedOnce(tree, client) {
|
||||||
if (subscribeToFeedOnce.fired) {
|
if (subscribeToFeedOnce.fired) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
subscribeToFeedOnce.fired = true;
|
subscribeToFeedOnce.fired = true;
|
||||||
return subscribeToFeed(tree, client);
|
return subscribeToFeed(tree, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,7 +85,7 @@ export function subscribeToFeedOnce(tree, client) {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export const compareFeedItem = (a, b) => {
|
export const compareFeedItem = (a, b) => {
|
||||||
return (
|
return (
|
||||||
(b.started_at || b.created_at || -1) - (a.started_at || a.created_at || -1)
|
(b.started_at || b.created_at || -1) - (a.started_at || a.created_at || -1)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
import { repositorySlug } from "./repository";
|
import { repositorySlug } from "./repository";
|
||||||
|
|
||||||
export function subscribeToLogs(tree, client, owner, repo, build, proc) {
|
export function subscribeToLogs(tree, client, owner, repo, build, proc) {
|
||||||
if (subscribeToLogs.ws) {
|
if (subscribeToLogs.ws) {
|
||||||
subscribeToLogs.ws.close();
|
subscribeToLogs.ws.close();
|
||||||
}
|
}
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
const init = { data: [] };
|
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 => {
|
subscribeToLogs.ws = client.stream(owner, repo, build, proc.ppid, item => {
|
||||||
if (item.proc === proc.name) {
|
if (item.proc === proc.name) {
|
||||||
tree.push(["logs", "data", slug, build, proc.pid, "data"], item);
|
tree.push(["logs", "data", slug, build, proc.pid, "data"], item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchLogs(tree, client, owner, repo, build, proc) {
|
export function fetchLogs(tree, client, owner, repo, build, proc) {
|
||||||
const slug = repositorySlug(owner, repo);
|
const slug = repositorySlug(owner, repo);
|
||||||
const init = {
|
const init = {
|
||||||
data: [],
|
data: [],
|
||||||
loading: true,
|
loading: true
|
||||||
};
|
};
|
||||||
|
|
||||||
tree.set(["logs", "data", slug, build, proc], init);
|
tree.set(["logs", "data", slug, build, proc], init);
|
||||||
|
|
||||||
client
|
client
|
||||||
.getLogs(owner, repo, build, proc)
|
.getLogs(owner, repo, build, proc)
|
||||||
.then(results => {
|
.then(results => {
|
||||||
tree.set(["logs", "data", slug, build, proc, "data"], 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, "loading"], false);
|
||||||
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
tree.set(["logs", "data", slug, build, proc, "loading"], false);
|
tree.set(["logs", "data", slug, build, proc, "loading"], false);
|
||||||
tree.set(["logs", "data", slug, build, proc, "eof"], true);
|
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.
|
* @param {boolean} follow - Follow the logs.
|
||||||
*/
|
*/
|
||||||
export const toggleLogs = (tree, follow) => {
|
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.
|
* @param {string} message - The message text.
|
||||||
*/
|
*/
|
||||||
export const displayMessage = (tree, message) => {
|
export const displayMessage = (tree, message) => {
|
||||||
tree.set(["message", "text"], message);
|
tree.set(["message", "text"], message);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
hideMessage(tree);
|
hideMessage(tree);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,5 +18,5 @@ export const displayMessage = (tree, message) => {
|
||||||
* @param {Object} tree - The drone state tree.
|
* @param {Object} tree - The drone state tree.
|
||||||
*/
|
*/
|
||||||
export const hideMessage = 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}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export const findChildProcess = (tree, pid) => {
|
export const findChildProcess = (tree, pid) => {
|
||||||
for (var i = 0; i < tree.length; i++) {
|
for (var i = 0; i < tree.length; i++) {
|
||||||
const parent = tree[i];
|
const parent = tree[i];
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
if (parent.pid == pid) {
|
if (parent.pid == pid) {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
for (var ii = 0; ii < parent.children.length; ii++) {
|
for (var ii = 0; ii < parent.children.length; ii++) {
|
||||||
const child = parent.children[ii];
|
const child = parent.children[ii];
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
if (child.pid == pid) {
|
if (child.pid == pid) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +32,7 @@ export const findChildProcess = (tree, pid) => {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export const assertProcFinished = proc => {
|
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}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export const assertProcRunning = proc => {
|
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.
|
* @param {string} name - The repository name.
|
||||||
*/
|
*/
|
||||||
export const fetchRegistryList = (tree, client, owner, 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", "loaded"]);
|
||||||
tree.unset(["registry", "error"]);
|
tree.unset(["registry", "error"]);
|
||||||
|
|
||||||
client.getRegistryList(owner, name).then(results => {
|
client.getRegistryList(owner, name).then(results => {
|
||||||
let list = {};
|
let list = {};
|
||||||
results.map(registry => {
|
results.map(registry => {
|
||||||
list[registry.address] = registry;
|
list[registry.address] = registry;
|
||||||
});
|
});
|
||||||
tree.set(["registry", "data", slug], list);
|
tree.set(["registry", "data", slug], list);
|
||||||
tree.set(["registry", "loaded"], true);
|
tree.set(["registry", "loaded"], true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,17 +37,17 @@ export const fetchRegistryList = (tree, client, owner, name) => {
|
||||||
* @param {Object} registry - The registry hostname.
|
* @param {Object} registry - The registry hostname.
|
||||||
*/
|
*/
|
||||||
export const createRegistry = (tree, client, owner, name, registry) => {
|
export const createRegistry = (tree, client, owner, name, registry) => {
|
||||||
const slug = repositorySlug(owner, name);
|
const slug = repositorySlug(owner, name);
|
||||||
|
|
||||||
client
|
client
|
||||||
.createRegistry(owner, name, registry)
|
.createRegistry(owner, name, registry)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
tree.set(["registry", "data", slug, registry.address], result);
|
tree.set(["registry", "data", slug, registry.address], result);
|
||||||
displayMessage(tree, "Successfully stored the registry credentials");
|
displayMessage(tree, "Successfully stored the registry credentials");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to store the registry credentials");
|
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.
|
* @param {Object} registry - The registry hostname.
|
||||||
*/
|
*/
|
||||||
export const deleteRegistry = (tree, client, owner, name, registry) => {
|
export const deleteRegistry = (tree, client, owner, name, registry) => {
|
||||||
const slug = repositorySlug(owner, name);
|
const slug = repositorySlug(owner, name);
|
||||||
|
|
||||||
client
|
client
|
||||||
.deleteRegistry(owner, name, registry)
|
.deleteRegistry(owner, name, registry)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
tree.unset(["registry", "data", slug, registry]);
|
tree.unset(["registry", "data", slug, registry]);
|
||||||
displayMessage(tree, "Successfully deleted the registry credentials");
|
displayMessage(tree, "Successfully deleted the registry credentials");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to delete the registry credentials");
|
displayMessage(tree, "Failed to delete the registry credentials");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,19 +11,19 @@ import { fetchFeed } from "shared/utils/feed";
|
||||||
* @param {string} name - The repository name.
|
* @param {string} name - The repository name.
|
||||||
*/
|
*/
|
||||||
export const fetchRepository = (tree, client, owner, name) => {
|
export const fetchRepository = (tree, client, owner, name) => {
|
||||||
tree.unset(["repo", "error"]);
|
tree.unset(["repo", "error"]);
|
||||||
tree.unset(["repo", "loaded"]);
|
tree.unset(["repo", "loaded"]);
|
||||||
|
|
||||||
client
|
client
|
||||||
.getRepo(owner, name)
|
.getRepo(owner, name)
|
||||||
.then(repo => {
|
.then(repo => {
|
||||||
tree.set(["repos", "data", repo.full_name], repo);
|
tree.set(["repos", "data", repo.full_name], repo);
|
||||||
tree.set(["repo", "loaded"], true);
|
tree.set(["repo", "loaded"], true);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
tree.set(["repo", "error"], error);
|
tree.set(["repo", "error"], error);
|
||||||
tree.set(["repo", "loaded"], true);
|
tree.set(["repo", "loaded"], true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,30 +34,30 @@ export const fetchRepository = (tree, client, owner, name) => {
|
||||||
* @param {Object} client - The drone client.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export const fetchRepostoryList = (tree, client) => {
|
export const fetchRepostoryList = (tree, client) => {
|
||||||
tree.unset(["repos", "loaded"]);
|
tree.unset(["repos", "loaded"]);
|
||||||
tree.unset(["repos", "error"]);
|
tree.unset(["repos", "error"]);
|
||||||
|
|
||||||
client
|
client
|
||||||
.getRepoList({ all: true })
|
.getRepoList({ all: true })
|
||||||
.then(results => {
|
.then(results => {
|
||||||
let list = {};
|
let list = {};
|
||||||
results.map(repo => {
|
results.map(repo => {
|
||||||
list[repo.full_name] = repo;
|
list[repo.full_name] = repo;
|
||||||
});
|
});
|
||||||
|
|
||||||
const path = ["repos", "data"];
|
const path = ["repos", "data"];
|
||||||
if (tree.exists(path)) {
|
if (tree.exists(path)) {
|
||||||
tree.deepMerge(path, list);
|
tree.deepMerge(path, list);
|
||||||
} else {
|
} else {
|
||||||
tree.set(path, list);
|
tree.set(path, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.set(["repos", "loaded"], true);
|
tree.set(["repos", "loaded"], true);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
tree.set(["repos", "loaded"], true);
|
tree.set(["repos", "loaded"], true);
|
||||||
tree.set(["repos", "error"], error);
|
tree.set(["repos", "error"], error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,32 +68,32 @@ export const fetchRepostoryList = (tree, client) => {
|
||||||
* @param {Object} client - The drone client.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export const syncRepostoryList = (tree, client) => {
|
export const syncRepostoryList = (tree, client) => {
|
||||||
tree.unset(["repos", "loaded"]);
|
tree.unset(["repos", "loaded"]);
|
||||||
tree.unset(["repos", "error"]);
|
tree.unset(["repos", "error"]);
|
||||||
|
|
||||||
client
|
client
|
||||||
.getRepoList({ all: true, flush: true })
|
.getRepoList({ all: true, flush: true })
|
||||||
.then(results => {
|
.then(results => {
|
||||||
let list = {};
|
let list = {};
|
||||||
results.map(repo => {
|
results.map(repo => {
|
||||||
list[repo.full_name] = repo;
|
list[repo.full_name] = repo;
|
||||||
});
|
});
|
||||||
|
|
||||||
const path = ["repos", "data"];
|
const path = ["repos", "data"];
|
||||||
if (tree.exists(path)) {
|
if (tree.exists(path)) {
|
||||||
tree.deepMerge(path, list);
|
tree.deepMerge(path, list);
|
||||||
} else {
|
} else {
|
||||||
tree.set(path, list);
|
tree.set(path, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
displayMessage(tree, "Successfully synchronized your repository list");
|
displayMessage(tree, "Successfully synchronized your repository list");
|
||||||
tree.set(["repos", "loaded"], true);
|
tree.set(["repos", "loaded"], true);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
displayMessage(tree, "Failed to synchronize your repository list");
|
displayMessage(tree, "Failed to synchronize your repository list");
|
||||||
tree.set(["repos", "loaded"], true);
|
tree.set(["repos", "loaded"], true);
|
||||||
tree.set(["repos", "error"], error);
|
tree.set(["repos", "error"], error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,15 +107,15 @@ export const syncRepostoryList = (tree, client) => {
|
||||||
* @param {Object} data - The repository updates.
|
* @param {Object} data - The repository updates.
|
||||||
*/
|
*/
|
||||||
export const updateRepository = (tree, client, owner, name, data) => {
|
export const updateRepository = (tree, client, owner, name, data) => {
|
||||||
client
|
client
|
||||||
.updateRepo(owner, name, data)
|
.updateRepo(owner, name, data)
|
||||||
.then(repo => {
|
.then(repo => {
|
||||||
tree.set(["repos", "data", repo.full_name], repo);
|
tree.set(["repos", "data", repo.full_name], repo);
|
||||||
displayMessage(tree, "Successfully updated the repository settings");
|
displayMessage(tree, "Successfully updated the repository settings");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to update the repository settings");
|
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.
|
* @param {string} name - The repository name.
|
||||||
*/
|
*/
|
||||||
export const enableRepository = (tree, client, owner, name) => {
|
export const enableRepository = (tree, client, owner, name) => {
|
||||||
client
|
client
|
||||||
.activateRepo(owner, name)
|
.activateRepo(owner, name)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
displayMessage(tree, "Successfully activated your repository");
|
displayMessage(tree, "Successfully activated your repository");
|
||||||
tree.set(["repos", "data", result.full_name, "active"], true);
|
tree.set(["repos", "data", result.full_name, "active"], true);
|
||||||
fetchFeed(tree, client);
|
fetchFeed(tree, client);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to activate your repository");
|
displayMessage(tree, "Failed to activate your repository");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,16 +150,16 @@ export const enableRepository = (tree, client, owner, name) => {
|
||||||
* @param {string} name - The repository name.
|
* @param {string} name - The repository name.
|
||||||
*/
|
*/
|
||||||
export const disableRepository = (tree, client, owner, name) => {
|
export const disableRepository = (tree, client, owner, name) => {
|
||||||
client
|
client
|
||||||
.deleteRepo(owner, name)
|
.deleteRepo(owner, name)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
displayMessage(tree, "Successfully disabled your repository");
|
displayMessage(tree, "Successfully disabled your repository");
|
||||||
tree.set(["repos", "data", result.full_name, "active"], false);
|
tree.set(["repos", "data", result.full_name, "active"], false);
|
||||||
fetchFeed(tree, client);
|
fetchFeed(tree, client);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to disabled your repository");
|
displayMessage(tree, "Failed to disabled your repository");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,9 +170,9 @@ export const disableRepository = (tree, client, owner, name) => {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export const compareRepository = (a, b) => {
|
export const compareRepository = (a, b) => {
|
||||||
if (a.full_name < b.full_name) return -1;
|
if (a.full_name < b.full_name) return -1;
|
||||||
if (a.full_name > b.full_name) return 1;
|
if (a.full_name > b.full_name) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -182,5 +182,5 @@ export const compareRepository = (a, b) => {
|
||||||
* @param {string} name - The process name.
|
* @param {string} name - The process name.
|
||||||
*/
|
*/
|
||||||
export const repositorySlug = (owner, 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.
|
* @param {string} name - The repository name.
|
||||||
*/
|
*/
|
||||||
export const fetchSecretList = (tree, client, owner, 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", "loaded"]);
|
||||||
tree.unset(["secrets", "error"]);
|
tree.unset(["secrets", "error"]);
|
||||||
|
|
||||||
client.getSecretList(owner, name).then(results => {
|
client.getSecretList(owner, name).then(results => {
|
||||||
let list = {};
|
let list = {};
|
||||||
results.map(secret => {
|
results.map(secret => {
|
||||||
list[secret.name] = secret;
|
list[secret.name] = secret;
|
||||||
});
|
});
|
||||||
tree.set(["secrets", "data", slug], list);
|
tree.set(["secrets", "data", slug], list);
|
||||||
tree.set(["secrets", "loaded"], true);
|
tree.set(["secrets", "loaded"], true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,17 +37,17 @@ export const fetchSecretList = (tree, client, owner, name) => {
|
||||||
* @param {Object} secret - The secret object.
|
* @param {Object} secret - The secret object.
|
||||||
*/
|
*/
|
||||||
export const createSecret = (tree, client, owner, name, secret) => {
|
export const createSecret = (tree, client, owner, name, secret) => {
|
||||||
const slug = repositorySlug(owner, name);
|
const slug = repositorySlug(owner, name);
|
||||||
|
|
||||||
client
|
client
|
||||||
.createSecret(owner, name, secret)
|
.createSecret(owner, name, secret)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
tree.set(["secrets", "data", slug, secret.name], result);
|
tree.set(["secrets", "data", slug, secret.name], result);
|
||||||
displayMessage(tree, "Successfully added the secret");
|
displayMessage(tree, "Successfully added the secret");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to create the secret");
|
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.
|
* @param {string} secret - The secret name.
|
||||||
*/
|
*/
|
||||||
export const deleteSecret = (tree, client, owner, name, secret) => {
|
export const deleteSecret = (tree, client, owner, name, secret) => {
|
||||||
const slug = repositorySlug(owner, name);
|
const slug = repositorySlug(owner, name);
|
||||||
|
|
||||||
client
|
client
|
||||||
.deleteSecret(owner, name, secret)
|
.deleteSecret(owner, name, secret)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
tree.unset(["secrets", "data", slug, secret]);
|
tree.unset(["secrets", "data", slug, secret]);
|
||||||
displayMessage(tree, "Successfully removed the secret");
|
displayMessage(tree, "Successfully removed the secret");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to remove the secret");
|
displayMessage(tree, "Failed to remove the secret");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import { displayMessage } from "./message";
|
import { displayMessage } from "./message";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a personal access token and stores the results in
|
* Generates a personal access token and stores the results in
|
||||||
* the state tree.
|
* the state tree.
|
||||||
*
|
*
|
||||||
* @param {Object} tree - The drone state tree.
|
* @param {Object} tree - The drone state tree.
|
||||||
* @param {Object} client - The drone client.
|
* @param {Object} client - The drone client.
|
||||||
*/
|
*/
|
||||||
export const generateToken = (tree, client) => {
|
export const generateToken = (tree, client) => {
|
||||||
client
|
client
|
||||||
.getToken()
|
.getToken()
|
||||||
.then(token => {
|
.then(token => {
|
||||||
tree.set(["token"], token);
|
tree.set(["token"], token);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
displayMessage(tree, "Failed to retrieve your personal access token");
|
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) {
|
(function(global, factory) {
|
||||||
if (typeof define === "function" && define.amd) {
|
if (typeof define === "function" && define.amd) {
|
||||||
define(["exports"], factory);
|
define(["exports"], factory);
|
||||||
} else if (typeof exports !== "undefined") {
|
} else if (typeof exports !== "undefined") {
|
||||||
factory(exports);
|
factory(exports);
|
||||||
} else {
|
} else {
|
||||||
var mod = {
|
var mod = {
|
||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
factory(mod.exports);
|
factory(mod.exports);
|
||||||
global.index = mod.exports;
|
global.index = mod.exports;
|
||||||
}
|
}
|
||||||
})(this, function (exports) {
|
})(this, function(exports) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
Object.defineProperty(exports, "__esModule", {
|
||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) {
|
function _classCallCheck(instance, Constructor) {
|
||||||
if (!(instance instanceof Constructor)) {
|
if (!(instance instanceof Constructor)) {
|
||||||
throw new TypeError("Cannot call a class as a function");
|
throw new TypeError("Cannot call a class as a function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _createClass = function () {
|
var _createClass = (function() {
|
||||||
function defineProperties(target, props) {
|
function defineProperties(target, props) {
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
var descriptor = props[i];
|
var descriptor = props[i];
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
descriptor.enumerable = descriptor.enumerable || false;
|
||||||
descriptor.configurable = true;
|
descriptor.configurable = true;
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
if ("value" in descriptor) descriptor.writable = true;
|
||||||
Object.defineProperty(target, descriptor.key, descriptor);
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
return function(Constructor, protoProps, staticProps) {
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||||||
return Constructor;
|
return Constructor;
|
||||||
};
|
};
|
||||||
}();
|
})();
|
||||||
|
|
||||||
var DroneClient = function () {
|
var DroneClient = (function() {
|
||||||
function DroneClient(server, token, csrf) {
|
function DroneClient(server, token, csrf) {
|
||||||
_classCallCheck(this, DroneClient);
|
_classCallCheck(this, DroneClient);
|
||||||
|
|
||||||
this.server = server || "";
|
this.server = server || "";
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.csrf = csrf;
|
this.csrf = csrf;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(DroneClient, [{
|
_createClass(
|
||||||
key: "getRepoList",
|
DroneClient,
|
||||||
value: function getRepoList(opts) {
|
[
|
||||||
var query = encodeQueryString(opts);
|
{
|
||||||
return this._get("/api/user/repos?" + query);
|
key: "getRepoList",
|
||||||
}
|
value: function getRepoList(opts) {
|
||||||
}, {
|
var query = encodeQueryString(opts);
|
||||||
key: "getRepo",
|
return this._get("/api/user/repos?" + query);
|
||||||
value: function getRepo(owner, repo) {
|
}
|
||||||
return this._get("/api/repos/" + owner + "/" + repo);
|
},
|
||||||
}
|
{
|
||||||
}, {
|
key: "getRepo",
|
||||||
key: "activateRepo",
|
value: function getRepo(owner, repo) {
|
||||||
value: function activateRepo(owner, repo) {
|
return this._get("/api/repos/" + owner + "/" + repo);
|
||||||
return this._post("/api/repos/" + owner + "/" + repo);
|
}
|
||||||
}
|
},
|
||||||
}, {
|
{
|
||||||
key: "updateRepo",
|
key: "activateRepo",
|
||||||
value: function updateRepo(owner, repo, data) {
|
value: function activateRepo(owner, repo) {
|
||||||
return this._patch("/api/repos/" + owner + "/" + repo, data);
|
return this._post("/api/repos/" + owner + "/" + repo);
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
key: "deleteRepo",
|
{
|
||||||
value: function deleteRepo(owner, repo) {
|
key: "updateRepo",
|
||||||
return this._delete("/api/repos/" + owner + "/" + repo);
|
value: function updateRepo(owner, repo, data) {
|
||||||
}
|
return this._patch("/api/repos/" + owner + "/" + repo, data);
|
||||||
}, {
|
}
|
||||||
key: "getBuildList",
|
},
|
||||||
value: function getBuildList(owner, repo, opts) {
|
{
|
||||||
var query = encodeQueryString(opts);
|
key: "deleteRepo",
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/builds?" + query);
|
value: function deleteRepo(owner, repo) {
|
||||||
}
|
return this._delete("/api/repos/" + owner + "/" + repo);
|
||||||
}, {
|
}
|
||||||
key: "getBuild",
|
},
|
||||||
value: function getBuild(owner, repo, number) {
|
{
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/builds/" + number);
|
key: "getBuildList",
|
||||||
}
|
value: function getBuildList(owner, repo, opts) {
|
||||||
}, {
|
var query = encodeQueryString(opts);
|
||||||
key: "getBuildFeed",
|
return this._get(
|
||||||
value: function getBuildFeed(opts) {
|
"/api/repos/" + owner + "/" + repo + "/builds?" + query
|
||||||
var query = encodeQueryString(opts);
|
);
|
||||||
return this._get("/api/user/feed?" + query);
|
}
|
||||||
}
|
},
|
||||||
}, {
|
{
|
||||||
key: "cancelBuild",
|
key: "getBuild",
|
||||||
value: function cancelBuild(owner, repo, number, ppid) {
|
value: function getBuild(owner, repo, number) {
|
||||||
return this._delete("/api/repos/" + owner + "/" + repo + "/builds/" + number + "/" + ppid);
|
return this._get(
|
||||||
}
|
"/api/repos/" + owner + "/" + repo + "/builds/" + number
|
||||||
}, {
|
);
|
||||||
key: "approveBuild",
|
}
|
||||||
value: function approveBuild(owner, repo, build) {
|
},
|
||||||
return this._post("/api/repos/" + owner + "/" + repo + "/builds/" + build + "/approve");
|
{
|
||||||
}
|
key: "getBuildFeed",
|
||||||
}, {
|
value: function getBuildFeed(opts) {
|
||||||
key: "declineBuild",
|
var query = encodeQueryString(opts);
|
||||||
value: function declineBuild(owner, repo, build) {
|
return this._get("/api/user/feed?" + query);
|
||||||
return this._post("/api/repos/" + owner + "/" + repo + "/builds/" + build + "/decline");
|
}
|
||||||
}
|
},
|
||||||
}, {
|
{
|
||||||
key: "restartBuild",
|
key: "cancelBuild",
|
||||||
value: function restartBuild(owner, repo, build, opts) {
|
value: function cancelBuild(owner, repo, number, ppid) {
|
||||||
var query = encodeQueryString(opts);
|
return this._delete(
|
||||||
return this._post("/api/repos/" + owner + "/" + repo + "/builds/" + build + "?" + query);
|
"/api/repos/" +
|
||||||
}
|
owner +
|
||||||
}, {
|
"/" +
|
||||||
key: "getLogs",
|
repo +
|
||||||
value: function getLogs(owner, repo, build, proc) {
|
"/builds/" +
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/logs/" + build + "/" + proc);
|
number +
|
||||||
}
|
"/" +
|
||||||
}, {
|
ppid
|
||||||
key: "getArtifact",
|
);
|
||||||
value: function getArtifact(owner, repo, build, proc, file) {
|
}
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/files/" + build + "/" + proc + "/" + file + "?raw=true");
|
},
|
||||||
}
|
{
|
||||||
}, {
|
key: "approveBuild",
|
||||||
key: "getArtifactList",
|
value: function approveBuild(owner, repo, build) {
|
||||||
value: function getArtifactList(owner, repo, build) {
|
return this._post(
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/files/" + build);
|
"/api/repos/" +
|
||||||
}
|
owner +
|
||||||
}, {
|
"/" +
|
||||||
key: "getSecretList",
|
repo +
|
||||||
value: function getSecretList(owner, repo) {
|
"/builds/" +
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/secrets");
|
build +
|
||||||
}
|
"/approve"
|
||||||
}, {
|
);
|
||||||
key: "createSecret",
|
}
|
||||||
value: function createSecret(owner, repo, secret) {
|
},
|
||||||
return this._post("/api/repos/" + owner + "/" + repo + "/secrets", secret);
|
{
|
||||||
}
|
key: "declineBuild",
|
||||||
}, {
|
value: function declineBuild(owner, repo, build) {
|
||||||
key: "deleteSecret",
|
return this._post(
|
||||||
value: function deleteSecret(owner, repo, secret) {
|
"/api/repos/" +
|
||||||
return this._delete("/api/repos/" + owner + "/" + repo + "/secrets/" + secret);
|
owner +
|
||||||
}
|
"/" +
|
||||||
}, {
|
repo +
|
||||||
key: "getRegistryList",
|
"/builds/" +
|
||||||
value: function getRegistryList(owner, repo) {
|
build +
|
||||||
return this._get("/api/repos/" + owner + "/" + repo + "/registry");
|
"/decline"
|
||||||
}
|
);
|
||||||
}, {
|
}
|
||||||
key: "createRegistry",
|
},
|
||||||
value: function createRegistry(owner, repo, registry) {
|
{
|
||||||
return this._post("/api/repos/" + owner + "/" + repo + "/registry", registry);
|
key: "restartBuild",
|
||||||
}
|
value: function restartBuild(owner, repo, build, opts) {
|
||||||
}, {
|
var query = encodeQueryString(opts);
|
||||||
key: "deleteRegistry",
|
return this._post(
|
||||||
value: function deleteRegistry(owner, repo, address) {
|
"/api/repos/" +
|
||||||
return this._delete("/api/repos/" + owner + "/" + repo + "/registry/" + address);
|
owner +
|
||||||
}
|
"/" +
|
||||||
}, {
|
repo +
|
||||||
key: "getSelf",
|
"/builds/" +
|
||||||
value: function getSelf() {
|
build +
|
||||||
return this._get("/api/user");
|
"?" +
|
||||||
}
|
query
|
||||||
}, {
|
);
|
||||||
key: "getToken",
|
}
|
||||||
value: function getToken() {
|
},
|
||||||
return this._post("/api/user/token");
|
{
|
||||||
}
|
key: "getLogs",
|
||||||
}, {
|
value: function getLogs(owner, repo, build, proc) {
|
||||||
key: "on",
|
return this._get(
|
||||||
value: function on(callback) {
|
"/api/repos/" + owner + "/" + repo + "/logs/" + build + "/" + proc
|
||||||
return this._subscribe("/stream/events", callback, {
|
);
|
||||||
reconnect: true
|
}
|
||||||
});
|
},
|
||||||
}
|
{
|
||||||
}, {
|
key: "getArtifact",
|
||||||
key: "stream",
|
value: function getArtifact(owner, repo, build, proc, file) {
|
||||||
value: function stream(owner, repo, build, proc, callback) {
|
return this._get(
|
||||||
return this._subscribe("/stream/logs/" + owner + "/" + repo + "/" + build + "/" + proc, callback, {
|
"/api/repos/" +
|
||||||
reconnect: false
|
owner +
|
||||||
});
|
"/" +
|
||||||
}
|
repo +
|
||||||
}, {
|
"/files/" +
|
||||||
key: "_get",
|
build +
|
||||||
value: function _get(path) {
|
"/" +
|
||||||
return this._request("GET", path, null);
|
proc +
|
||||||
}
|
"/" +
|
||||||
}, {
|
file +
|
||||||
key: "_post",
|
"?raw=true"
|
||||||
value: function _post(path, data) {
|
);
|
||||||
return this._request("POST", path, data);
|
}
|
||||||
}
|
},
|
||||||
}, {
|
{
|
||||||
key: "_patch",
|
key: "getArtifactList",
|
||||||
value: function _patch(path, data) {
|
value: function getArtifactList(owner, repo, build) {
|
||||||
return this._request("PATCH", path, data);
|
return this._get(
|
||||||
}
|
"/api/repos/" + owner + "/" + repo + "/files/" + build
|
||||||
}, {
|
);
|
||||||
key: "_delete",
|
}
|
||||||
value: function _delete(path) {
|
},
|
||||||
return this._request("DELETE", path, null);
|
{
|
||||||
}
|
key: "getSecretList",
|
||||||
}, {
|
value: function getSecretList(owner, repo) {
|
||||||
key: "_subscribe",
|
return this._get("/api/repos/" + owner + "/" + repo + "/secrets");
|
||||||
value: function _subscribe(path, callback, opts) {
|
}
|
||||||
var query = encodeQueryString({
|
},
|
||||||
access_token: this.token
|
{
|
||||||
});
|
key: "createSecret",
|
||||||
path = this.server ? this.server + path : path;
|
value: function createSecret(owner, repo, secret) {
|
||||||
path = this.token ? path + "?" + query : path;
|
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);
|
var events = new EventSource(path);
|
||||||
events.onmessage = function (event) {
|
events.onmessage = function(event) {
|
||||||
var data = JSON.parse(event.data);
|
var data = JSON.parse(event.data);
|
||||||
callback(data);
|
callback(data);
|
||||||
};
|
};
|
||||||
if (!opts.reconnect) {
|
if (!opts.reconnect) {
|
||||||
events.onerror = function (err) {
|
events.onerror = function(err) {
|
||||||
if (err.data === "eof") {
|
if (err.data === "eof") {
|
||||||
events.close();
|
events.close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
key: "_request",
|
{
|
||||||
value: function _request(method, path, data) {
|
key: "_request",
|
||||||
var endpoint = [this.server, path].join("");
|
value: function _request(method, path, data) {
|
||||||
var xhr = new XMLHttpRequest();
|
var endpoint = [this.server, path].join("");
|
||||||
xhr.open(method, endpoint, true);
|
var xhr = new XMLHttpRequest();
|
||||||
if (this.token) {
|
xhr.open(method, endpoint, true);
|
||||||
xhr.setRequestHeader("Authorization", "Bearer " + this.token);
|
if (this.token) {
|
||||||
}
|
xhr.setRequestHeader("Authorization", "Bearer " + this.token);
|
||||||
if (method !== "GET" && this.csrf) {
|
}
|
||||||
xhr.setRequestHeader("X-CSRF-TOKEN", this.csrf);
|
if (method !== "GET" && this.csrf) {
|
||||||
}
|
xhr.setRequestHeader("X-CSRF-TOKEN", this.csrf);
|
||||||
return new Promise(function (resolve, reject) {
|
}
|
||||||
xhr.onload = function () {
|
return new Promise(
|
||||||
if (xhr.readyState === 4) {
|
function(resolve, reject) {
|
||||||
if (xhr.status >= 300) {
|
xhr.onload = function() {
|
||||||
var error = {
|
if (xhr.readyState === 4) {
|
||||||
status: xhr.status,
|
if (xhr.status >= 300) {
|
||||||
message: xhr.response
|
var error = {
|
||||||
};
|
status: xhr.status,
|
||||||
if (this.onerror) {
|
message: xhr.response
|
||||||
this.onerror(error);
|
};
|
||||||
}
|
if (this.onerror) {
|
||||||
reject(error);
|
this.onerror(error);
|
||||||
return;
|
}
|
||||||
}
|
reject(error);
|
||||||
var contentType = xhr.getResponseHeader("Content-Type");
|
return;
|
||||||
if (contentType && contentType.startsWith("application/json")) {
|
}
|
||||||
resolve(JSON.parse(xhr.response));
|
var contentType = xhr.getResponseHeader("Content-Type");
|
||||||
} else {
|
if (
|
||||||
resolve(xhr.response);
|
contentType &&
|
||||||
}
|
contentType.startsWith("application/json")
|
||||||
}
|
) {
|
||||||
}.bind(this);
|
resolve(JSON.parse(xhr.response));
|
||||||
xhr.onerror = function (e) {
|
} else {
|
||||||
reject(e);
|
resolve(xhr.response);
|
||||||
};
|
}
|
||||||
if (data) {
|
}
|
||||||
xhr.setRequestHeader("Content-Type", "application/json");
|
}.bind(this);
|
||||||
xhr.send(JSON.stringify(data));
|
xhr.onerror = function(e) {
|
||||||
} else {
|
reject(e);
|
||||||
xhr.send();
|
};
|
||||||
}
|
if (data) {
|
||||||
}.bind(this));
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
}
|
xhr.send(JSON.stringify(data));
|
||||||
}], [{
|
} else {
|
||||||
key: "fromEnviron",
|
xhr.send();
|
||||||
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);
|
}.bind(this)
|
||||||
}
|
);
|
||||||
}, {
|
}
|
||||||
key: "fromWindow",
|
}
|
||||||
value: function fromWindow() {
|
],
|
||||||
return new DroneClient(window && window.DRONE_SERVER, window && window.DRONE_TOKEN, window && window.DRONE_CSRF);
|
[
|
||||||
}
|
{
|
||||||
}]);
|
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] : {};
|
||||||
|
|
||||||
/**
|
return params
|
||||||
* Encodes the values into url encoded form sorted by key.
|
? Object.keys(params)
|
||||||
*
|
.sort()
|
||||||
* @param {object} query parameters in key value object.
|
.map(function(key) {
|
||||||
* @return {string} query parameter string
|
var val = params[key];
|
||||||
*/
|
return encodeURIComponent(key) + "=" + encodeURIComponent(val);
|
||||||
var encodeQueryString = exports.encodeQueryString = function encodeQueryString() {
|
})
|
||||||
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
.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";
|
const ENV = process.env.NODE_ENV || "development";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
app: "./src",
|
app: "./src",
|
||||||
vendor: [
|
vendor: [
|
||||||
"ansi_up",
|
"ansi_up",
|
||||||
"babel-polyfill",
|
"babel-polyfill",
|
||||||
"baobab",
|
"baobab",
|
||||||
"baobab-react",
|
"baobab-react",
|
||||||
"classnames",
|
"classnames",
|
||||||
"drone-js",
|
"drone-js",
|
||||||
"humanize-duration",
|
"humanize-duration",
|
||||||
"preact",
|
"preact",
|
||||||
"preact-compat",
|
"preact-compat",
|
||||||
"query-string",
|
"query-string",
|
||||||
"react-router",
|
"react-router",
|
||||||
"react-router-dom",
|
"react-router-dom",
|
||||||
"react-screen-size",
|
"react-screen-size",
|
||||||
"react-timeago",
|
"react-timeago",
|
||||||
"react-title-component",
|
"react-title-component",
|
||||||
"react-transition-group"
|
"react-transition-group"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
// where to dump the output of a production build
|
// where to dump the output of a production build
|
||||||
output: {
|
output: {
|
||||||
publicPath: "/",
|
publicPath: "/",
|
||||||
path: path.join(__dirname, "dist/files"),
|
path: path.join(__dirname, "dist/files"),
|
||||||
filename: "static/bundle.[chunkhash].js"
|
filename: "static/bundle.[chunkhash].js"
|
||||||
},
|
},
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
client: path.resolve(__dirname, "src/client/"),
|
client: path.resolve(__dirname, "src/client/"),
|
||||||
config: path.resolve(__dirname, "src/config/"),
|
config: path.resolve(__dirname, "src/config/"),
|
||||||
components: path.resolve(__dirname, "src/components/"),
|
components: path.resolve(__dirname, "src/components/"),
|
||||||
layouts: path.resolve(__dirname, "src/layouts/"),
|
layouts: path.resolve(__dirname, "src/layouts/"),
|
||||||
pages: path.resolve(__dirname, "src/pages/"),
|
pages: path.resolve(__dirname, "src/pages/"),
|
||||||
screens: path.resolve(__dirname, "src/screens/"),
|
screens: path.resolve(__dirname, "src/screens/"),
|
||||||
shared: path.resolve(__dirname, "src/shared/"),
|
shared: path.resolve(__dirname, "src/shared/"),
|
||||||
|
|
||||||
react: "preact-compat/dist/preact-compat",
|
react: "preact-compat/dist/preact-compat",
|
||||||
"react-dom": "preact-compat/dist/preact-compat",
|
"react-dom": "preact-compat/dist/preact-compat",
|
||||||
"create-react-class": "preact-compat/lib/create-react-class"
|
"create-react-class": "preact-compat/lib/create-react-class"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.jsx?/i,
|
test: /\.jsx?/i,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: "babel-loader"
|
loader: "babel-loader"
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
test: /\.(less|css)$/,
|
test: /\.(less|css)$/,
|
||||||
loader: "style-loader"
|
loader: "style-loader"
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
test: /\.(less|css)$/,
|
test: /\.(less|css)$/,
|
||||||
loader: "css-loader",
|
loader: "css-loader",
|
||||||
query: {
|
query: {
|
||||||
modules: true,
|
modules: true,
|
||||||
localIdentName: "[name]__[local]___[hash:base64:5]"
|
localIdentName: "[name]__[local]___[hash:base64:5]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
test: /\.(less|css)$/,
|
test: /\.(less|css)$/,
|
||||||
loader: "less-loader"
|
loader: "less-loader"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
new webpack.optimize.CommonsChunkPlugin({
|
||||||
name: "vendor",
|
name: "vendor",
|
||||||
filename: "static/vendor.[hash].js"
|
filename: "static/vendor.[hash].js"
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
favicon: "src/public/favicon.svg",
|
favicon: "src/public/favicon.svg",
|
||||||
template: "src/index.html"
|
template: "src/index.html"
|
||||||
})
|
})
|
||||||
].concat(
|
].concat(
|
||||||
ENV === "production"
|
ENV === "production"
|
||||||
? [
|
? [
|
||||||
new webpack.optimize.UglifyJsPlugin({
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
output: {
|
output: {
|
||||||
comments: false
|
comments: false
|
||||||
},
|
},
|
||||||
exclude: [/bundle/],
|
exclude: [/bundle/],
|
||||||
compress: {
|
compress: {
|
||||||
unsafe_comps: true,
|
unsafe_comps: true,
|
||||||
properties: true,
|
properties: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
pure_getters: true,
|
pure_getters: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
warnings: false,
|
warnings: false,
|
||||||
screw_ie8: true,
|
screw_ie8: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
drop_debugger: true,
|
drop_debugger: true,
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
booleans: true,
|
booleans: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
hoist_funs: true,
|
hoist_funs: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
drop_console: true
|
drop_console: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
// drone server uses authorization cookies, but the client can
|
// drone server uses authorization cookies, but the client can
|
||||||
// optionally source the authorization token from the environment.
|
// optionally source the authorization token from the environment.
|
||||||
// this should be used for the test server only.
|
// this should be used for the test server only.
|
||||||
"window.DRONE_TOKEN": JSON.stringify(process.env.DRONE_TOKEN),
|
"window.DRONE_TOKEN": JSON.stringify(process.env.DRONE_TOKEN),
|
||||||
"window.DRONE_SERVER": JSON.stringify(process.env.DRONE_SERVER),
|
"window.DRONE_SERVER": JSON.stringify(process.env.DRONE_SERVER),
|
||||||
|
|
||||||
// drone server provides the currently authenticated user in the
|
// drone server provides the currently authenticated user in the
|
||||||
// index.html file. For testing purposes we simulate this and provides
|
// index.html file. For testing purposes we simulate this and provides
|
||||||
// a dummy user object.
|
// a dummy user object.
|
||||||
"window.DRONE_USER": {
|
"window.DRONE_USER": {
|
||||||
login: JSON.stringify("octocat"),
|
login: JSON.stringify("octocat"),
|
||||||
avatar_url: JSON.stringify(
|
avatar_url: JSON.stringify(
|
||||||
"https://avatars3.githubusercontent.com/u/583231"
|
"https://avatars3.githubusercontent.com/u/583231"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|
||||||
devServer: {
|
devServer: {
|
||||||
port: process.env.PORT || 9999,
|
port: process.env.PORT || 9999,
|
||||||
|
|
||||||
// serve up any static files from src/
|
// serve up any static files from src/
|
||||||
contentBase: path.join(__dirname, "src"),
|
contentBase: path.join(__dirname, "src"),
|
||||||
|
|
||||||
// enable gzip compression:
|
// enable gzip compression:
|
||||||
compress: true,
|
compress: true,
|
||||||
|
|
||||||
// enable pushState() routing, as used by preact-router et al:
|
// enable pushState() routing, as used by preact-router et al:
|
||||||
historyApiFallback: true
|
historyApiFallback: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue