Skip to content

Commit

Permalink
Add volumes functionality
Browse files Browse the repository at this point in the history
Now the volumes are filled with real data from the app.tasks.
volumes now have a detail view.
  • Loading branch information
Philipp Hinrichsen committed Feb 24, 2016
1 parent 2223e9a commit 48e565a
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 50 deletions.
88 changes: 84 additions & 4 deletions src/js/components/AppPageComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ var AppPageComponent = React.createClass({

var appId = decodeURIComponent(params.appId);
var view = params.view;
var volumeId = params.volumeId;

var activeTabId = `apps/${encodeURIComponent(appId)}`;

Expand All @@ -82,6 +83,8 @@ var AppPageComponent = React.createClass({
activeTabId += "/debug";
} else if (view === "volumes") {
activeTabId += "/volumes";
} else if (volumeId != null) {
activeViewIndex = 2;
} else if (view != null) {
activeTaskId = view;
activeViewIndex = 1;
Expand All @@ -92,6 +95,7 @@ var AppPageComponent = React.createClass({
activeTaskId: activeTaskId,
activeViewIndex: activeViewIndex,
app: app,
volumeId: volumeId,
appId: appId,
view: decodeURIComponent(params.view),
tabs: tabs
Expand Down Expand Up @@ -277,12 +281,85 @@ var AppPageComponent = React.createClass({
);
},

getVolumeDetails: function () {
var {app, volumeId} = this.state;
var tasks = app.tasks;

var volume = tasks
// Get the first volume from a task with the same id as provided
// by the router. This should be unique.
.reduce((memo, task) => {
return task.localVolumes
.filter(volume => volume.persistenceId === volumeId)
.reduce((memo, volume) => {
if (memo != null) {
return memo;
}
volume.taskId = task.id;
return volume;
}, null);
}, null);

if (volume == null) {
return null;
}

if (app.container != null && app.container.volumes != null) {
app.container.volumes.forEach(function (volumeConfig) {
if (volumeConfig.containerPath &&
volumeConfig.containerPath === volume.containerPath) {
Object.keys(volumeConfig).forEach(key =>
volume[key] = volumeConfig[key]
);
}
});
}

return (
<dl className={"dl-horizontal"}>
<dt>ID</dt>
<dd>{volume.persistenceId}</dd>
<dt>Container Path</dt>
<dd>{volume.containerPath}</dd>
<dt>Mode</dt>
<dd>{volume.mode}</dd>
<dt>Size</dt>
<dd>{volume.persistent.size}</dd>
<dt>Task Id</dt>
<dd>{volume.taskId}</dd>
</dl>
);
},

getAppDetails: function () {
var state = this.state;
var model = state.app;
var volumes = model.container != null
? model.container.volumes
: null;

var volumes = model.tasks.reduce((memo, task) => {
if (task.localVolumes != null) {
return memo.concat(task.localVolumes.map(volume => {
volume.taskId = task.id;
return volume;
}));
}
return memo;
}, [])
.map(volume => {
if (model.container == null || model.container.volumes == null) {
return null;
}
model.container.volumes.forEach(function (volumeConfig) {
if (volumeConfig.containerPath &&
volumeConfig.containerPath === volume.containerPath) {
Object.keys(volumeConfig).forEach(key =>
volume[key] = volumeConfig[key]
);
volume.appId = model.id;
}
});
return volume;
})
.filter(volume => volume != null);

var tabs = state.tabs.filter(tab =>
tab.text !== "Volumes" ||
Expand Down Expand Up @@ -327,6 +404,8 @@ var AppPageComponent = React.createClass({
content = this.getAppDetails();
} else if (this.state.activeViewIndex === 1) {
content = this.getTaskDetailComponent();
} else if (this.state.activeViewIndex === 2) {
content = this.getVolumeDetails();
}

var groupId = PathUtil.getGroupFromAppId(state.appId);
Expand All @@ -336,7 +415,8 @@ var AppPageComponent = React.createClass({
<div>
<BreadcrumbComponent groupId={groupId}
appId={state.appId}
taskId={state.activeTaskId} />
taskId={state.activeTaskId}
volumeId={state.volumeId} />
<div className="container-fluid">
<div className="page-header">
<h1>{name}</h1>
Expand Down
10 changes: 9 additions & 1 deletion src/js/components/AppVolumesListItemComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import classNames from "classnames";
import React from "react/addons";
import {Link} from "react-router";

var AppVolumesListItemComponent = React.createClass({
displayName: "AppVolumesListItemComponent",
Expand Down Expand Up @@ -36,10 +37,17 @@ var AppVolumesListItemComponent = React.createClass({
"cell-highlighted": sortKey === "mode"
});

var params = {
appId: encodeURIComponent(volume.appId),
volumeId: volume.persistenceId
};

return (
<tr>
<td className={idClassSet}>
{volume.id}
<Link to="volumeView" params={params}>
{volume.persistenceId}
</Link>
</td>
<td className={typeClassSet}>
{volume.type}
Expand Down
26 changes: 25 additions & 1 deletion src/js/components/BreadcrumbComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ var BreadcrumbComponent = React.createClass({
propTypes: {
appId: React.PropTypes.string,
groupId: React.PropTypes.string,
taskId: React.PropTypes.string
taskId: React.PropTypes.string,
volumeId: React.PropTypes.string
},

getInitialState: function () {
Expand Down Expand Up @@ -61,6 +62,7 @@ var BreadcrumbComponent = React.createClass({
didPropsChange: function (nextProps) {
return nextProps.appId !== this.props.appId ||
nextProps.groupId !== this.props.groupId ||
nextProps.volumeId !== this.props.volumeId ||
nextProps.taskId !== this.props.taskId;
},

Expand Down Expand Up @@ -213,6 +215,27 @@ var BreadcrumbComponent = React.createClass({
);
},

getVolumeLink: function () {
var appId = this.props.appId;
var volumeId = this.props.volumeId;
if (volumeId == null || appId == null) {
return null;
}

var params = {
appId: encodeURIComponent(appId),
volumeId: volumeId
};

return (
<li>
<Link to="volumeView" params={params}>
{volumeId}
</Link>
</li>
);
},

render: function () {
var classSet = classNames({
breadcrumb: true,
Expand All @@ -227,6 +250,7 @@ var BreadcrumbComponent = React.createClass({
{this.getGroupLinks()}
{this.getAppLink()}
{this.getTaskLink()}
{this.getVolumeLink()}
</ol>
);
}
Expand Down
62 changes: 22 additions & 40 deletions src/js/components/TaskDetailComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ var TaskDetailComponent = React.createClass({

getTabs: function (task) {
var appId = this.props.appId;
var app = AppsStore.getCurrentApp(appId);

var activeTabId =
`apps/${encodeURIComponent(appId)}/${encodeURIComponent(task.id)}`;
Expand All @@ -251,46 +252,27 @@ var TaskDetailComponent = React.createClass({
activeTabId = activeTab;
}

task.volumes = [
{
"containerPath": "foo",
"persistenceId": "appid.container.random"
},
{
"containerPath": "bar",
"persistenceId": "appid.bar.random"
}
];

var appVolumes = [
{
"containerPath": "foo",
"mode": "RW",
"persistent": {
"size": 1024
}
},
{
"containerPath": "bar",
"mode": "RW",
"persistent": {
"size": 1024
}
}
];

appVolumes = appVolumes.reduce((memo, volume) => {
if (volume.containerPath == null) {
return memo;
}
memo[volume.containerPath] = volume;
return memo;
}, {});

var volumes = task.volumes.map(taskVolume => {
appVolumes[taskVolume.containerPath].id = taskVolume.persistenceId;
return appVolumes[taskVolume.containerPath];
});
var volumes = [];

if (task.localVolumes != null) {
volumes = task.localVolumes
.map(volume => {
if (app.container == null || app.container.volumes == null) {
return null;
}
app.container.volumes.forEach(function (volumeConfig) {
if (volumeConfig.containerPath &&
volumeConfig.containerPath === volume.containerPath) {
Object.keys(volumeConfig).forEach(key =>
volume[key] = volumeConfig[key]
);
volume.appId = app.id;
volume.taskId = task.id;
}
});
return volume;
});
}

return (
<TogglableTabsComponent className="page-body page-body-no-top"
Expand Down
17 changes: 13 additions & 4 deletions src/js/components/TaskListItemComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,16 @@ var TaskListItemComponent = React.createClass({
var task = this.props.task;
var sortKey = this.props.sortKey;
var hasHealth = !!this.props.hasHealth;
var version = new Date(task.version).toISOString();
var version;
var endpoints;
var status = "Waiting";

if (task.status != null) {
var version = new Date(task.version).toISOString();
var endpoints = this.getEndpoints();
var status = task.status;
}

var taskId = task.id;
var taskURI = "#apps/" +
encodeURIComponent(this.props.appId) +
Expand Down Expand Up @@ -216,14 +225,14 @@ var TaskListItemComponent = React.createClass({
<td className={idClassSet}>
<a href={taskURI}>{taskId}</a>
<br />
{this.getEndpoints()}
{endpoints}
</td>
<td className={healthClassSet} title={this.props.taskHealthMessage}>
{this.props.taskHealthMessage}
</td>
<td className={statusCellClassSet}>
<span className={statusClassSet}>
{task.status}
{status}
</span>
</td>
<td className="text-center">
Expand All @@ -234,7 +243,7 @@ var TaskListItemComponent = React.createClass({
</td>
<td className={versionClassSet}>
<span title={version}>
{new Moment(version).fromNow()}
{version && new Moment(version).fromNow() || "---"}
</span>
</td>
<td className={updatedAtClassSet}>
Expand Down
2 changes: 2 additions & 0 deletions src/js/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ var routes = (
<Route name="group" path="group/:groupId" handler={TabPanesComponent} />
<Route name="app" path="apps/:appId" handler={AppPageComponent} />
<Route name="appView" path="apps/:appId/:view" handler={AppPageComponent} />
<Route name="volumeView" path="apps/:appId/volume/:volumeId"
handler={AppPageComponent} />
<Route name="taskView" path="apps/:appId/:view/:tab"
handler={AppPageComponent} />
<Route name="deployments" path="deployments" handler={TabPanesComponent} />
Expand Down

0 comments on commit 48e565a

Please sign in to comment.