Mercurial > code > home > repos > streamed-graph
changeset 110:3cdbbd913f1d
table displays now just barely
author | drewp@bigasterisk.com |
---|---|
date | Fri, 18 Mar 2022 23:41:24 -0700 |
parents | cbcd82d21356 |
children | f08004002444 |
files | src/layout/Layout.ts src/layout/ViewConfig.ts src/layout/namespaces.ts src/render/GraphView.ts src/render/StreamedGraph.ts src/render/style.ts |
diffstat | 6 files changed, 136 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- 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<ISP>({ + subj: new NamedNode(""), + pred: new NamedNode(""), +}); + class AlignedTableBuilder { - columnPreds = Immutable.List<NamedNode>(); - subjRowIndices = Immutable.Map<NamedNode, number>(); - rows: (Term | null)[][] = []; + subjSet = Immutable.Set<NamedNode>(); + predSet = Immutable.Set<NamedNode>(); + cell = Immutable.Map<string, Immutable.Set<Term>>(); 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<Term>([])); + 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<ISP>({ -// subj: new NamedNode(""), -// pred: new NamedNode(""), -// }); - // // One table of rows with a common rdf:type. // export class MultiSubjsTypeBlockLayout { // subjs: NamedNode[];
--- 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();
--- 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"), +};
--- 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 - <a href="${this.viewConfig.url}">${this.viewConfig.label()}</a>`; + <a href="${this.viewConfig?.url}">${this.viewConfig?.label()}</a>`; } - // const tables = this.view.toplevelTables(typesPresent); return html` <section> <h2> @@ -78,27 +83,54 @@ } _renderAlignedTable(section: AlignedTable): TemplateResult { - return html`aligned table section`; + const heads = section.columnHeaders.map((ch) => { + return html`<th>${this.nodeDisplay.render(ch.pred)}</th>`; + }); + const cells = []; + + for (let rowIndex in section.rows) { + const headerCol = html`<th>${this.nodeDisplay.render(section.rowHeaders[rowIndex])}</th>`; + const bodyCols = [] + for (let cellObjs of section.rows[rowIndex]) { + const display = cellObjs.map( + (t) => html`<div>${this.nodeDisplay.render(t)}</div>` + ); + bodyCols.push(html`<td>${display}</td>`); + } + cells.push(html`<tr>${headerCol}${bodyCols}</tr>`); + } + return html` + <pre> {JSON.stringify(section.rows,null,' ')}</pre> + <div class="typeBlockScroll"> + <table class="typeBlock"> + <thead> + <th>Subject</th> + ${heads} + </thead> + <tbody> + ${cells} + </tbody> + </table> + </div> + `; } _renderFreeStatements(section: FreeStatements): TemplateResult { const subjects: NamedNode[] = []; let subjPreds = Immutable.Map<NamedNode, UriSet>(); - + return html`<div class="spoGrid"> - grid has rowcount ${section.subjRows.length} + grid has rowcount ${section.subjRows.length} ${section.subjRows.map(this._subjPredObjsBlock.bind(this))} </div>`; } - _subjPredObjsBlock( row: SubjRow ): TemplateResult { + _subjPredObjsBlock(row: SubjRow): TemplateResult { return html` <div class="subject"> ${this.nodeDisplay.render(row.subj)} <!-- todo: special section for uri/type-and-icon/label/comment --> - <div> - ${row.predRows.map(this._predObjsBlock.bind(this))} - </div> + <div>${row.predRows.map(this._predObjsBlock.bind(this))}</div> </div> `; }
--- 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)
--- 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;