Newer
Older
import React, { useContext, useEffect } from "react";
import { Table, Alert, Form } from "react-bootstrap";
import axios from "axios";
import { GlobalContext } from "../../contexts/GlobalContext";
import { QueryContext } from "../../contexts/QueryContext";
import { BasketContext } from "../../contexts/BasketContext";
import LoadingSpinner from "../LoadingSpinner";
import Paginate, { pagination_fields } from "../Paginate";
import SaveBasketButton from "../basket/SaveBasketButton";
import AddToBasket from "../basket/AddToBasketCheckBox";
const DATETIME_OPTIONS = {

Zheng Meyer
committed
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",

Zheng Meyer
committed
timeZoneName: "short",
Object.isObject = function(obj) {

Zheng Meyer
committed
return (obj && obj.constructor === this) || false;
Hugh Dickinson
committed
};

Zheng Meyer
committed
function renderArray(array, currentReactKey = "") {
Hugh Dickinson
committed
return array.map((element, index) => {
const updatedReactKey = `${currentReactKey}_${index}`;
const separator = index < array.length - 1 ? ", " : "";
return renderIfCompound(element, updatedReactKey, separator);
Hugh Dickinson
committed
});
}

Zheng Meyer
committed
function renderObject(object, currentReactKey = "") {
Hugh Dickinson
committed
return (
<Table key={currentReactKey + "_objTable"}>

Zheng Meyer
committed
<tbody>
{Object.entries(object).map(([key, value]) => {
const updatedReactKey = `${currentReactKey}_${key}`;
return (
<tr key={updatedReactKey}>
<td className="b">{key}</td>
<td>{renderIfCompound(value, updatedReactKey)}</td>
</tr>
);
})}
</tbody>
Hugh Dickinson
committed
</Table>

Zheng Meyer
committed
);
Hugh Dickinson
committed
}

Zheng Meyer
committed
function renderIfCompound(
element,
currentReactKey = "",
separatorForPod = "",
floatPrecision = 3
) {
Hugh Dickinson
committed
if (Array.isArray(element)) {
return renderArray(element, currentReactKey, separatorForPod);
Hugh Dickinson
committed
} else if (Object.isObject(element)) {
return renderObject(element, currentReactKey, separatorForPod);
Hugh Dickinson
committed
} else if (typeof element === "boolean") {

Zheng Meyer
committed
return JSON.stringify(element) + separatorForPod;
return element.toString() + separatorForPod;
} else {
return element.toFixed(floatPrecision) + separatorForPod;
} catch (err) {
return `${element}` + separatorForPod;
Hugh Dickinson
committed
}
}
function titleCase(string) {

Zheng Meyer
committed
var sentence = string.toLowerCase().split(" ");
for (var i = 0; i < sentence.length; i++) {
sentence[i] = sentence[i][0].toUpperCase() + sentence[i].slice(1);
}
return sentence.join(" ");
}
Hugh Dickinson
committed
return (args) => {
if (args.target) {
setPage(parseFloat(args.target.text));
}
};
Hugh Dickinson
committed
function projectBasketItem(projectId, category){
return {
archive: "zooniverse",
Hugh Dickinson
committed
catalog: "project",
project_id: projectId,
category: category
};
}
Hugh Dickinson
committed
function workflowBasketItem(projectId, workflowId, category){
return {
archive: "zooniverse",
Hugh Dickinson
committed
catalog: "workflow",
project_id: projectId,
workflow_id: workflowId,
category: category
};
}
Hugh Dickinson
committed
function ZooniverseProjectResults(context) {
const { queryMap, page, setPage } = context;
const date_formatter = new Intl.DateTimeFormat("default", DATETIME_OPTIONS);
const result = queryMap.get("zooniverse_projects").results.results[0];
const numPages = result.pages;

Zheng Meyer
committed
"launch_date",
"created_at",
"live",
"updated_at",
"project_id",
"display_name",
"slug",
];
const remaining_fields = Object.keys(result).filter(
(key) =>
!(mandatory_fields.includes(key) || pagination_fields.includes(key))

Zheng Meyer
committed
);
const remaining_headers = remaining_fields.map((field) => {

Zheng Meyer
committed
return <th key={`project_header_${field}`}>{title}</th>;
Hugh Dickinson
committed
});

Zheng Meyer
committed
return (
<>
<Paginate
getNewPage={newPageCallback(setPage)}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/>
<Table className="mt-3" responsive>
<thead>
<tr className="bg-light">
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<th>Select Classification Data</th>
<th>Select Subject Data</th>
<th>ID</th>
<th>Display Name</th>
<th>Created</th>
<th>Updated</th>
<th>Launched</th>
<th>Live</th>
<th>View</th>
{remaining_headers}
</tr>
</thead>
<tbody>
{queryMap
.get("zooniverse_projects")
.results.results.map((result) => {
const launch_date = result.launch_date
? date_formatter.format(new Date(result.launch_date))
: "Not Launched";
const created_at = date_formatter.format(
new Date(result.created_at)
);
const updated_at = date_formatter.format(
new Date(result.updated_at)

Zheng Meyer
committed
);
const live = result.live ? "Yes" : "No";
const remaining_cells = remaining_fields.map((field) => {
const reactKey = `project_${result.project_id}_${field}`;
return (
<td key={reactKey}>
{renderIfCompound(result[field], reactKey)}
</td>
);
});
return (
<tr key={`project_${result.project_id}`}>
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<AddToBasket id={`selectClassifications_${result.project_id}`} item={projectBasketItem(result.project_id, "classifications")} />
<AddToBasket id={`selectSubjects_${result.project_id}`} item={projectBasketItem(result.project_id, "subjects")} />
</td>
<td>{result.project_id}</td>
<td>{result.display_name}</td>
<td>{created_at}</td>
<td>{updated_at}</td>
<td>{launch_date}</td>
<td>{live}</td>
<td>
<a href={`https://zooniverse.org/projects/${result.slug}`}>
Link

Zheng Meyer
committed
</a>
</td>
{remaining_cells}
</tr>
);
})}
</tbody>
</Table>
</Form>
<Paginate
getNewPage={newPageCallback(setPage)}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/>

Zheng Meyer
committed
</>
);
Hugh Dickinson
committed
function ZooniverseWorkflowResults(context) {

Zheng Meyer
committed
let date_formatter = new Intl.DateTimeFormat("default", DATETIME_OPTIONS);
let result = queryMap.get("zooniverse_workflows").results.results[0];

Zheng Meyer
committed
let result_workflow = result.workflows[0];
const numPages = result.pages;

Zheng Meyer
committed
let mandatory_fields = [
"created_at",
"updated_at",
"workflow_id",
"display_name",
];
let remaining_fields = Object.keys(result_workflow).filter(
(key) =>
!(mandatory_fields.includes(key) || pagination_fields.includes(key))

Zheng Meyer
committed
);
Hugh Dickinson
committed
let remaining_headers = remaining_fields.map((field) => {

Zheng Meyer
committed
let title = titleCase(field.replace("_", " "));
return <th key={`project_header_${field}`}>{title}</th>;
Hugh Dickinson
committed
});
Hugh Dickinson
committed
const saveBasketStyle = { marginBottom : "10px"} ;

Zheng Meyer
committed
return (
<>
<Paginate
getNewPage={newPageCallback(setPage)}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/>
Hugh Dickinson
committed
<Form>
<SaveBasketButton style={saveBasketStyle} />

Zheng Meyer
committed
{queryMap
.get("zooniverse_workflows")
.results.results.map((project) => {

Zheng Meyer
committed
return (
<div key={project.project_id}>
<h4>{project.display_name}</h4>
<Table className="mt-3" responsive>
<thead>
<tr className="bg-light">
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<th>Select Classification Data</th>
<th>Select Subject Data</th>

Zheng Meyer
committed
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
<th>ID</th>
<th>Display Name</th>
<th>Created</th>
<th>Updated</th>
{remaining_headers}
{/* <th>View</th> */}
</tr>
</thead>
<tbody>
{project.workflows.map((workflow) => {
let created_at = date_formatter.format(
new Date(workflow.created_at)
);
let updated_at = date_formatter.format(
new Date(workflow.updated_at)
);
let remaining_cells = remaining_fields.map((field) => {
let reactKey = `workflow_${workflow.workflow_id}_${field}`;
return (
<td key={reactKey}>
{renderIfCompound(workflow[field], reactKey)}
</td>
);
});
return (
<tr key={`workflow_${workflow.workflow_id}`}>
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<AddToBasket id={`selectClassifications_${workflow.workflow_id}`} item={workflowBasketItem(result.project_id, workflow.workflow_id, "classifications")} />
<AddToBasket id={`selectSubjects_${workflow.workflow_id}`} item={workflowBasketItem(result.project_id, workflow.workflow_id, "subjects")} />

Zheng Meyer
committed
<td>{workflow.workflow_id}</td>
<td>{workflow.display_name}</td>
<td>{created_at}</td>
<td>{updated_at}</td>
{remaining_cells}
{/* <td><a href={`https://zooniverse.org/workflows/${workflow.slug}`}>Link</a></td> */}
</tr>
);
})}
</tbody>
</Table>
</div>
);
Hugh Dickinson
committed
</Form>
<Paginate
getNewPage={newPageCallback(setPage)}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/>

Zheng Meyer
committed
</>
);
}
export default function ZooniverseResults({ catalog }) {
const context = useContext(QueryContext);
const basketContext = useContext(BasketContext);
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
const { queryMap, page } = useContext(QueryContext);
const { api_host } = useContext(GlobalContext);
useEffect(() => {
queryMap.set(catalog, {
catalog: catalog,
page: page,
esapquery: queryMap.get(catalog).esapquery + `&page=${page}`,
});
const url = api_host + "query/query/?" + queryMap.get(catalog).esapquery;
axios
.get(url)
.then((queryResponse) => {
queryMap.set(catalog, {
catalog: catalog,
esapquery: queryMap.get(catalog).esapquery,
page: page,
status: "fetched",
results: queryResponse.data,
});
})
.catch(() => {
queryMap.set(catalog, {
catalog: catalog,
esapquery: queryMap.get(catalog).esapquery,
page: page,
status: "error",
results: null,
});
});
}, [page])
if (!context.queryMap) return null;
if (context.queryMap.get(catalog).status === "fetched") {
if (context.queryMap.get(catalog).results.results.length === 0)
return <Alert variant="warning">No matching results found!</Alert>;

Zheng Meyer
committed
else if (catalog === "zooniverse_projects") {
console.log(`basketContext -> ${basketContext}`);
console.log(basketContext);
return ZooniverseProjectResults(context, basketContext);

Zheng Meyer
committed
} else if (catalog === "zooniverse_workflows") {
return ZooniverseWorkflowResults(context, basketContext);

Zheng Meyer
committed
} else {
return <Alert variant="warning">Unrecognised Zooniverse Catalog!</Alert>;
}
} else {
return <LoadingSpinner />;
}
}