import { createRoot } from "react-dom/client"; import { createElement as h, createContext, Fragment, useReducer, useState } from 'react'; import { css, cx } from '@emotion/css'; import { html } from 'htm'; import N from "./n.js"; import Pivot from "./pivot.js"; let columnNames = CSV.shift(); let columnTypes = ([...columnNames]).fill("hidden"); columnTypes[29] = "sum"; columnTypes[30] = "sum"; columnTypes[31] = "sum"; columnTypes[32] = "sum"; columnTypes[33] = "sum"; columnTypes[7 ] = "label"; columnTypes[8 ] = "label"; columnTypes[9 ] = "label"; columnTypes[10] = "label"; columnTypes[11] = "label"; Pivot.Init( columnTypes, columnNames, CSV ); let PivotForm = props => { let styles = css` position:realtive; box-sizing: border-box; padding: 10px; color:black; font-family:sans-serif; .Title { font-size:24px; font-weight:100; } .Section { padding:10px 0 10px 0; .Heading { display:inline-block; color:#666; font-family:sans-serif; font-size:12px; font-weight:900; text-transform:uppercase; } .Group { display:inline-block; padding:5px; border-radius:5px; margin:3px; background:rgba(0, 0, 0, 0.3) } } `; let pivotColumns = N.Step(Pivot.Schema, "label")||[]; let pivotColumnsUsed = N.Step(Pivot.Proto, "used-pivot")||[]; let sumColumns = N.Step(Pivot.Schema, "sum")||[]; //let sumColumnsUsed = N.Step(Pivot.Proto, "used-sum")||[]; let indiciesPivot = pivotColumnsUsed.map(node=>node.Meta.Index); let indiciesSum = sumColumns.map(node=>node.Meta.Index); //let indiciesSum = sumColumnsUsed.map(node=>node.Meta.Index); let displayPivotsAll = html`
Available Columns
${pivotColumns.map( columnPivot => { let attributes = {}; if(N.Step(columnPivot, "used-pivot", false)) { attributes.disabled = true; } else { attributes.onClick = e=> { N.Connect(Pivot.Proto, columnPivot, "used-pivot"); Render(); } } return html``; })}
`; let displayPivotsPending = null; if(pivotColumnsUsed.length) { displayPivotsPending = html`
Pending Pivot
${pivotColumnsUsed.map(columnPivot=>html` `)}
`; } return html`
Create New Pivot
${displayPivotsAll} ${displayPivotsPending}
`; } let Section = props => { let styles = css` .Heading { padding:6px 0 6px 0; color:#666; font-weight:900; font-size:12px; text-transform:uppercase; cursor:pointer; span { display:inline-block; width:20px; height:20px; margin-right:10px; border-radius:20px; background:black; color:white; text-align:center; } } .Heading:hover { color:black; } .Body { position:relative; padding:10px 0 20px 30px; &::before { content: " "; display:block; position:absolute; top:-8px; left:8px; width:3px; height:100%; background:black; } } `; let [openGet, openSet] = useState(false); return html`
openSet(!openGet)}> ${openGet ? `−` : `+`} ${props.label}
${ openGet ? html`
${props.children}
` : null }
`; } let ModificationsIcon = ({node}) => { let modsUp = N.Step(node, "ModifyUp", false)||[]; let modsDown = N.Step(node, "ModifyDown", false)||[]; let modsAt = N.Step(node, "ModifyAt", false)||[]; let modsOut = N.Step(node, "ModifyOut", false)||[]; var button = null; if(modsAt.length) { button = html``; } else { button = html``; } let padding = 7; let icon = 0; let styles = css` position:relative; display:inline-block; vertical-align:middle; width:${padding*2 + icon}px; height:${padding*2 + icon}px; margin:${padding*2}; .Icon { position:absolute; display:inline-block; width:${padding*2 + icon}px; height:${padding*2 + icon}px; text-align:center; font-size:9px; font-family:sans-serif; font-weight:900; line-height:${padding*2 + icon}px; &::after { content:" "; display:block; position:absolute; width:${icon}px; height:${icon}px; border:${padding}px solid transparent; } &.Down { left:0; bottom:100%; &::after { top:100%; border-top-color:green; border-bottom:0px solid transparent; } } &.At { top:0; left:100%; &::after { top:0; right:100%; border-right-color:red; border-left:0px solid transparent; } } &.Up { left:0; top:100%; &::after { bottom:100%; border-bottom-color:orange; border-top:0px solid transparent; } } &.Out { top:0; right:100%; &::after { top:0; left:100%; border-left-color:grey; border-right:0px solid transparent; } } } `; return html`
${modsDown.length ? html`
${modsDown.length}
` : null} ${modsAt.length ? html`${modsAt.length}` : null} ${modsUp.length ? html`${modsUp.length}` : null} ${modsOut.length ? html`${modsOut.length}` : null}
${button} `; }; let PivotBranch = props => { let row = props.node.Meta.Row; let displayCellsModify = row.map(column=>false); props.node.Meta.IndexSum.forEach(i=> { displayCellsModify[i] = html``; }); displayCellsModify.forEach((cell, i)=> { if(!cell) { displayCellsModify[i] = html`${row[i]}` } }); let displayCells = (node, visible) => { let output = []; node.Meta.Row.forEach((column, i)=> { if(visible[i]) { output.push( h("td", null, column) ); } } ); return output; } let stylesLeaf = css` background:#ddd; color:#333; `; return html` ${props.node.Meta.Label} <${ModificationsIcon} node=${props.node}> ${displayCells(props.node, props.visible)} ${(N.Step(props.node, "Leaf")||[]).map(leaf => { return html` <${ModificationsIcon} node=${leaf}> ${displayCells(leaf, props.visible)} `; } )} `; }; let PivotRoot = ({pivot}) => { let labelsDefault = (N.Step(Pivot.Schema, "hidden")||[]).map(column => column.Meta.Index); let labelsSum = (N.Step(Pivot.Schema, "sum")||[]).map(column => column.Meta.Index); let labelsPivot = (N.Step(Pivot.Schema, "label")||[]).map(column => column.Meta.Index); let labelsAll = (N.Step(Pivot.Schema, "all")||[]).map(column => column.Meta.Label); let labelsAllState = useState(labelsAll.map(column=>true)) let headersDisplay = []; labelsAllState[0].forEach((visible, index)=> { if(visible) { headersDisplay.push(html`${labelsAll[index]}`); } } ); let stylesRoot = css` display:block; box-sizing:border-box; padding:15px; font-family:sans-serif; `; let stylesHeading = css` margin: 0 0 15px 0; font-weight:0; font-size:24px; `; let modifiers = N.Step(pivot, "ModifyUp", false) || []; let handleDelete = ()=> { Pivot.Delete(pivot); Render(); }; let displayColumnGroup = (inAllLabels, inAllState, inIndicies) => { return html`
${inIndicies.map((index) => html``)}
`; }; let rows = []; N.ID.Walk++; N.Walk(n=>rows.push(h(PivotBranch, {node:n, visible:labelsAllState[0]}, null)), pivot, "Hierarchy"); return html`
${pivot.Meta.Label}
<${Section} key="settings" label=${`Settings`}> <${Section} key="columns" label="Columns">

Unused

${displayColumnGroup(labelsAll, labelsAllState, labelsDefault)}

Summation

${displayColumnGroup(labelsAll, labelsAllState, labelsSum)}

Pivot

${displayColumnGroup(labelsAll, labelsAllState, labelsPivot)} <${Section} key="tree" label=${"Tree"}> ${headersDisplay} ${rows}
LabelModifications
`; }; let ElRoot = props => { let pivots = N.Step(Pivot.Root, "Pivot")||[]; return h("div", null, [ h(PivotForm), pivots.map(pivot=>h(PivotRoot, {key:pivot.Meta.Label, pivot})) ]) }; const Root = createRoot(document.querySelector("#app")); const Render = () => Root.render(h(ElRoot)); Render();