Skip to content
This repository has been archived by the owner on Nov 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request #37 from datatogether/task_pipeline
Browse files Browse the repository at this point in the history
Task Pipeline frontend & Collections Support
  • Loading branch information
b5 authored Jul 12, 2017
2 parents 87a809e + 56bd154 commit 67c97ad
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 46 deletions.
48 changes: 47 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
version: '2'
services:

context:
build: .
volumes:
Expand Down Expand Up @@ -41,7 +42,11 @@ services:
-----END RSA PRIVATE KEY-----
patchbay:
image: datatogether/patchbay:latest
# image: datatogether/patchbay:latest
build: $GOPATH/src/github.com/datatogether/patchbay/
volumes:
- $GOPATH/src/github.com/datatogether/patchbay:/go/src/github.com/datatogether/patchbay
- ./sql:/sql
ports:
- 3000:3000
networks:
Expand All @@ -68,7 +73,48 @@ services:
k4uJgqHl8hgs3bndGibFuepdLWJed7YXa+eF57FdmA==
-----END RSA PRIVATE KEY-----
- WEBAPP_SCRIPTS=http://localhost:4000/static/bundle.js
- TASKS_SERVICE_URL=task-mgmt:4400

task-mgmt:
build: $GOPATH/src/github.com/datatogether/task-mgmt/
volumes:
- $GOPATH/src/github.com/datatogether/task-mgmt:/go/src/github.com/datatogether/task-mgmt
- ./sql:/sql
ports:
- 3400:3400
- 4400:4400
networks:
- back-tier
depends_on:
- ipfs
- rabbitmq
- postgres
environment:
- PORT=3400
- TLS=false
- GOLANG_ENV=develop
- POSTGRES_DB_URL=postgres://postgres@postgres/postgres?sslmode=disable
- PUBLIC_KEY=nothing_yet
- POSTMARK_KEY=POSTMARK_API_TEST
- [email protected]
- GITHUB_LOGIN_URL=http://localhost:3100/oauth/github
- AMQP_URL=amqp://guest:guest@rabbitmq:5672/
- IPFS_API_URL=http://ipfs:5001/api/v0
- RPC_PORT=4400

ipfs:
image: "ipfs/go-ipfs:latest"
networks:
- back-tier
ports:
- 5001:5001
rabbitmq:
image: "library/rabbitmq:latest"
networks:
- back-tier
ports:
- 5672:5672
- 15672:15672
postgres:
image: postgres:9.6-alpine
networks:
Expand Down
25 changes: 17 additions & 8 deletions src/js/actions/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import analytics from '../analytics';
import { newLocalModel, updateLocalModel, editModel, removeLocalModel } from './locals';

const blankCollection = {
meta: {
title: "",
description: "",
},
title: "",
description: "",
schema: ["hash","url","description"],
contents: [],
};

const COLLECTION_NEW = "COLLECTION_NEW";
Expand Down Expand Up @@ -80,7 +80,7 @@ export const COLLECTION_SAVE_REQUEST = "COLLECTION_SAVE_REQUEST";
export const COLLECTION_SAVE_SUCCESS = "COLLECTION_SAVE_SUCCESS";
export const COLLECTION_SAVE_FAILURE = "COLLECTION_SAVE_FAILURE";

export function saveCollection(collection = {}) {
export function saveCollection(collection = {}, callback) {
return (dispatch) => {
analytics.track(collection.id ? "Created Collection" : "Saved Collection", collection);
return dispatch({
Expand All @@ -89,11 +89,14 @@ export function saveCollection(collection = {}) {
schema: Schemas.COLLECTION,
method: (collection.id == "new") ? "POST" : "PUT",
endpoint: "/collections",
data: collection,
data: (collection.id != "new") ? {collection} : { collection: Object.assign({}, collection, { id : "" }) },
},
}).then((action) => {
if (action.type == COLLECTION_SAVE_SUCCESS) {
cancelCollectionEdit(collection.keyId, collection.subject);
if (typeof callback == "function") {
callback(action.data);
}
}
});
};
Expand All @@ -103,7 +106,7 @@ export const COLLECTION_DELETE_REQUEST = "COLLECTION_DELETE_REQUEST";
export const COLLECTION_DELETE_SUCCESS = "COLLECTION_DELETE_SUCCESS";
export const COLLECTION_DELETE_FAILURE = "COLLECTION_DELETE_FAILURE";

export function deleteCollection(collection = {}) {
export function deleteCollection(collection = {}, callback) {
analytics.track("Deleted Collection", collection);
return (dispatch) => {
return dispatch({
Expand All @@ -114,6 +117,12 @@ export function deleteCollection(collection = {}) {
method: "DELETE",
data: collection,
},
});
}).then((action) => {
if (action.type == COLLECTION_DELETE_SUCCESS) {
if (typeof callback == "function") {
callback(action.data);
}
}
})
};
}
30 changes: 15 additions & 15 deletions src/js/actions/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,41 +76,41 @@ export function loadTask(id = "") {
};
}

export const TASK_SAVE_REQUEST = "TASK_SAVE_REQUEST";
export const TASK_SAVE_SUCCESS = "TASK_SAVE_SUCCESS";
export const TASK_SAVE_FAILURE = "TASK_SAVE_FAILURE";
export const TASK_ENQUEUE_REQUEST = "TASK_ENQUEUE_REQUEST";
export const TASK_ENQUEUE_SUCCESS = "TASK_ENQUEUE_SUCCESS";
export const TASK_ENQUEUE_FAILURE = "TASK_ENQUEUE_FAILURE";

export function saveTask(task = {}) {
export function enqueueTask(task = {}) {
return (dispatch) => {
analytics.track(task.id ? "Created Task" : "Saved Task", task);
analytics.track("Enqueued Task", task);
return dispatch({
[CALL_API]: {
types: [TASK_SAVE_REQUEST, TASK_SAVE_SUCCESS, TASK_SAVE_FAILURE],
types: [TASK_ENQUEUE_REQUEST, TASK_ENQUEUE_SUCCESS, TASK_ENQUEUE_FAILURE],
schema: Schemas.TASK,
method: (task.id == "new") ? "POST" : "PUT",
method: "POST",
endpoint: "/tasks",
data: task,
},
}).then((action) => {
if (action.type == TASK_SAVE_SUCCESS) {
if (action.type == TASK_ENQUEUE_SUCCESS) {
cancelTaskEdit(task.keyId, task.subject);
}
});
};
}

export const TASK_DELETE_REQUEST = "TASK_DELETE_REQUEST";
export const TASK_DELETE_SUCCESS = "TASK_DELETE_SUCCESS";
export const TASK_DELETE_FAILURE = "TASK_DELETE_FAILURE";
export const TASK_CANCEL_REQUEST = "TASK_CANCEL_REQUEST";
export const TASK_CANCEL_SUCCESS = "TASK_CANCEL_SUCCESS";
export const TASK_CANCEL_FAILURE = "TASK_CANCEL_FAILURE";

export function deleteTask(task = {}) {
analytics.track("Deleted Task", task);
export function cancelTask(task = {}) {
return (dispatch) => {
analytics.track("Cancelled Task", task);
return dispatch({
[CALL_API]: {
types: [TASK_DELETE_REQUEST, TASK_DELETE_SUCCESS, TASK_DELETE_FAILURE],
types: [TASK_CANCEL_REQUEST, TASK_CANCEL_SUCCESS, TASK_CANCEL_FAILURE],
schema: Schemas.TASK,
endpoint: "/tasks",
endpoint: `/tasks/${task.id}`,
method: "DELETE",
data: task,
},
Expand Down
35 changes: 27 additions & 8 deletions src/js/components/Collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import React, { PropTypes } from 'react';
import { Link } from 'react-router';

import List from './List';
import ContentItem from './item/ContentItem';

const Collection = ({ data, sessionKeyId }) => {
const Collection = ({ data, sessionKeyId, onEdit, onDelete }) => {
const collection = data;
return (
<div id="collection" className="page">
<div className="container">
<header className="row">
<div className="col-md-12">
<hr className="green" />
<a className="right red" onClick={onDelete}>&nbsp; delete</a>
<a className="right" onClick={onEdit}>edit</a>
<label className="label">Collection</label>
<h1 className="green">{collection.title}</h1>
</div>
Expand All @@ -24,14 +25,32 @@ const Collection = ({ data, sessionKeyId }) => {
</div>
<div className="row">
<div className="col-md-12">
<hr className="green" />
<h3 className="green">Contents:</h3>
<br />
<table className="table">
<thead>
<tr>
<th>hash</th>
<th>url</th>
<th>description</th>
</tr>
</thead>
<tbody>
{collection.contents.map((data, i) => {
const hash = data[0];
const url = data[1];
const description = data[2];

return (
<tr key={i} className="">
<td>{ hash && <Link to={`/content/${hash}`}><h5 className="title">{hash}</h5></Link>}</td>
<td>{url}</td>
<td>{description}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<div className="row">
<List data={collection.contents} component={ContentItem} />
</div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const List = (props) => {

return (
<div className={className}>
{data.map((item, i) => <props.component data={item} key={i} index={i} onSelect={selectFunc(onSelectItem, item, i)} />)}
{data.map((item, i) => <props.component {...props} data={item} key={i} index={i} onSelect={selectFunc(onSelectItem, item, i)} />)}
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/js/components/MainMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class MainMenu extends React.Component {
<Link className="blue" to="/primers">Home</Link>
{/*<Link className="blue" to="/coverage">Coverage</Link>*/}
<Link className="blue" to="/archives">Datasets</Link>
<Link className="blue" to="/collections">Collections</Link>
{/*<Link className="blue" to="/collections">Collections</Link>*/}
{/*<Link className="blue" to="/uncrawlables">Uncrawlables</Link>*/}
{
Expand Down
80 changes: 77 additions & 3 deletions src/js/components/form/CollectionForm.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
import React, { PropTypes } from 'react';

import List from '../List';
import ValidInput from './ValidInput';
// import ValidTextarea from './ValidTextarea';

const CollectionForm = ({ data, onChange, onCancel, onSubmit }) => {
const CollectionForm = ({ name, data, onChange, onCancel, onSubmit }) => {
const collection = data;
const handleChange = (name, value) => {
onChange(name, Object.assign({}, data, { [name] : value }));
}
const handleSubmit = (e) => {
e.preventDefault();
onSubmit(collection, e);
};

const handleItemChange = (index, item) => {
let contents = collection.contents.concat()
contents.splice(index,1,item);

onChange(name, Object.assign({}, collection, { contents }));
}

const handleItemDelete = (index) => {
// onChange(name, data);
}

const handleAddItem = (e) => {
e.preventDefault();
let contents = collection.contents || [];
onChange(name,Object.assign({}, collection, { contents: contents.concat([["", "", ""]])}));
}

return (
<div id="collection" className="page">
<div className="container">
Expand All @@ -21,23 +42,76 @@ const CollectionForm = ({ data, onChange, onCancel, onSubmit }) => {
</header>
<div className="row">
<div className="col-md-12">
<ValidInput name="title" value={collection.title} onChange={onChange} />
<ValidInput name="title" label="title" value={collection.title} onChange={handleChange} />
<br />
<button className="btn" onClick={onCancel}>Cancel</button>
<input className="btn btn-primary" type="submit" value="Save" onClick={handleSubmit} />
</div>
</div>
<div className="row">
<div className="col-md-12">
<hr className="green" />
<label className="label">collection items</label>
<table className="table">
<thead>
<tr>
<th>hash</th>
<th>url</th>
<th>description</th>
<th>delete</th>
</tr>
</thead>
<tbody>
{collection.contents.map((item, i) => {
return <CollectionItem key={i} data={item} index={i} onChange={handleItemChange} onDelete={handleItemDelete} />
})}
</tbody>
</table>
<a onClick={handleAddItem}>add item</a>
</div>
</div>
</div>
</div>
);
};

CollectionForm.propTypes = {
data: PropTypes.object.isRequired,

name: PropTypes.string,
onChange: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
};

CollectionForm.defaultProps = {
name : "collection",
}

const CollectionItem = ({data, index, onChange, onDelete}) => {
const handleChange = (name, value) => {
// TODO - lol make this not bad
switch (name) {
case "url":
onChange(index, [data[0],value, data[2]])
break;
case "note":
onChange(index, [data[0], data[1], value])
break;
}
}

const handleDelete = (e) => {
onDelete(index);
}

return (
<tr>
<td>{data[0]}</td>
<td><ValidInput name="url" value={data[1]} onChange={handleChange} /></td>
<td><ValidInput name="note" value={data[2]} onChange={handleChange} /></td>
<td><a onClick={handleDelete}>delete</a></td>
</tr>
);
}

export default CollectionForm;
Loading

0 comments on commit 67c97ad

Please sign in to comment.