chore: Switch formatter.
This commit is contained in:
parent
bd5bdb9cd0
commit
b86deafefd
583
lib/\
583
lib/\
|
@ -1,583 +0,0 @@
|
||||||
/* Imports */
|
|
||||||
import Head from "next/head";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { DrawGraph, removeOldSvg } from "./labeledGraph";
|
|
||||||
import { SubmitSliderButton } from "./slider";
|
|
||||||
import { DisplayElement } from "./displayElement";
|
|
||||||
import { DisplayAsMarkdown } from "./displayAsMarkdown";
|
|
||||||
import { CreateTable, buildRows } from "./findPaths";
|
|
||||||
import { DataSetChanger } from "./datasetChanger";
|
|
||||||
import { ComparisonsChanger } from "./comparisonsChanger";
|
|
||||||
import { pushToMongo } from "./pushToMongo.js";
|
|
||||||
import {
|
|
||||||
increasingList,
|
|
||||||
maxMergeSortSteps,
|
|
||||||
expectedNumMergeSortSteps,
|
|
||||||
conservativeNumMergeSortSteps,
|
|
||||||
} from "./utils.js";
|
|
||||||
|
|
||||||
/* DEFINTIONS */
|
|
||||||
const DEFAULT_COMPARE = () => 1; // 1/Math.random() - 1
|
|
||||||
|
|
||||||
/* Misc. helpers */
|
|
||||||
let buildLinks = (quantitativeComparisons) =>
|
|
||||||
quantitativeComparisons.map(([element1, element2, distance, reasoning]) => ({
|
|
||||||
source: element1,
|
|
||||||
target: element2,
|
|
||||||
distance: distance,
|
|
||||||
reasoning: reasoning,
|
|
||||||
}));
|
|
||||||
|
|
||||||
Array.prototype.containsArray = function (val) {
|
|
||||||
var hash = {};
|
|
||||||
for (var i = 0; i < this.length; i++) {
|
|
||||||
hash[this[i]] = i;
|
|
||||||
}
|
|
||||||
return hash.hasOwnProperty(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
let checkIfListIsOrdered = (arr, binaryComparisons) => {
|
|
||||||
let l = arr.length;
|
|
||||||
let isOrdered = true;
|
|
||||||
for (let i = 0; i < l - 1; i++) {
|
|
||||||
isOrdered =
|
|
||||||
isOrdered && binaryComparisons.containsArray([arr[i], arr[i + 1]]);
|
|
||||||
}
|
|
||||||
return isOrdered;
|
|
||||||
};
|
|
||||||
|
|
||||||
let nicelyFormatLinks = (quantitativeComparisons, listOfElements) =>
|
|
||||||
quantitativeComparisons.map(([element1, element2, distance, reasoning]) => ({
|
|
||||||
source: listOfElements[element1].name,
|
|
||||||
target: listOfElements[element2].name,
|
|
||||||
distance: distance,
|
|
||||||
reasoning: reasoning,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Main react component
|
|
||||||
export default function ComparisonView({ listOfElementsForView }) {
|
|
||||||
/* State */
|
|
||||||
// initial state values
|
|
||||||
let initialListOfElements = listOfElementsForView.map((element, i) => ({
|
|
||||||
...element,
|
|
||||||
id: i,
|
|
||||||
}));
|
|
||||||
let initialPosList = increasingList(listOfElementsForView.length); // [0,1,2,3,4]
|
|
||||||
let initialComparePair = [
|
|
||||||
initialPosList[initialPosList.length - 2],
|
|
||||||
initialPosList[initialPosList.length - 1],
|
|
||||||
];
|
|
||||||
let initialSliderValue = 1;
|
|
||||||
let initialReasoning = "";
|
|
||||||
let initialBinaryComparisons = [];
|
|
||||||
let initialQuantitativeComparisons = [];
|
|
||||||
let initialIsListOdered = false;
|
|
||||||
let initialOrderedList = [];
|
|
||||||
let initialShowAdvancedOptions = false;
|
|
||||||
let initialShowComparisons = false;
|
|
||||||
let initialShowLoadComparisons = false;
|
|
||||||
let initialShowChangeDataSet = false;
|
|
||||||
let initialNumSteps = 0;
|
|
||||||
let initialMaxSteps = maxMergeSortSteps(listOfElementsForView.length);
|
|
||||||
let initialExpectedSteps = expectedNumMergeSortSteps(
|
|
||||||
listOfElementsForView.length
|
|
||||||
);
|
|
||||||
let initialTableRows = [];
|
|
||||||
let initialDontPushSubmitButtonAnyMore = false;
|
|
||||||
|
|
||||||
// state variables and functions
|
|
||||||
const [listOfElements, setListOfElements] = useState(initialListOfElements);
|
|
||||||
const [posList, setPosList] = useState(initialPosList);
|
|
||||||
const [toComparePair, setToComparePair] = useState(initialComparePair);
|
|
||||||
const [sliderValue, setSliderValue] = useState(initialSliderValue);
|
|
||||||
const [reasoning, setReasoning] = useState(initialReasoning);
|
|
||||||
const [binaryComparisons, setBinaryComparisons] = useState(
|
|
||||||
initialBinaryComparisons
|
|
||||||
);
|
|
||||||
const [quantitativeComparisons, setQuantitativeComparisons] = useState(
|
|
||||||
initialQuantitativeComparisons
|
|
||||||
); // More expressive, but more laborious to search through. For the ordering step, I only manipulate the binaryComparisons.
|
|
||||||
|
|
||||||
const [isListOrdered, setIsListOrdered] = useState(initialIsListOdered);
|
|
||||||
const [orderedList, setOrderedList] = useState(initialOrderedList);
|
|
||||||
const [dontPushSubmitButtonAnyMore, setDontPushSubmitButtonAnyMore] =
|
|
||||||
useState(initialDontPushSubmitButtonAnyMore);
|
|
||||||
|
|
||||||
let [showAdvancedOptions, changeShowAdvanceOptions] = useState(
|
|
||||||
initialShowAdvancedOptions
|
|
||||||
);
|
|
||||||
let [showComparisons, changeShowComparisons] = useState(
|
|
||||||
initialShowComparisons
|
|
||||||
);
|
|
||||||
let [showLoadComparisons, changeShowLoadComparisons] = useState(
|
|
||||||
initialShowLoadComparisons
|
|
||||||
);
|
|
||||||
let [showChangeDataSet, changeshowChangeDataSet] = useState(
|
|
||||||
initialShowChangeDataSet
|
|
||||||
);
|
|
||||||
let [numSteps, changeNumSteps] = useState(initialNumSteps);
|
|
||||||
let [maxSteps, changeMaxSteps] = useState(initialMaxSteps);
|
|
||||||
let [expectedSteps, changeExpectedSteps] = useState(initialExpectedSteps);
|
|
||||||
let [tableRows, setTableRows] = useState(initialTableRows);
|
|
||||||
|
|
||||||
/* Convenience utils: restart + changeDataSet */
|
|
||||||
let restart = (
|
|
||||||
posList,
|
|
||||||
initialBinaryComparisons2,
|
|
||||||
initialQuantitativeComparisons2
|
|
||||||
) => {
|
|
||||||
//({posList, initialBinaryComparisons2, initialQuantitativeComparisons2}) => {
|
|
||||||
setToComparePair([
|
|
||||||
posList[posList.length - 2],
|
|
||||||
posList[posList.length - 1],
|
|
||||||
]);
|
|
||||||
setSliderValue(initialSliderValue);
|
|
||||||
setBinaryComparisons(initialBinaryComparisons2 || initialBinaryComparisons);
|
|
||||||
setQuantitativeComparisons(
|
|
||||||
initialQuantitativeComparisons2 || initialQuantitativeComparisons
|
|
||||||
);
|
|
||||||
setIsListOrdered(initialIsListOdered);
|
|
||||||
setOrderedList(initialOrderedList);
|
|
||||||
changeNumSteps(initialNumSteps);
|
|
||||||
removeOldSvg();
|
|
||||||
setTableRows(initialTableRows);
|
|
||||||
setDontPushSubmitButtonAnyMore(initialDontPushSubmitButtonAnyMore);
|
|
||||||
};
|
|
||||||
|
|
||||||
let changeDataSet = (listOfElementsNew) => {
|
|
||||||
listOfElementsNew = listOfElementsNew.map((element, i) => ({
|
|
||||||
...element,
|
|
||||||
id: i,
|
|
||||||
}));
|
|
||||||
let newPosList = increasingList(listOfElementsNew.length);
|
|
||||||
let newListLength = listOfElementsNew.length;
|
|
||||||
|
|
||||||
setListOfElements(listOfElementsNew);
|
|
||||||
setPosList(increasingList(listOfElementsNew.length));
|
|
||||||
setToComparePair([
|
|
||||||
newPosList[newPosList.length - 2],
|
|
||||||
newPosList[newPosList.length - 1],
|
|
||||||
]);
|
|
||||||
|
|
||||||
changeExpectedSteps(expectedNumMergeSortSteps(newListLength));
|
|
||||||
changeMaxSteps(maxMergeSortSteps(newListLength));
|
|
||||||
|
|
||||||
restart(newPosList);
|
|
||||||
// restart({posList: newPosList})
|
|
||||||
};
|
|
||||||
|
|
||||||
let changeComparisons = async (links) => {
|
|
||||||
let quantitativeComparisons2 = [];
|
|
||||||
let binaryComparisons2 = [];
|
|
||||||
links.shift();
|
|
||||||
for (let link of links) {
|
|
||||||
let { source, target, distance, reasoning } = link;
|
|
||||||
let searchByName = (name, candidate) => candidate.name == name;
|
|
||||||
let testForSource = (candidate) => searchByName(source, candidate);
|
|
||||||
let testForTarget = (candidate) => searchByName(target, candidate);
|
|
||||||
let element1 = listOfElements.findIndex(testForSource);
|
|
||||||
let element2 = listOfElements.findIndex(testForTarget);
|
|
||||||
if (element1 == -1 || element2 == -1) {
|
|
||||||
console.log("link", link);
|
|
||||||
console.log(source);
|
|
||||||
console.log(target);
|
|
||||||
throw new Error("Comparisons include unknown elements, please retry");
|
|
||||||
}
|
|
||||||
quantitativeComparisons2.push([element1, element2, distance, reasoning]);
|
|
||||||
binaryComparisons2.push([element1, element2]);
|
|
||||||
}
|
|
||||||
// return ({quantitativeComparisons: quantitativeComparisons2, binaryComparisons: binaryComparisons2})
|
|
||||||
//restart({posList, initialBinaryComparisons2=initialBinaryComparisons, initialQuantitativeComparisons2=initialQuantitativeComparisons})
|
|
||||||
// restart(posList, binaryComparisons2, quantitativeComparisons2)
|
|
||||||
setQuantitativeComparisons(quantitativeComparisons2);
|
|
||||||
setBinaryComparisons(binaryComparisons2);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Manipulations
|
|
||||||
let compareTwoElements = (newBinaryComparisons, element1, element2) => {
|
|
||||||
let element1Greater = newBinaryComparisons.containsArray([
|
|
||||||
element1,
|
|
||||||
element2,
|
|
||||||
]);
|
|
||||||
let element2Greater = newBinaryComparisons.containsArray([
|
|
||||||
element2,
|
|
||||||
element1,
|
|
||||||
]);
|
|
||||||
if (element1Greater || element2Greater) {
|
|
||||||
return element1Greater && !element2Greater;
|
|
||||||
} else {
|
|
||||||
setToComparePair([element1, element2]);
|
|
||||||
//console.log(`No comparison found between ${element1} and ${element2}`)
|
|
||||||
//console.log(`Comparisons:`)
|
|
||||||
//console.log(JSON.stringify(newBinaryComparisons, null, 4));
|
|
||||||
return "No comparison found";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function merge(newBinaryComparisons, left, right) {
|
|
||||||
let sortedArr = []; // the sorted elements will go here
|
|
||||||
|
|
||||||
while (left.length && right.length) {
|
|
||||||
// insert the biggest element to the sortedArr
|
|
||||||
let comparison = compareTwoElements(
|
|
||||||
newBinaryComparisons,
|
|
||||||
left[0],
|
|
||||||
right[0]
|
|
||||||
);
|
|
||||||
if (comparison == "No comparison found") {
|
|
||||||
return "No comparison found; unable to proceed";
|
|
||||||
} else if (comparison) {
|
|
||||||
// left[0] > right[0]
|
|
||||||
sortedArr.push(left.shift());
|
|
||||||
} else {
|
|
||||||
sortedArr.push(right.shift());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use spread operator and create a new array, combining the three arrays
|
|
||||||
return [...sortedArr, ...left, ...right]; // if they don't have the same size, the remaining ones will be greater than the ones before
|
|
||||||
}
|
|
||||||
|
|
||||||
function mergeSort({ array, comparisons }) {
|
|
||||||
if (array == "No comparison found; unable to proceed") {
|
|
||||||
return "No comparison found; unable to proceed";
|
|
||||||
}
|
|
||||||
const half = array.length / 2;
|
|
||||||
|
|
||||||
// the base case is array length <=1
|
|
||||||
if (array.length <= 1) {
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
const left = array.slice(0, half); // the first half of the array
|
|
||||||
const right = array.slice(half, array.length); // Note that splice is destructive.
|
|
||||||
let orderedFirstHalf = mergeSort({ array: left, comparisons });
|
|
||||||
let orderedSecondHalf = mergeSort({ array: right, comparisons });
|
|
||||||
if (
|
|
||||||
orderedFirstHalf != "No comparison found; unable to proceed" &&
|
|
||||||
orderedSecondHalf != "No comparison found; unable to proceed"
|
|
||||||
) {
|
|
||||||
let result = merge(comparisons, orderedFirstHalf, orderedSecondHalf);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return "No comparison found; unable to proceed";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let nextStepSimple = (posList, binaryComparisons, element1, element2) => {
|
|
||||||
//console.log("Binary comparisons: ")
|
|
||||||
//console.log(JSON.stringify(binaryComparisons, null, 4));
|
|
||||||
|
|
||||||
let newComparison = [element1, element2]; // [element1, element2]
|
|
||||||
let newBinaryComparisons = [...binaryComparisons, newComparison];
|
|
||||||
//console.log("New binaryComparisons: ")
|
|
||||||
//console.log(JSON.stringify(newBinaryComparisons, null, 4));
|
|
||||||
setBinaryComparisons(newBinaryComparisons);
|
|
||||||
|
|
||||||
let result = mergeSort({
|
|
||||||
array: posList,
|
|
||||||
comparisons: newBinaryComparisons,
|
|
||||||
});
|
|
||||||
//console.log(result)
|
|
||||||
if (
|
|
||||||
result != "No comparison found; unable to proceed" &&
|
|
||||||
checkIfListIsOrdered(result, newBinaryComparisons)
|
|
||||||
) {
|
|
||||||
// console.log(`isListOrdered: ${isListOrdered}`)
|
|
||||||
console.log("poslist@nextStepSimple");
|
|
||||||
console.log(posList);
|
|
||||||
console.log("result@nextStepSimple");
|
|
||||||
console.log(result);
|
|
||||||
|
|
||||||
return [true, result];
|
|
||||||
} else {
|
|
||||||
return [false, result];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let nextStepSlider = async ({
|
|
||||||
posList,
|
|
||||||
binaryComparisons,
|
|
||||||
sliderValue,
|
|
||||||
reasoning,
|
|
||||||
element1,
|
|
||||||
element2,
|
|
||||||
}) => {
|
|
||||||
if (!dontPushSubmitButtonAnyMore) {
|
|
||||||
if (sliderValue < 1 && sliderValue > 0) {
|
|
||||||
sliderValue = 1 / sliderValue;
|
|
||||||
[element1, element2] = [element2, element1];
|
|
||||||
}
|
|
||||||
console.log(`posList@nextStepSlider:`);
|
|
||||||
console.log(posList);
|
|
||||||
let [successStatus, result] = nextStepSimple(
|
|
||||||
posList,
|
|
||||||
binaryComparisons,
|
|
||||||
element1,
|
|
||||||
element2
|
|
||||||
);
|
|
||||||
|
|
||||||
let newQuantitativeComparison = [
|
|
||||||
element1,
|
|
||||||
element2,
|
|
||||||
sliderValue,
|
|
||||||
reasoning,
|
|
||||||
];
|
|
||||||
let newQuantitativeComparisons = [
|
|
||||||
...quantitativeComparisons,
|
|
||||||
newQuantitativeComparison,
|
|
||||||
];
|
|
||||||
setQuantitativeComparisons(newQuantitativeComparisons);
|
|
||||||
|
|
||||||
setSliderValue(DEFAULT_COMPARE());
|
|
||||||
setReasoning("");
|
|
||||||
changeNumSteps(numSteps + 1);
|
|
||||||
if (successStatus) {
|
|
||||||
setDontPushSubmitButtonAnyMore(true);
|
|
||||||
|
|
||||||
let jsObject = nicelyFormatLinks(
|
|
||||||
quantitativeComparisons,
|
|
||||||
listOfElements
|
|
||||||
);
|
|
||||||
await pushToMongo(jsObject);
|
|
||||||
console.log(jsObject);
|
|
||||||
|
|
||||||
alert(
|
|
||||||
"Comparisons completed. Background work might take a while, or straight-out fail"
|
|
||||||
);
|
|
||||||
setIsListOrdered(true);
|
|
||||||
setOrderedList(result);
|
|
||||||
|
|
||||||
await buildRows({
|
|
||||||
isListOrdered: true,
|
|
||||||
orderedList: result,
|
|
||||||
listOfElements,
|
|
||||||
links: buildLinks(newQuantitativeComparisons),
|
|
||||||
rows: tableRows,
|
|
||||||
setTableRows,
|
|
||||||
});
|
|
||||||
/*
|
|
||||||
setTimeout(async () => {
|
|
||||||
// Make sure to do this after the
|
|
||||||
|
|
||||||
}, 100);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Html
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center justify-center min-h-screen py-2">
|
|
||||||
{/* Webpage name & favicon */}
|
|
||||||
<div className="mt-20">
|
|
||||||
<Head>
|
|
||||||
<title>Utility Function Extractor</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
</div>
|
|
||||||
<main className="flex flex-col items-center w-full flex-1 px-20 text-center">
|
|
||||||
{/* Heading */}
|
|
||||||
<h1 className="text-6xl font-bold">Utility Function Extractor</h1>
|
|
||||||
{/* Approximate progress indicator */}
|
|
||||||
|
|
||||||
<p>{`${numSteps} out of ~${expectedSteps} (max ${maxSteps}) comparisons`}</p>
|
|
||||||
|
|
||||||
{/* Comparison section */}
|
|
||||||
<div className={isListOrdered ? "hidden" : ""}>
|
|
||||||
<div className="flex flex-wrap items-center max-w-4xl sm:w-full mt-10">
|
|
||||||
{/* Element 1 */}
|
|
||||||
<div className="flex m-auto border-gray-300 border-4 h-72 w-72 p-5">
|
|
||||||
<div className="block m-auto text-center">
|
|
||||||
<DisplayElement
|
|
||||||
element={listOfElements[toComparePair[0]]}
|
|
||||||
></DisplayElement>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Comparison actuator (text, previously slider) */}
|
|
||||||
<div className="flex m-auto w-72">
|
|
||||||
<div className="block m-auto text-center">
|
|
||||||
<br />
|
|
||||||
<label>
|
|
||||||
{`... is `}
|
|
||||||
<br />
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="text-center text-blueGray-600 bg-white rounded text-lg border-0 shadow outline-none focus:outline-none focus:ring w-8/12 h-10 m-2"
|
|
||||||
value={sliderValue}
|
|
||||||
onChange={(event) => {
|
|
||||||
//console.log(event)
|
|
||||||
//console.log(event.target.value)
|
|
||||||
setSliderValue(event.target.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<br />
|
|
||||||
{`times as valuable as ...`}
|
|
||||||
</label>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<SubmitSliderButton
|
|
||||||
posList={posList}
|
|
||||||
binaryComparisons={binaryComparisons}
|
|
||||||
sliderValue={sliderValue}
|
|
||||||
reasoning={reasoning}
|
|
||||||
toComparePair={toComparePair}
|
|
||||||
nextStepSlider={nextStepSlider}
|
|
||||||
dontPushSubmitButtonAnyMore={dontPushSubmitButtonAnyMore}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Element 2 */}
|
|
||||||
<div className="flex m-auto border-gray-300 border-4 h-72 w-72 p-5">
|
|
||||||
<div className="block m-auto text-center">
|
|
||||||
<DisplayElement
|
|
||||||
element={listOfElements[toComparePair[1]]}
|
|
||||||
></DisplayElement>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<label className="">
|
|
||||||
Reasoning (optional):
|
|
||||||
<textarea
|
|
||||||
className="mt-2 px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border-0 shadow outline-none focus:outline-none focus:ring w-full"
|
|
||||||
value={reasoning}
|
|
||||||
onChange={(event) => setReasoning(event.target.value)}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<br />
|
|
||||||
<div></div>
|
|
||||||
{/* Old slider element (previous actuator)
|
|
||||||
|
|
||||||
<div className={`flex row-start-3 row-end-3 col-start-1 col-end-4 md:col-start-3 md:col-end-3 md:row-start-1 md:row-end-1 lg:col-start-3 lg:col-end-3 lg:row-start-1 lg:row-end-1 items-center justify-center mb-4 mt-10 ${isListOrdered ? "hidden" : ""}`}>
|
|
||||||
<SliderElement
|
|
||||||
className="flex items-center justify-center"
|
|
||||||
onChange={(event) => (setSliderValue(event[0]))}
|
|
||||||
value={sliderValue}
|
|
||||||
displayFunction={displayFunctionSlider}
|
|
||||||
domain={domain}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
*/}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Results section */}
|
|
||||||
<div className={isListOrdered ? "" : "hidden"}>
|
|
||||||
{/* Graph */}
|
|
||||||
<div className="flex items-center text-center ">
|
|
||||||
<DrawGraph
|
|
||||||
isListOrdered={isListOrdered}
|
|
||||||
orderedList={orderedList}
|
|
||||||
listOfElements={listOfElements}
|
|
||||||
links={buildLinks(quantitativeComparisons)}
|
|
||||||
></DrawGraph>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Comparison table */}
|
|
||||||
<div className="flex items-center text-center ">
|
|
||||||
<CreateTable
|
|
||||||
isListOrdered={isListOrdered}
|
|
||||||
orderedList={orderedList}
|
|
||||||
listOfElements={listOfElements}
|
|
||||||
links={buildLinks(quantitativeComparisons)}
|
|
||||||
tableRows={tableRows}
|
|
||||||
setTableRows={setTableRows}
|
|
||||||
></CreateTable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Convenience functions */}
|
|
||||||
<div className="w-2/12 flex justify-center mt-10">
|
|
||||||
<button
|
|
||||||
className="text-gray-500 text-sm"
|
|
||||||
onClick={() => changeShowAdvanceOptions(!showAdvancedOptions)}
|
|
||||||
>
|
|
||||||
Advanced options ▼
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={
|
|
||||||
showAdvancedOptions
|
|
||||||
? "flex flex-wrap -mx-4 overflow-hidden"
|
|
||||||
: "hidden"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{/* Button: Restart */}
|
|
||||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
|
||||||
<button
|
|
||||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
|
||||||
onClick={() => restart(posList)}
|
|
||||||
>
|
|
||||||
{/* onClick={() => restart({posList})}> */}
|
|
||||||
Restart
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{/* Button: Show comparisons */}
|
|
||||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
|
||||||
<button
|
|
||||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
|
||||||
onClick={() => changeShowComparisons(!showComparisons)}
|
|
||||||
>
|
|
||||||
Show comparisons
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{/* Button: Load comparisons */}
|
|
||||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
|
||||||
<button
|
|
||||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
|
||||||
onClick={() => changeShowLoadComparisons(!showLoadComparisons)}
|
|
||||||
>
|
|
||||||
Load comparisons
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{/* Button: Change dataset */}
|
|
||||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
|
||||||
<button
|
|
||||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
|
||||||
onClick={() => changeshowChangeDataSet(!showChangeDataSet)}
|
|
||||||
>
|
|
||||||
Use your own data
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Change dataset section */}
|
|
||||||
<div className={showChangeDataSet ? "inline mt-5" : "hidden"}>
|
|
||||||
<DataSetChanger handleSubmit={changeDataSet} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Show comparisons section */}
|
|
||||||
<div className={showComparisons ? "inline mt-5" : "hidden"}>
|
|
||||||
<div className="text-left">
|
|
||||||
<DisplayAsMarkdown
|
|
||||||
markdowntext={`
|
|
||||||
${
|
|
||||||
"" /*
|
|
||||||
## Comparisons
|
|
||||||
### Binary comparisons
|
|
||||||
${JSON.stringify(binaryComparisons, null, 4)}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
### Numerical comparisons
|
|
||||||
${JSON.stringify(
|
|
||||||
nicelyFormatLinks(quantitativeComparisons, listOfElements),
|
|
||||||
null,
|
|
||||||
4
|
|
||||||
)}
|
|
||||||
`}
|
|
||||||
className={""}
|
|
||||||
></DisplayAsMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Load comparisons section */}
|
|
||||||
<div className={showLoadComparisons ? "inline mt-5" : "hidden"}>
|
|
||||||
<ComparisonsChanger handleSubmit={changeComparisons} />
|
|
||||||
{/*<ComparisonsChanger handleSubmit={changeComparisons} />*/}
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,38 +1,39 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
|
|
||||||
export function ComparisonsChanger({handleSubmit}){
|
export function ComparisonsChanger({ handleSubmit }) {
|
||||||
// let defaultText=JSON.stringify(nicelyFormatLinks(quantitativeComparisons, listOfElements), null, 4)
|
// let defaultText=JSON.stringify(nicelyFormatLinks(quantitativeComparisons, listOfElements), null, 4)
|
||||||
|
|
||||||
let [value, setValue] = useState(``)
|
let [value, setValue] = useState(``);
|
||||||
const [displayingDoneMessage, setDisplayingDoneMessage] = useState(false)
|
const [displayingDoneMessage, setDisplayingDoneMessage] = useState(false);
|
||||||
const [displayingDoneMessageTimer, setDisplayingDoneMessageTimer] = useState(null)
|
const [displayingDoneMessageTimer, setDisplayingDoneMessageTimer] =
|
||||||
|
useState(null);
|
||||||
|
|
||||||
let handleChange = (event) => {
|
let handleChange = (event) => {
|
||||||
setValue(event.target.value)
|
setValue(event.target.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
let handleSubmitInner = (event) => {
|
let handleSubmitInner = (event) => {
|
||||||
clearTimeout(displayingDoneMessageTimer)
|
clearTimeout(displayingDoneMessageTimer);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//console.log(event)
|
//console.log(event)
|
||||||
console.log("value@handleSubmitInner@ComparisonsChanger")
|
console.log("value@handleSubmitInner@ComparisonsChanger");
|
||||||
//console.log(typeof(value));
|
//console.log(typeof(value));
|
||||||
console.log(value);
|
console.log(value);
|
||||||
try{
|
try {
|
||||||
let newData = JSON.parse(value)
|
let newData = JSON.parse(value);
|
||||||
//console.log(typeof(newData))
|
//console.log(typeof(newData))
|
||||||
//console.log(newData)
|
//console.log(newData)
|
||||||
handleSubmit(newData)
|
handleSubmit(newData);
|
||||||
/*
|
/*
|
||||||
if(!newData.length || newData.length < 2){
|
if(!newData.length || newData.length < 2){
|
||||||
throw Error("Not enough objects")
|
throw Error("Not enough objects")
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
setDisplayingDoneMessage(true)
|
setDisplayingDoneMessage(true);
|
||||||
let timer = setTimeout(() => setDisplayingDoneMessage(false), 3000);
|
let timer = setTimeout(() => setDisplayingDoneMessage(false), 3000);
|
||||||
setDisplayingDoneMessageTimer(timer)
|
setDisplayingDoneMessageTimer(timer);
|
||||||
}catch(error){
|
} catch (error) {
|
||||||
setDisplayingDoneMessage(false)
|
setDisplayingDoneMessage(false);
|
||||||
//alert(error)
|
//alert(error)
|
||||||
//console.log(error)
|
//console.log(error)
|
||||||
let substituteText = `Error: ${error.message}
|
let substituteText = `Error: ${error.message}
|
||||||
|
@ -59,35 +60,40 @@ Try something like:
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
Your old input was: ${value}`
|
Your old input was: ${value}`;
|
||||||
setValue(substituteText)
|
setValue(substituteText);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmitInner} className="inline">
|
<form onSubmit={handleSubmitInner} className="inline">
|
||||||
<p>Load comparisons in the same style as in "Show comparisons".</p>
|
<p>Load comparisons in the same style as in "Show comparisons".</p>
|
||||||
<p>These will override your current comparisons.</p>
|
<p>These will override your current comparisons.</p>
|
||||||
<br/>
|
<br />
|
||||||
<textarea
|
<textarea
|
||||||
value={value}
|
value={value}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
rows="10" cols="50"
|
rows="10"
|
||||||
|
cols="50"
|
||||||
className=""
|
className=""
|
||||||
/>
|
/>
|
||||||
<br/>
|
<br />
|
||||||
<button
|
<button
|
||||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5 p-10"
|
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5 p-10"
|
||||||
onClick={handleSubmitInner}>
|
onClick={handleSubmitInner}
|
||||||
|
>
|
||||||
Change comparisons
|
Change comparisons
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={displayingDoneMessage ? "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5 p-10" : "hidden"}
|
className={
|
||||||
|
displayingDoneMessage
|
||||||
|
? "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5 p-10"
|
||||||
|
: "hidden"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Done!
|
Done!
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
518
lib/d3experiment.js
vendored
518
lib/d3experiment.js
vendored
|
@ -1,262 +1,280 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import * as d3 from 'd3';
|
import * as d3 from "d3";
|
||||||
|
|
||||||
export function drawChart(height, width){
|
export function drawChart(height, width) {
|
||||||
|
d3.select("#chart")
|
||||||
d3.select("#chart")
|
.append("svg")
|
||||||
.append("svg")
|
.attr("width", width)
|
||||||
.attr("width", width)
|
.attr("height", height)
|
||||||
.attr("height", height)
|
.style("border", "1px solid black")
|
||||||
.style("border", "1px solid black")
|
|
||||||
.append("text")
|
|
||||||
.attr("fill", "green")
|
|
||||||
.attr("x", 50)
|
|
||||||
.attr("y", 50)
|
|
||||||
.text("Hello D3")
|
|
||||||
}
|
|
||||||
|
|
||||||
export function drawCircles(){
|
|
||||||
var svg = d3.select("#circles")
|
|
||||||
.append("svg")
|
|
||||||
.attr("width", 960)
|
|
||||||
.attr("height", 500)
|
|
||||||
.attr("bgcolor", "blue")
|
|
||||||
|
|
||||||
var background = svg.append("rect")
|
|
||||||
.attr("width", "100%")
|
|
||||||
.attr("height", "100%")
|
|
||||||
.attr("fill", "blue")
|
|
||||||
|
|
||||||
var ball = svg.append("circle")
|
|
||||||
.attr("r", 73)
|
|
||||||
.attr("cx", 480)
|
|
||||||
.attr("cy", 250)
|
|
||||||
.style("fill", "#ffe41e");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function drawGraph(){
|
|
||||||
let margin = {top: 20, right: 30, bottom: 20, left: 30};
|
|
||||||
let width = 900 - margin.left - margin.right;
|
|
||||||
let height = 600 - margin.top - margin.bottom;
|
|
||||||
|
|
||||||
var svg = d3.select("#graph")
|
|
||||||
.append("svg")
|
|
||||||
.attr("width", width + margin.left + margin.right)
|
|
||||||
.attr("height", height + margin.top + margin.bottom)
|
|
||||||
.append("g")
|
|
||||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
|
||||||
|
|
||||||
let data = ({
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "A"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"name": "C"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"name": "D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"name": "E"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"name": "F"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 7,
|
|
||||||
"name": "G"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"name": "H"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"name": "I"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10,
|
|
||||||
"name": "J"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
|
|
||||||
{
|
|
||||||
"source": 1,
|
|
||||||
"target": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": 1,
|
|
||||||
"target": 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": 1,
|
|
||||||
"target": 6
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"source": 2,
|
|
||||||
"target": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": 2,
|
|
||||||
"target": 7
|
|
||||||
}
|
|
||||||
,
|
|
||||||
|
|
||||||
{
|
|
||||||
"source": 3,
|
|
||||||
"target": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": 8,
|
|
||||||
"target": 3
|
|
||||||
}
|
|
||||||
,
|
|
||||||
{
|
|
||||||
"source": 4,
|
|
||||||
"target": 5
|
|
||||||
}
|
|
||||||
,
|
|
||||||
|
|
||||||
{
|
|
||||||
"source": 4,
|
|
||||||
"target": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": 5,
|
|
||||||
"target": 10
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(data)
|
|
||||||
// List of node names
|
|
||||||
var allNodes = data.nodes.map(function(d){return d.name})
|
|
||||||
|
|
||||||
// A linear scale to position the nodes on the X axis
|
|
||||||
var x = d3.scalePoint()
|
|
||||||
.range([0, width])
|
|
||||||
.domain(allNodes)
|
|
||||||
|
|
||||||
// Add the circle for the nodes
|
|
||||||
svg
|
|
||||||
.selectAll("mynodes")
|
|
||||||
.data(data.nodes)
|
|
||||||
.enter()
|
|
||||||
.append("circle")
|
|
||||||
.attr("cx", function(d){ return(x(d.name))})
|
|
||||||
.attr("cy", height-30)
|
|
||||||
.attr("r", 8)
|
|
||||||
.style("fill", "#69b3a2")
|
|
||||||
|
|
||||||
// And give them a label
|
|
||||||
svg
|
|
||||||
.selectAll("mylabels")
|
|
||||||
.data(data.nodes)
|
|
||||||
.enter()
|
|
||||||
.append("text")
|
|
||||||
.attr("x", function(d){ return(x(d.name))})
|
|
||||||
.attr("y", height-10)
|
|
||||||
.text(function(d){ return(d.name)})
|
|
||||||
.style("text-anchor", "middle")
|
|
||||||
|
|
||||||
// Add links between nodes. Here is the tricky part.
|
|
||||||
// In my input data, links are provided between nodes -id-, NOT between node names.
|
|
||||||
// So I have to do a link between this id and the name
|
|
||||||
var idToNode = {};
|
|
||||||
data.nodes.forEach(function (n) {
|
|
||||||
idToNode[n.id] = n;
|
|
||||||
});
|
|
||||||
// Cool, now if I do idToNode["2"].name I've got the name of the node with id 2
|
|
||||||
|
|
||||||
// Add the links
|
|
||||||
svg
|
|
||||||
.selectAll('mylinks')
|
|
||||||
.data(data.links)
|
|
||||||
.enter()
|
|
||||||
.append('path')
|
|
||||||
.attr('d', function (d) {
|
|
||||||
let start = x(idToNode[d.source].name)
|
|
||||||
// X position of start node on the X axis
|
|
||||||
let end = x(idToNode[d.target].name)
|
|
||||||
// X position of end node
|
|
||||||
return ['M',
|
|
||||||
start,
|
|
||||||
height-30,
|
|
||||||
// the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
|
|
||||||
'A',
|
|
||||||
// This means we're gonna build an elliptical arc
|
|
||||||
(start - end)/2, ',',
|
|
||||||
// Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
|
|
||||||
(start - end)/2, 0, 0, ',',
|
|
||||||
start < end ? 1 : 0, end, ',', height-30]
|
|
||||||
// We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
|
|
||||||
.join(' ');
|
|
||||||
})
|
|
||||||
.style("fill", "none")
|
|
||||||
.attr("stroke", "black")
|
|
||||||
|
|
||||||
// labels for links
|
|
||||||
svg
|
|
||||||
.selectAll('mylinks')
|
|
||||||
.data(data.links)
|
|
||||||
.enter()
|
|
||||||
.append("text")
|
|
||||||
.attr("x", function(d){
|
|
||||||
let start = x(idToNode[d.source].name)
|
|
||||||
// X position of start node on the X axis
|
|
||||||
let end = x(idToNode[d.target].name)
|
|
||||||
// X position of end node
|
|
||||||
return start + (end-start)/2
|
|
||||||
})
|
|
||||||
.attr("y", function(d){
|
|
||||||
let start = x(idToNode[d.source].name)
|
|
||||||
// X position of start node on the X axis
|
|
||||||
let end = x(idToNode[d.target].name)
|
|
||||||
// X position of end node
|
|
||||||
return height-30-(Math.abs(start-end)/2)//height-30
|
|
||||||
})
|
|
||||||
.text(function(d){ return(`${idToNode[d.source].name}-${idToNode[d.target].name}`)})
|
|
||||||
.style("text-anchor", "top")
|
|
||||||
|
|
||||||
svg.selectAll("text").data(data.links).enter()
|
|
||||||
.append("text")
|
.append("text")
|
||||||
.attr("x", function(d) { return d.source.x + (d.target.x - d.source.x)/2; })
|
.attr("fill", "green")
|
||||||
.attr("y", function(d) { return d.source.y + (d.target.y - d.source.y)/2; })
|
.attr("x", 50)
|
||||||
.text(function(d) { return d.something; });
|
.attr("y", 50)
|
||||||
|
.text("Hello D3");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawCircles() {
|
||||||
|
var svg = d3
|
||||||
|
.select("#circles")
|
||||||
|
.append("svg")
|
||||||
|
.attr("width", 960)
|
||||||
|
.attr("height", 500)
|
||||||
|
.attr("bgcolor", "blue");
|
||||||
|
|
||||||
|
var background = svg
|
||||||
|
.append("rect")
|
||||||
|
.attr("width", "100%")
|
||||||
|
.attr("height", "100%")
|
||||||
|
.attr("fill", "blue");
|
||||||
|
|
||||||
|
var ball = svg
|
||||||
|
.append("circle")
|
||||||
|
.attr("r", 73)
|
||||||
|
.attr("cx", 480)
|
||||||
|
.attr("cy", 250)
|
||||||
|
.style("fill", "#ffe41e");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawGraph() {
|
||||||
|
let margin = { top: 20, right: 30, bottom: 20, left: 30 };
|
||||||
|
let width = 900 - margin.left - margin.right;
|
||||||
|
let height = 600 - margin.top - margin.bottom;
|
||||||
|
|
||||||
|
var svg = d3
|
||||||
|
.select("#graph")
|
||||||
|
.append("svg")
|
||||||
|
.attr("width", width + margin.left + margin.right)
|
||||||
|
.attr("height", height + margin.top + margin.bottom)
|
||||||
|
.append("g")
|
||||||
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "A",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "B",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "C",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "D",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "E",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "F",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "G",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "H",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: "I",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: "J",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
source: 1,
|
||||||
|
target: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 1,
|
||||||
|
target: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 1,
|
||||||
|
target: 6,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
source: 2,
|
||||||
|
target: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 2,
|
||||||
|
target: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 3,
|
||||||
|
target: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 8,
|
||||||
|
target: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 4,
|
||||||
|
target: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 4,
|
||||||
|
target: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 5,
|
||||||
|
target: 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
// List of node names
|
||||||
|
var allNodes = data.nodes.map(function (d) {
|
||||||
|
return d.name;
|
||||||
|
});
|
||||||
|
|
||||||
|
// A linear scale to position the nodes on the X axis
|
||||||
|
var x = d3.scalePoint().range([0, width]).domain(allNodes);
|
||||||
|
|
||||||
|
// Add the circle for the nodes
|
||||||
|
svg
|
||||||
|
.selectAll("mynodes")
|
||||||
|
.data(data.nodes)
|
||||||
|
.enter()
|
||||||
|
.append("circle")
|
||||||
|
.attr("cx", function (d) {
|
||||||
|
return x(d.name);
|
||||||
|
})
|
||||||
|
.attr("cy", height - 30)
|
||||||
|
.attr("r", 8)
|
||||||
|
.style("fill", "#69b3a2");
|
||||||
|
|
||||||
|
// And give them a label
|
||||||
|
svg
|
||||||
|
.selectAll("mylabels")
|
||||||
|
.data(data.nodes)
|
||||||
|
.enter()
|
||||||
|
.append("text")
|
||||||
|
.attr("x", function (d) {
|
||||||
|
return x(d.name);
|
||||||
|
})
|
||||||
|
.attr("y", height - 10)
|
||||||
|
.text(function (d) {
|
||||||
|
return d.name;
|
||||||
|
})
|
||||||
|
.style("text-anchor", "middle");
|
||||||
|
|
||||||
|
// Add links between nodes. Here is the tricky part.
|
||||||
|
// In my input data, links are provided between nodes -id-, NOT between node names.
|
||||||
|
// So I have to do a link between this id and the name
|
||||||
|
var idToNode = {};
|
||||||
|
data.nodes.forEach(function (n) {
|
||||||
|
idToNode[n.id] = n;
|
||||||
|
});
|
||||||
|
// Cool, now if I do idToNode["2"].name I've got the name of the node with id 2
|
||||||
|
|
||||||
|
// Add the links
|
||||||
|
svg
|
||||||
|
.selectAll("mylinks")
|
||||||
|
.data(data.links)
|
||||||
|
.enter()
|
||||||
|
.append("path")
|
||||||
|
.attr("d", function (d) {
|
||||||
|
let start = x(idToNode[d.source].name);
|
||||||
|
// X position of start node on the X axis
|
||||||
|
let end = x(idToNode[d.target].name);
|
||||||
|
// X position of end node
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
"M",
|
||||||
|
start,
|
||||||
|
height - 30,
|
||||||
|
// the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
|
||||||
|
"A",
|
||||||
|
// This means we're gonna build an elliptical arc
|
||||||
|
(start - end) / 2,
|
||||||
|
",",
|
||||||
|
// Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
|
||||||
|
(start - end) / 2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
",",
|
||||||
|
start < end ? 1 : 0,
|
||||||
|
end,
|
||||||
|
",",
|
||||||
|
height - 30,
|
||||||
|
]
|
||||||
|
// We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
|
||||||
|
.join(" ")
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.style("fill", "none")
|
||||||
|
.attr("stroke", "black");
|
||||||
|
|
||||||
|
// labels for links
|
||||||
|
svg
|
||||||
|
.selectAll("mylinks")
|
||||||
|
.data(data.links)
|
||||||
|
.enter()
|
||||||
|
.append("text")
|
||||||
|
.attr("x", function (d) {
|
||||||
|
let start = x(idToNode[d.source].name);
|
||||||
|
// X position of start node on the X axis
|
||||||
|
let end = x(idToNode[d.target].name);
|
||||||
|
// X position of end node
|
||||||
|
return start + (end - start) / 2;
|
||||||
|
})
|
||||||
|
.attr("y", function (d) {
|
||||||
|
let start = x(idToNode[d.source].name);
|
||||||
|
// X position of start node on the X axis
|
||||||
|
let end = x(idToNode[d.target].name);
|
||||||
|
// X position of end node
|
||||||
|
return height - 30 - Math.abs(start - end) / 2; //height-30
|
||||||
|
})
|
||||||
|
.text(function (d) {
|
||||||
|
return `${idToNode[d.source].name}-${idToNode[d.target].name}`;
|
||||||
|
})
|
||||||
|
.style("text-anchor", "top");
|
||||||
|
|
||||||
|
svg
|
||||||
|
.selectAll("text")
|
||||||
|
.data(data.links)
|
||||||
|
.enter()
|
||||||
|
.append("text")
|
||||||
|
.attr("x", function (d) {
|
||||||
|
return d.source.x + (d.target.x - d.source.x) / 2;
|
||||||
|
})
|
||||||
|
.attr("y", function (d) {
|
||||||
|
return d.source.y + (d.target.y - d.source.y) / 2;
|
||||||
|
})
|
||||||
|
.text(function (d) {
|
||||||
|
return d.something;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function D3Experiment() {
|
export function D3Experiment() {
|
||||||
|
useEffect(() => {
|
||||||
|
drawGraph();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
return (
|
||||||
drawGraph();
|
<div>
|
||||||
}, []);
|
<div id="chart"></div>
|
||||||
|
<div id="circles"></div>
|
||||||
return (
|
<div id="graph"></div>
|
||||||
<div>
|
</div>
|
||||||
<div id="chart">
|
);
|
||||||
</div>
|
|
||||||
<div id="circles">
|
|
||||||
</div>
|
|
||||||
<div id="graph">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default D3Experiment;
|
||||||
|
|
||||||
export default D3Experiment;
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
|
|
||||||
export function DataSetChanger({handleSubmit}){
|
export function DataSetChanger({ handleSubmit }) {
|
||||||
let [value, setValue] = useState(`[
|
let [value, setValue] = useState(`[
|
||||||
{
|
{
|
||||||
"name": "Some element. The name field is necessary",
|
"name": "Some element. The name field is necessary",
|
||||||
|
@ -18,34 +18,35 @@ export function DataSetChanger({handleSubmit}){
|
||||||
"isReferenceValue": true,
|
"isReferenceValue": true,
|
||||||
"somethirdfield": "c"
|
"somethirdfield": "c"
|
||||||
}
|
}
|
||||||
]`)
|
]`);
|
||||||
const [displayingDoneMessage, setDisplayingDoneMessage] = useState(false)
|
const [displayingDoneMessage, setDisplayingDoneMessage] = useState(false);
|
||||||
const [displayingDoneMessageTimer, setDisplayingDoneMessageTimer] = useState(null)
|
const [displayingDoneMessageTimer, setDisplayingDoneMessageTimer] =
|
||||||
|
useState(null);
|
||||||
|
|
||||||
let handleChange = (event) => {
|
let handleChange = (event) => {
|
||||||
setValue(event.target.value)
|
setValue(event.target.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
let handleSubmitInner = (event) => {
|
let handleSubmitInner = (event) => {
|
||||||
clearTimeout(displayingDoneMessageTimer)
|
clearTimeout(displayingDoneMessageTimer);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//console.log(event)
|
//console.log(event)
|
||||||
console.log("value@handleSubmitInner@DataSetChanger")
|
console.log("value@handleSubmitInner@DataSetChanger");
|
||||||
//console.log(typeof(value));
|
//console.log(typeof(value));
|
||||||
console.log(value);
|
console.log(value);
|
||||||
try{
|
try {
|
||||||
let newData = JSON.parse(value)
|
let newData = JSON.parse(value);
|
||||||
//console.log(typeof(newData))
|
//console.log(typeof(newData))
|
||||||
//console.log(newData)
|
//console.log(newData)
|
||||||
handleSubmit(newData)
|
handleSubmit(newData);
|
||||||
if(!newData.length || newData.length < 2){
|
if (!newData.length || newData.length < 2) {
|
||||||
throw Error("Not enough objects")
|
throw Error("Not enough objects");
|
||||||
}
|
}
|
||||||
setDisplayingDoneMessage(true)
|
setDisplayingDoneMessage(true);
|
||||||
let timer = setTimeout(() => setDisplayingDoneMessage(false), 3000);
|
let timer = setTimeout(() => setDisplayingDoneMessage(false), 3000);
|
||||||
setDisplayingDoneMessageTimer(timer)
|
setDisplayingDoneMessageTimer(timer);
|
||||||
}catch(error){
|
} catch (error) {
|
||||||
setDisplayingDoneMessage(false)
|
setDisplayingDoneMessage(false);
|
||||||
//alert(error)
|
//alert(error)
|
||||||
//console.log(error)
|
//console.log(error)
|
||||||
let substituteText = `Error: ${error.message}
|
let substituteText = `Error: ${error.message}
|
||||||
|
@ -70,34 +71,39 @@ Try something like:
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
Your old input was: ${value}`
|
Your old input was: ${value}`;
|
||||||
setValue(substituteText)
|
setValue(substituteText);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmitInner} className="inline">
|
<form onSubmit={handleSubmitInner} className="inline">
|
||||||
<br/>
|
<br />
|
||||||
<br/>
|
<br />
|
||||||
<textarea
|
<textarea
|
||||||
value={value}
|
value={value}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
rows="10" cols="50"
|
rows="10"
|
||||||
|
cols="50"
|
||||||
className=""
|
className=""
|
||||||
/>
|
/>
|
||||||
<br/>
|
<br />
|
||||||
<button
|
<button
|
||||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5 p-10"
|
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5 p-10"
|
||||||
onClick={handleSubmitInner}>
|
onClick={handleSubmitInner}
|
||||||
|
>
|
||||||
Change dataset
|
Change dataset
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={displayingDoneMessage ? "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5 p-10" : "hidden"}
|
className={
|
||||||
|
displayingDoneMessage
|
||||||
|
? "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5 p-10"
|
||||||
|
: "hidden"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Done!
|
Done!
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,25 +3,28 @@ import ReactMarkdown from "react-markdown";
|
||||||
import gfm from "remark-gfm";
|
import gfm from "remark-gfm";
|
||||||
|
|
||||||
if (!String.prototype.replaceAll) {
|
if (!String.prototype.replaceAll) {
|
||||||
String.prototype.replaceAll = function(str, newStr){
|
String.prototype.replaceAll = function (str, newStr) {
|
||||||
|
// If a regex pattern
|
||||||
|
if (
|
||||||
|
Object.prototype.toString.call(str).toLowerCase() === "[object regexp]"
|
||||||
|
) {
|
||||||
|
return this.replace(str, newStr);
|
||||||
|
}
|
||||||
|
|
||||||
// If a regex pattern
|
// If a string
|
||||||
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
|
return this.replace(new RegExp(str, "g"), newStr);
|
||||||
return this.replace(str, newStr);
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a string
|
export function DisplayAsMarkdown({ markdowntext, className }) {
|
||||||
return this.replace(new RegExp(str, 'g'), newStr);
|
//console.log(markdowntext)
|
||||||
|
markdowntext = markdowntext.replaceAll("\n", "\n\n");
|
||||||
};
|
return (
|
||||||
|
<ReactMarkdown
|
||||||
|
plugins={[gfm]}
|
||||||
|
children={markdowntext}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DisplayAsMarkdown({markdowntext, className}){
|
|
||||||
//console.log(markdowntext)
|
|
||||||
markdowntext = markdowntext.replaceAll("\n", "\n\n")
|
|
||||||
return( <ReactMarkdown
|
|
||||||
plugins={[gfm]}
|
|
||||||
children={markdowntext}
|
|
||||||
className={className}
|
|
||||||
/>)
|
|
||||||
}
|
|
|
@ -1,31 +1,44 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
let capitalizeFirstLetter = (string) => string.charAt(0).toUpperCase() + string.slice(1)
|
let capitalizeFirstLetter = (string) =>
|
||||||
|
string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
|
||||||
|
export function DisplayElement({ element }) {
|
||||||
|
let otherkeys = Object.keys(element).filter(
|
||||||
|
(key) =>
|
||||||
|
key != "name" && key != "url" && key != "id" && key != "isReferenceValue"
|
||||||
|
);
|
||||||
|
let othervalues = otherkeys.map((key) => element[key]);
|
||||||
|
let otherpairs = otherkeys.map((key, i) => ({
|
||||||
|
key: capitalizeFirstLetter(key),
|
||||||
|
value: othervalues[i],
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (element.url) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/*<a href={element.url} target="_blank">*/}
|
||||||
|
<h2>{`${element.name}`}</h2>
|
||||||
|
{/*</a>*/}
|
||||||
|
{otherpairs.map((pair) => (
|
||||||
|
<p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>
|
||||||
|
))}
|
||||||
|
<p>
|
||||||
|
<a href={element.url} target="_blank">
|
||||||
|
More info
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>{`${element.name}`}</h2>
|
||||||
|
{otherpairs.map((pair) => (
|
||||||
|
<p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function DisplayElement({element}){
|
|
||||||
let otherkeys = Object.keys(element).filter(key => key!="name" && key!="url" && key != "id" && key != "isReferenceValue")
|
|
||||||
let othervalues = otherkeys.map(key => element[key])
|
|
||||||
let otherpairs = otherkeys.map((key,i) => ({key: capitalizeFirstLetter(key), value: othervalues[i]}))
|
|
||||||
|
|
||||||
if(element.url){
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
{/*<a href={element.url} target="_blank">*/}
|
|
||||||
<h2>{`${element.name}`}</h2>
|
|
||||||
{/*</a>*/}
|
|
||||||
{otherpairs.map(pair => <p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>)}
|
|
||||||
<p>
|
|
||||||
<a href={element.url} target="_blank">More info</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<h2>{`${element.name}`}</h2>
|
|
||||||
{otherpairs.map(pair => <p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,14 +1,17 @@
|
||||||
import axios from "axios"
|
import axios from "axios";
|
||||||
|
|
||||||
const CONNECTION_IS_ACTIVE = true
|
const CONNECTION_IS_ACTIVE = true;
|
||||||
|
|
||||||
export async function pushToMongo(data){
|
export async function pushToMongo(data) {
|
||||||
if(CONNECTION_IS_ACTIVE){
|
if (CONNECTION_IS_ACTIVE) {
|
||||||
let response = await axios.post('https://server.loki.red/utility-function-extractor', {
|
let response = await axios.post(
|
||||||
data: data
|
"https://server.loki.red/utility-function-extractor",
|
||||||
})
|
{
|
||||||
console.log(response)
|
data: data,
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// pushToMongo()
|
// pushToMongo()
|
||||||
|
|
||||||
|
|
123
lib/slider.js
123
lib/slider.js
|
@ -1,34 +1,34 @@
|
||||||
/* Imports */
|
/* Imports */
|
||||||
import { Slider, Rail, Handles, Tracks, Ticks } from "react-compound-slider";
|
import { Slider, Rail, Handles, Tracks, Ticks } from "react-compound-slider";
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
// https://sghall.github.io/react-compound-slider/#/getting-started/tutorial
|
// https://sghall.github.io/react-compound-slider/#/getting-started/tutorial
|
||||||
|
|
||||||
/* Definitions */
|
/* Definitions */
|
||||||
|
|
||||||
const sliderStyle = { // Give the slider some width
|
const sliderStyle = {
|
||||||
position: 'relative',
|
// Give the slider some width
|
||||||
width: '40em',
|
position: "relative",
|
||||||
|
width: "40em",
|
||||||
height: 40,
|
height: 40,
|
||||||
border: '5em',
|
border: "5em",
|
||||||
}
|
};
|
||||||
|
|
||||||
const railStyle = {
|
const railStyle = {
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
width: '100%',
|
width: "100%",
|
||||||
height: 15,
|
height: 15,
|
||||||
marginTop: 32.5,
|
marginTop: 32.5,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
backgroundColor: 'lightgrey',
|
backgroundColor: "lightgrey",
|
||||||
}
|
};
|
||||||
|
|
||||||
/* Support functions */
|
/* Support functions */
|
||||||
function Handle({
|
function Handle({
|
||||||
handle: { id, value, percent },
|
handle: { id, value, percent },
|
||||||
getHandleProps,
|
getHandleProps,
|
||||||
displayFunction,
|
displayFunction,
|
||||||
handleWidth
|
handleWidth,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="justify-center text-center text-gray-600 text-xs">
|
<div className="justify-center text-center text-gray-600 text-xs">
|
||||||
|
@ -37,50 +37,56 @@ function Handle({
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
left: `${percent}%`,
|
left: `${percent}%`,
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
marginLeft: -10,
|
marginLeft: -10,
|
||||||
marginTop: 2.5,
|
marginTop: 2.5,
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
cursor: 'pointer',
|
cursor: "pointer",
|
||||||
borderRadius: '0%',
|
borderRadius: "0%",
|
||||||
backgroundColor: '#374151',
|
backgroundColor: "#374151",
|
||||||
color: '#374151',
|
color: "#374151",
|
||||||
}}
|
}}
|
||||||
{...getHandleProps(id)}
|
{...getHandleProps(id)}
|
||||||
>
|
></div>
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Track({ source, target, getTrackProps }) {
|
function Track({ source, target, getTrackProps }) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
height: 17.5,
|
height: 17.5,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
marginTop: 8.25,
|
marginTop: 8.25,
|
||||||
backgroundColor: ' #3B82F6',
|
backgroundColor: " #3B82F6",
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
cursor: 'pointer',
|
cursor: "pointer",
|
||||||
left: `${source.percent}%`,
|
left: `${source.percent}%`,
|
||||||
width: `${target.percent - source.percent}%`,
|
width: `${target.percent - source.percent}%`,
|
||||||
}}
|
}}
|
||||||
{...getTrackProps() /* this will set up events if you want it to be clickeable (optional) */}
|
{
|
||||||
|
...getTrackProps() /* this will set up events if you want it to be clickeable (optional) */
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Body */
|
/* Body */
|
||||||
// Two functions, essentially identical.
|
// Two functions, essentially identical.
|
||||||
export function SliderElement({ onChange, value, displayFunction, domain }) {
|
export function SliderElement({ onChange, value, displayFunction, domain }) {
|
||||||
let toLogDomain = (arr) => [Math.log(arr[0]) / Math.log(10), Math.log(arr[1]) / Math.log(10)]
|
let toLogDomain = (arr) => [
|
||||||
|
Math.log(arr[0]) / Math.log(10),
|
||||||
|
Math.log(arr[1]) / Math.log(10),
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<Slider
|
<Slider
|
||||||
rootStyle={sliderStyle /* inline styles for the outer div. Can also use className prop. */}
|
rootStyle={
|
||||||
|
sliderStyle /* inline styles for the outer div. Can also use className prop. */
|
||||||
|
}
|
||||||
domain={toLogDomain([1 / domain, domain])}
|
domain={toLogDomain([1 / domain, domain])}
|
||||||
values={[value]}
|
values={[value]}
|
||||||
step={0.0001}
|
step={0.0001}
|
||||||
|
@ -88,14 +94,12 @@ export function SliderElement({ onChange, value, displayFunction, domain }) {
|
||||||
reversed={true}
|
reversed={true}
|
||||||
>
|
>
|
||||||
<Rail>
|
<Rail>
|
||||||
{({ getRailProps }) => (
|
{({ getRailProps }) => <div style={railStyle} {...getRailProps()} />}
|
||||||
<div style={railStyle} {...getRailProps()} />
|
|
||||||
)}
|
|
||||||
</Rail>
|
</Rail>
|
||||||
<Handles>
|
<Handles>
|
||||||
{({ handles, getHandleProps }) => (
|
{({ handles, getHandleProps }) => (
|
||||||
<div className="slider-handles">
|
<div className="slider-handles">
|
||||||
{handles.map(handle => (
|
{handles.map((handle) => (
|
||||||
<Handle
|
<Handle
|
||||||
key={handle.id}
|
key={handle.id}
|
||||||
handle={handle}
|
handle={handle}
|
||||||
|
@ -122,33 +126,54 @@ export function SliderElement({ onChange, value, displayFunction, domain }) {
|
||||||
)}
|
)}
|
||||||
</Tracks>
|
</Tracks>
|
||||||
</Slider>
|
</Slider>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SubmitSliderButton({ posList, binaryComparisons, sliderValue, reasoning, toComparePair, nextStepSlider, dontPushSubmitButtonAnyMore }) {
|
export function SubmitSliderButton({
|
||||||
|
posList,
|
||||||
|
binaryComparisons,
|
||||||
|
sliderValue,
|
||||||
|
reasoning,
|
||||||
|
toComparePair,
|
||||||
|
nextStepSlider,
|
||||||
|
dontPushSubmitButtonAnyMore,
|
||||||
|
}) {
|
||||||
// This element didn't necessarily have to exist, but it made it easier for debugging purposes
|
// This element didn't necessarily have to exist, but it made it easier for debugging purposes
|
||||||
let onClick = (event) => {
|
let onClick = (event) => {
|
||||||
if(!dontPushSubmitButtonAnyMore){
|
if (!dontPushSubmitButtonAnyMore) {
|
||||||
//event.preventDefault();
|
//event.preventDefault();
|
||||||
let obj = { posList, binaryComparisons, sliderValue, reasoning, element1: toComparePair[1], element2: toComparePair[0] }
|
let obj = {
|
||||||
|
posList,
|
||||||
|
binaryComparisons,
|
||||||
|
sliderValue,
|
||||||
|
reasoning,
|
||||||
|
element1: toComparePair[1],
|
||||||
|
element2: toComparePair[0],
|
||||||
|
};
|
||||||
//
|
//
|
||||||
console.log("input@SubmitSliderButton")
|
console.log("input@SubmitSliderButton");
|
||||||
console.log(obj)
|
console.log(obj);
|
||||||
if (!!Number(sliderValue) && sliderValue >= 0) {
|
if (!!Number(sliderValue) && sliderValue >= 0) {
|
||||||
nextStepSlider(obj)
|
nextStepSlider(obj);
|
||||||
} else if (!!Number(sliderValue) && sliderValue < 0) {
|
} else if (!!Number(sliderValue) && sliderValue < 0) {
|
||||||
alert("Negative numbers not yet allowed")
|
alert("Negative numbers not yet allowed");
|
||||||
} else {
|
} else {
|
||||||
alert("Your input is not a number")
|
alert("Your input is not a number");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return (<button
|
return (
|
||||||
className={!dontPushSubmitButtonAnyMore ? "bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5" : "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5"}
|
<button
|
||||||
onClick={onClick}>
|
className={
|
||||||
Submit
|
!dontPushSubmitButtonAnyMore
|
||||||
</button>)
|
? "bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||||
|
: "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5"
|
||||||
|
}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
|
@ -1,53 +1,42 @@
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
"source": 3,
|
||||||
|
|
||||||
|
"target": 4,
|
||||||
|
|
||||||
|
"distance": 5
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"source": 2,
|
||||||
|
|
||||||
|
"target": 3,
|
||||||
|
|
||||||
|
"distance": 4
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"source": 0,
|
||||||
|
|
||||||
|
"target": 1,
|
||||||
|
|
||||||
|
"distance": 4
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"source": 0,
|
||||||
|
|
||||||
|
"target": 2,
|
||||||
|
|
||||||
|
"distance": 5
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"source": 1,
|
||||||
|
|
||||||
|
"target": 2,
|
||||||
|
|
||||||
|
"distance": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"source": 3,
|
|
||||||
|
|
||||||
"target": 4,
|
|
||||||
|
|
||||||
"distance": 5
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"source": 2,
|
|
||||||
|
|
||||||
"target": 3,
|
|
||||||
|
|
||||||
"distance": 4
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"source": 0,
|
|
||||||
|
|
||||||
"target": 1,
|
|
||||||
|
|
||||||
"distance": 4
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"source": 0,
|
|
||||||
|
|
||||||
"target": 2,
|
|
||||||
|
|
||||||
"distance": 5
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"source": 1,
|
|
||||||
|
|
||||||
"target": 2,
|
|
||||||
|
|
||||||
"distance": 5
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
|
@ -5,25 +5,28 @@
|
||||||
|
|
||||||
/* Imports */
|
/* Imports */
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import fs from 'fs';
|
import fs from "fs";
|
||||||
import path from 'path';
|
import path from "path";
|
||||||
import ComparisonView from '../lib/comparisonView.js'
|
import ComparisonView from "../lib/comparisonView.js";
|
||||||
|
|
||||||
/* Definitions */
|
/* Definitions */
|
||||||
const elementsDocument = '../data/listOfMoralGoods.json'
|
const elementsDocument = "../data/listOfMoralGoods.json";
|
||||||
|
|
||||||
/* React components */
|
/* React components */
|
||||||
export async function getStaticProps() {
|
export async function getStaticProps() {
|
||||||
const directory = path.join(process.cwd(), "pages")
|
const directory = path.join(process.cwd(), "pages");
|
||||||
let listOfElementsForView = JSON.parse(fs.readFileSync(path.join(directory, elementsDocument), 'utf8'));
|
let listOfElementsForView = JSON.parse(
|
||||||
|
fs.readFileSync(path.join(directory, elementsDocument), "utf8")
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
listOfElementsForView
|
listOfElementsForView,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main react component
|
// Main react component
|
||||||
export default function Home({ listOfElementsForView }) {
|
export default function Home({ listOfElementsForView }) {
|
||||||
return(<ComparisonView listOfElementsForView={listOfElementsForView}/>)
|
return <ComparisonView listOfElementsForView={listOfElementsForView} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,4 +26,4 @@ export async function getStaticProps() {
|
||||||
// Main react component
|
// Main react component
|
||||||
export default function Home({ listOfElementsForView }) {
|
export default function Home({ listOfElementsForView }) {
|
||||||
return(<ComparisonView listOfElementsForView={listOfElementsForView}/>)
|
return(<ComparisonView listOfElementsForView={listOfElementsForView}/>)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user