blueocean-plugin/blueocean-personalization/src/main/js/components/DashboardCards.jsx

199 lines
6.3 KiB
JavaScript

/**
* Created by cmeyers on 7/6/16.
*/
import React, { Component, PropTypes } from 'react';
import TransitionGroup from 'react-addons-css-transition-group';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { List } from 'immutable';
import { favoritesSelector } from '../redux/FavoritesStore';
import { actions } from '../redux/FavoritesActions';
import FavoritesProvider from './FavoritesProvider';
import { PipelineCard } from './PipelineCard';
// the order the cards should be displayed based on their result/state (aka 'status')
const statusSortOrder = [
'UNKNOWN', 'FAILURE', 'ABORTED', 'NOT_BUILT',
'UNSTABLE', 'RUNNING', 'QUEUED', 'SUCCESS',
];
const extractStatus = (favorite) => {
const latestRun = favorite && favorite.item && favorite.item.latestRun || {};
return latestRun.result === 'UNKNOWN' ? latestRun.state : latestRun.result;
};
// sorts the cards based on 1. status 2. endTime, startTime or enQueueTime (descending)
const sortComparator = (favoriteA, favoriteB) => {
const statusA = extractStatus(favoriteA);
const statusB = extractStatus(favoriteB);
const orderA = statusSortOrder.indexOf(statusA);
const orderB = statusSortOrder.indexOf(statusB);
if (orderA < orderB) {
return -1;
} else if (orderA > orderB) {
return 1;
}
const endTimeA = favoriteA && favoriteA.item && favoriteA.item.latestRun && favoriteA.item.latestRun.endTime;
const endTimeB = favoriteB && favoriteB.item && favoriteB.item.latestRun && favoriteB.item.latestRun.endTime;
if (endTimeA && endTimeB) {
const endCompare = endTimeA.localeCompare(endTimeB);
if (endCompare !== 0) {
return -endCompare;
}
}
const startTimeA = favoriteA && favoriteA.item && favoriteA.item.latestRun && favoriteA.item.latestRun.startTime;
const startTimeB = favoriteB && favoriteB.item && favoriteB.item.latestRun && favoriteB.item.latestRun.startTime;
if (startTimeA && startTimeB) {
const startCompare = startTimeA.localeCompare(startTimeB);
if (startCompare !== 0) {
return -startCompare;
}
}
const queuedTimeA = favoriteA && favoriteA.item && favoriteA.item.latestRun && favoriteA.item.latestRun.enQueueTime;
const queuedTimeB = favoriteB && favoriteB.item && favoriteB.item.latestRun && favoriteB.item.latestRun.enQueueTime;
if (queuedTimeA && queuedTimeB) {
const queueCompare = queuedTimeA.localeCompare(queuedTimeB);
if (queueCompare !== 0) {
return -queueCompare;
}
}
return 0;
};
/**
* Extract elements from a path string deliminted with forward slashes
* @param path
* @param begin
* @param end
* @returns {string}
*/
const extractPath = (path, begin, end) => {
try {
return path.split('/').slice(begin, end).join('/');
} catch (error) {
return path;
}
};
/**
*/
export class DashboardCards extends Component {
_onFavoriteToggle(isFavorite, favorite) {
this.props.toggleFavorite(isFavorite, favorite.item, favorite);
}
_renderCardStack() {
if (!this.props.favorites) {
return null;
}
const sortedFavorites = this.props.favorites.sort(sortComparator);
const favoriteCards = sortedFavorites.map(favorite => {
const pipeline = favorite.item;
const latestRun = pipeline.latestRun;
let fullName;
let pipelineName;
let branchName;
if (pipeline._class === 'io.jenkins.blueocean.rest.impl.pipeline.BranchImpl') {
// branch.fullName is in the form folder1/folder2/pipeline/branch ...
// "pipeline"
pipelineName = extractPath(pipeline.fullName, -2, -1);
// everything up to "branch"
fullName = extractPath(pipeline.fullName, 0, -1);
branchName = pipeline.name;
} else {
pipelineName = pipeline.name;
fullName = pipeline.fullName;
}
let status = null;
let startTime = null;
let estimatedDuration = null;
let commitId = null;
let runId = null;
if (latestRun) {
if (latestRun.result) {
status = latestRun.result === 'UNKNOWN' ? latestRun.state : latestRun.result;
}
startTime = latestRun.startTime;
estimatedDuration = latestRun.estimatedDurationInMillis;
commitId = latestRun.commitId;
runId = latestRun.id;
}
if (latestRun && latestRun.result) {
status = latestRun.result === 'UNKNOWN' ? latestRun.state : latestRun.result;
}
return (
<div key={favorite._links.self.href}>
<PipelineCard
status={status}
startTime={startTime}
estimatedDuration={estimatedDuration}
fullName={fullName}
organization={pipeline.organization}
pipeline={pipelineName}
branch={branchName}
commitId={commitId}
runId={runId}
favorite
onFavoriteToggle={(isFavorite) => this._onFavoriteToggle(isFavorite, favorite)}
/>
</div>
);
});
return (
<div className="favorites-card-stack">
<TransitionGroup transitionName="vertical-expand-collapse"
transitionEnterTimeout={150}
transitionLeaveTimeout={150}
>
{favoriteCards}
</TransitionGroup>
</div>
);
}
render() {
return (
<FavoritesProvider store={this.props.store}>
{ this._renderCardStack() }
</FavoritesProvider>
);
}
}
DashboardCards.propTypes = {
store: PropTypes.object,
favorites: PropTypes.instanceOf(List),
toggleFavorite: PropTypes.func,
};
const selectors = createSelector(
[favoritesSelector],
(favorites) => ({ favorites })
);
export default connect(selectors, actions)(DashboardCards);