# HG changeset patch # User drewp@bigasterisk.com # Date 1647672084 25200 # Node ID 3cdbbd913f1dba6d8a3b5fecf65bfea5eb265c84 # Parent cbcd82d2135630c4bde9ee852765a93d636774f6 table displays now just barely diff -r cbcd82d21356 -r 3cdbbd913f1d src/layout/Layout.ts --- a/src/layout/Layout.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/layout/Layout.ts Fri Mar 18 23:41:24 2022 -0700 @@ -2,7 +2,7 @@ import Immutable from "immutable"; // mostly using this for the builtin equals() testing, since NamedNode(x)!=NamedNode(x) import { NamedNode, Quad, Store, Term } from "n3"; -import { rdf } from "./namespaces"; +import { rdf, rdfs } from "./namespaces"; import { uniqueSortedTerms } from "./rdf_value"; import { TableDesc, ViewConfig } from "./ViewConfig"; @@ -16,7 +16,8 @@ export interface AlignedTable { columnHeaders: ColumnHeader[]; - rows: (Term | null)[][]; // each row is 1 wider than columnHeaders since the 1st element is the subject for that row + rowHeaders: NamedNode[]; + rows: Term[][][]; } export interface PredRow { @@ -37,51 +38,72 @@ sections: (AlignedTable | FreeStatements)[]; } +interface ISP { + subj: NamedNode; + pred: NamedNode; +} +const makeSP = Immutable.Record({ + subj: new NamedNode(""), + pred: new NamedNode(""), +}); + class AlignedTableBuilder { - columnPreds = Immutable.List(); - subjRowIndices = Immutable.Map(); - rows: (Term | null)[][] = []; + subjSet = Immutable.Set(); + predSet = Immutable.Set(); + cell = Immutable.Map>(); constructor( public rdfType: NamedNode /* plus join types, sort instructions */ ) {} addQuad(q: Quad) { + const subj = q.subject as NamedNode; const pred = q.predicate as NamedNode; - const omittedColumn = pred.equals(rdf.type); - if (!this.columnPreds.contains(pred) && !omittedColumn) { - this.columnPreds = this.columnPreds.push(pred); // this is putting cols in random order - this.rows.forEach((r) => r.push(null)); + this.subjSet = this.subjSet.add(subj); + this.predSet = this.predSet.add(pred); + + const key =subj.id+pred.id//makeSP({ subj, pred }); + const cur = this.cell.get(key, undefined); + const newval = + cur === undefined ? Immutable.Set([q.object]) : cur.add(q.object); + + this.cell = this.cell.set(key, newval); + } + + value(): AlignedTable { + let preds = uniqueSortedTerms(this.predSet); + const tagged = preds.map((p, i)=>{ + if (p.equals(rdf.type)) { + i=999; + } + if (p.equals(rdfs.label)) { + i=-1 + } + return {sort:i, val: p} + }) + tagged.sort((a,b)=>{ + return a.sort - b.sort; + }); + preds = tagged.map((e)=>e.val); + + // const omittedColumn = pred.equals(rdf.type); + const subjs = uniqueSortedTerms(this.subjSet); + const outputGrid: Term[][][] = []; + for (let subj of subjs) { + const row: Term[][] = []; + preds.forEach((pred) => { + const key = subj.id+pred.id;//makeSP({ subj, pred }); + const objs = this.cell.get(key, Immutable.Set([])); + const uniq = uniqueSortedTerms(objs); + console.log("cell objs", objs.size, uniq.length); + row.push(uniq); + }); + outputGrid.push(row); } - const predIndex = omittedColumn ? null : this.columnPreds.indexOf(pred); - let rowIndex = this.subjRowIndices.get(q.subject as NamedNode); - if (rowIndex === undefined) { - const newRow = new Array(1 + this.columnPreds.size).fill(null); - newRow[0] = q.subject; - this.rows.push(newRow); - rowIndex = this.rows.length - 1; - this.subjRowIndices = this.subjRowIndices.set( - q.subject as NamedNode, - rowIndex - ); - } - if (predIndex !== null) { - this.rows[rowIndex][1 + predIndex] = q.object; - } - } - - value(): AlignedTable { - this.rows.sort((a, b) => { - const uriA = (a[0] as NamedNode).value, - uriB = (b[0] as NamedNode).value; - return uriA.localeCompare(uriB); + const headers = preds.map((pred) => { + return { rdfType: this.rdfType, pred: pred }; }); - const headers = this.columnPreds - .map((pred) => { - return { rdfType: this.rdfType, pred: pred }; - }) - .toArray(); - return { columnHeaders: headers, rows: this.rows }; + return { columnHeaders: headers, rowHeaders: subjs, rows: outputGrid }; } } @@ -95,11 +117,13 @@ return Immutable.Set(typesToGather); } -function findSubjectsWithTypes(graph: Store, typesToGatherSet: UriSet): UriSet { +function findSubjectsWithTypes(graph: Store, typesToGather: UriSet): UriSet { const subjectsToGather: NamedNode[] = []; + const ft = typesToGather.toArray()[0]; graph.forEach( (q: Quad) => { - if (typesToGatherSet.contains(q.object as NamedNode)) { + if (q.object.equals(ft)) { + //typesToGather.has(q.object as NamedNode)) { subjectsToGather.push(q.subject as NamedNode); } }, @@ -142,22 +166,30 @@ export class Layout { constructor(public viewConfig?: ViewConfig) {} plan(graph: Store): LayoutResult { - const typesToGatherSet = findTypesNeededForTables(this.viewConfig); + const typesToTable = findTypesNeededForTables(this.viewConfig); - const subjectsToGatherSet = findSubjectsWithTypes(graph, typesToGatherSet); + const subjectsToTable = findSubjectsWithTypes(graph, typesToTable); const ungrouped: Quad[] = []; const vc = this.viewConfig; const table = vc && vc.tables.length > 0 - ? new AlignedTableBuilder(vc.tables[0].primary) + ? new AlignedTableBuilder(vc.tables[0].primary) //todo multiple tables : null; graph.forEach( (q: Quad) => { - if (!subjectsToGatherSet.contains(q.subject as NamedNode) || !table) { + let contains = false; + subjectsToTable.forEach((s) => { + if (s.equals(q.subject)) { + contains = true; + } + }); + + // if (subjectsToTable.has(q.subject as NamedNode) && table) { // not working + if (contains && table) { + table.addQuad(q); + } else { ungrouped.push(q); - } else { - table.addQuad(q); } }, null, @@ -167,6 +199,7 @@ ); const res: LayoutResult = { sections: [] }; if (table) { + console.log("table value"); res.sections.push(table.value()); } res.sections.push(freeStatmentsSection(ungrouped)); @@ -174,15 +207,6 @@ } } -// interface ISP { -// subj: NamedNode; -// pred: NamedNode; -// } -// const SP = Immutable.Record({ -// subj: new NamedNode(""), -// pred: new NamedNode(""), -// }); - // // One table of rows with a common rdf:type. // export class MultiSubjsTypeBlockLayout { // subjs: NamedNode[]; diff -r cbcd82d21356 -r 3cdbbd913f1d src/layout/ViewConfig.ts --- a/src/layout/ViewConfig.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/layout/ViewConfig.ts Fri Mar 18 23:41:24 2022 -0700 @@ -32,6 +32,7 @@ if (!url) { return; } + this.url = url; await fetchAndParse(url, this.graph); this._read(); diff -r cbcd82d21356 -r 3cdbbd913f1d src/layout/namespaces.ts --- a/src/layout/namespaces.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/layout/namespaces.ts Fri Mar 18 23:41:24 2022 -0700 @@ -6,6 +6,8 @@ export const EX = Util.prefix("http://example.com/"); export const rdf = { - type: namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), - }; - \ No newline at end of file + type: namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), +}; +export const rdfs = { + label: namedNode("http://www.w3.org/2000/01/rdf-schema#label"), +}; diff -r cbcd82d21356 -r 3cdbbd913f1d src/render/GraphView.ts --- a/src/render/GraphView.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/render/GraphView.ts Fri Mar 18 23:41:24 2022 -0700 @@ -1,7 +1,13 @@ import Immutable from "immutable"; import { html, TemplateResult } from "lit"; import { NamedNode, Quad, Store, Term } from "n3"; -import { AlignedTable, FreeStatements, Layout, PredRow, SubjRow } from "../layout/Layout"; +import { + AlignedTable, + FreeStatements, + Layout, + PredRow, + SubjRow, +} from "../layout/Layout"; import { SuffixLabels } from "../layout/suffixLabels"; import { ViewConfig } from "../layout/ViewConfig"; import { NodeDisplay } from "./NodeDisplay"; @@ -27,9 +33,8 @@ let viewTitle = html` (no view)`; if (this.viewConfig?.url) { viewTitle = html` using view - ${this.viewConfig.label()}`; + ${this.viewConfig?.label()}`; } - // const tables = this.view.toplevelTables(typesPresent); return html`

@@ -78,27 +83,54 @@ } _renderAlignedTable(section: AlignedTable): TemplateResult { - return html`aligned table section`; + const heads = section.columnHeaders.map((ch) => { + return html`${this.nodeDisplay.render(ch.pred)}`; + }); + const cells = []; + + for (let rowIndex in section.rows) { + const headerCol = html`${this.nodeDisplay.render(section.rowHeaders[rowIndex])}`; + const bodyCols = [] + for (let cellObjs of section.rows[rowIndex]) { + const display = cellObjs.map( + (t) => html`
${this.nodeDisplay.render(t)}
` + ); + bodyCols.push(html`${display}`); + } + cells.push(html`${headerCol}${bodyCols}`); + } + return html` +
 {JSON.stringify(section.rows,null,'   ')}
+
+ + + + ${heads} + + + ${cells} + +
Subject
+
+ `; } _renderFreeStatements(section: FreeStatements): TemplateResult { const subjects: NamedNode[] = []; let subjPreds = Immutable.Map(); - + return html`
- grid has rowcount ${section.subjRows.length} + grid has rowcount ${section.subjRows.length} ${section.subjRows.map(this._subjPredObjsBlock.bind(this))}
`; } - _subjPredObjsBlock( row: SubjRow ): TemplateResult { + _subjPredObjsBlock(row: SubjRow): TemplateResult { return html`
${this.nodeDisplay.render(row.subj)} -
- ${row.predRows.map(this._predObjsBlock.bind(this))} -
+
${row.predRows.map(this._predObjsBlock.bind(this))}
`; } diff -r cbcd82d21356 -r 3cdbbd913f1d src/render/StreamedGraph.ts --- a/src/render/StreamedGraph.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/render/StreamedGraph.ts Fri Mar 18 23:41:24 2022 -0700 @@ -105,6 +105,9 @@ if ((this.graph as VersionedGraph).store && this.graph.store) { const vc = new ViewConfig(); + if (this.view) { + await vc.readFromUrl(this.view); // too often! + } await this._graphAreaShowGraph( new GraphView([this.url], this.graph.store, vc) diff -r cbcd82d21356 -r 3cdbbd913f1d src/render/style.ts --- a/src/render/style.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/render/style.ts Fri Mar 18 23:41:24 2022 -0700 @@ -83,6 +83,13 @@ #graphView table.typeBlock td { white-space: nowrap; } +#graphView table tr:nth-child(even) td:nth-child(even) { background: #1a191c; } +#graphView table tr:nth-child(even) td:nth-child(odd) { background: #181719; } +#graphView table tr:nth-child(odd) td:nth-child(even) { background: #201e22; } +#graphView table tr:nth-child(odd) td:nth-child(odd) { background: #1e1c1e; } +#graphView table td,#graphView table th { + vertical-align:top; +} #graphView table.typeBlock td .literal { padding-top: 1px; padding-bottom: 1px;