-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #347 from concord-consortium/186622903-report-item
Implement tecrock-table report item, render table to string, inline CSS
- Loading branch information
Showing
13 changed files
with
695 additions
and
375 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import * as React from "react"; | ||
import { useInitMessage, useAutoSetHeight, useReportItem } from "@concord-consortium/lara-interactive-api"; | ||
import { ITectonicExplorerInteractiveState } from "@concord-consortium/tecrock-shared"; | ||
import { reportItemHandler } from "./report-item"; | ||
import { IAuthoredState } from "../../types"; | ||
|
||
interface Props { } | ||
|
||
export const AppComponent: React.FC<Props> = (props) => { | ||
const initMessage = useInitMessage(); | ||
|
||
useAutoSetHeight(); | ||
|
||
useReportItem<ITectonicExplorerInteractiveState, IAuthoredState>({ | ||
metadata: { | ||
compactAnswerReportItemsAvailable: true | ||
}, | ||
handler: reportItemHandler | ||
}); | ||
|
||
if (!initMessage) { | ||
return ( | ||
<div> | ||
Loading... | ||
</div> | ||
); | ||
} | ||
|
||
if (initMessage.mode !== "reportItem") { | ||
return ( | ||
<div> | ||
This interactive is only available in 'reportItem' mode but '{initMessage.mode}' was given. | ||
</div> | ||
); | ||
} | ||
|
||
// Report item app can provide UI in the prompt area too, but TecRock Table never does it. It only responds | ||
// to getReportItemAnswer post message from the host window (portal report). | ||
return null; | ||
}; |
31 changes: 31 additions & 0 deletions
31
packages/tecrock-table/src/components/report-item/render-to-string.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from "react"; | ||
import * as ReactDOM from "react-dom"; | ||
import { inlineContent } from "juice"; | ||
|
||
export const renderToString = (element: React.ReactNode) => { | ||
const div = document.createElement("div"); | ||
ReactDOM.render(element as any, div); | ||
return div.innerHTML; | ||
}; | ||
|
||
export const renderToStringWithCss = (element: React.ReactNode, css: string, classMap?: Record<string, string>) => { | ||
const html = renderToString(element); | ||
if (classMap) { | ||
css = replaceCssClassNames(css, classMap); | ||
} | ||
return inlineContent(html, css); | ||
}; | ||
|
||
// This function is useful to replace class names in a raw CSS string with new class names provided by CSS modules. | ||
export const replaceCssClassNames = (cssString: string, classMap: Record<string, string>): string => { | ||
// Create a regular expression that matches all keys in the classMap. | ||
const classNamesRegex = new RegExp(`\\.(${Object.keys(classMap).join('|')})`, 'g'); | ||
|
||
return cssString.replace(classNamesRegex, (match) => { | ||
// Extract the class name without the dot. | ||
const className = match.substring(1); | ||
|
||
// Replace with the new class name, re-adding the dot. | ||
return `.${classMap[className]}`; | ||
}); | ||
}; |
39 changes: 39 additions & 0 deletions
39
packages/tecrock-table/src/components/report-item/report-item.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from "react"; | ||
import * as semver from "semver"; | ||
import { sendReportItemAnswer, IReportItemAnswerItem, IGetReportItemAnswerHandler } from "@concord-consortium/lara-interactive-api"; | ||
import { IAuthoredState } from "../../types"; | ||
import { ITectonicExplorerInteractiveState } from "@concord-consortium/tecrock-shared"; | ||
import { renderToStringWithCss } from "./render-to-string"; | ||
|
||
import { Table } from "../table"; | ||
// The `.inline` suffix will trigger a Webpack loader that simply converts SCSS to CSS and returns it as a string. | ||
import inlineCss from "../table.inline.scss"; | ||
// Regular `.scss` files use CSS modules and return a map of class names to unique identifiers. This map is later | ||
// used to replace class names in the `inlineCss` file. | ||
import classMap from "../table.scss"; | ||
|
||
export const reportItemHandler: IGetReportItemAnswerHandler<ITectonicExplorerInteractiveState, IAuthoredState> = request => { | ||
const {platformUserId, version, itemsType} = request; | ||
|
||
if (!version) { | ||
// for hosts sending older, unversioned requests | ||
// tslint:disable-next-line:no-console | ||
console.error("TecRock Table Report Item Interactive: Missing version in getReportItemAnswer request."); | ||
} | ||
else if (semver.satisfies(version, "2.x")) { | ||
const items: IReportItemAnswerItem[] = []; | ||
const htmlWithInlineStyles = renderToStringWithCss( | ||
<Table interactiveState={request.interactiveState} />, | ||
inlineCss, | ||
classMap | ||
); | ||
items.push({type: "html", html: htmlWithInlineStyles}); | ||
sendReportItemAnswer({version, platformUserId, items, itemsType}); | ||
} else { | ||
// tslint:disable-next-line:no-console | ||
console.error( | ||
"TecRock Table Report Item Interactive: Unsupported version in getReportItemAnswer request:", | ||
version | ||
); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Inline CSS is the same as regular CSS, but it requires a different suffix so that Webpack can distinguish | ||
// between them and use a different loader for each one. | ||
@import "./table.scss"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
.tableAndSnapshots { | ||
display: flex; | ||
flex-direction: row; | ||
margin-top: 10px; | ||
|
||
.table { | ||
overflow-x: auto; | ||
margin-right: 10px; | ||
vertical-align: top; | ||
|
||
table { | ||
border-collapse: collapse; | ||
table-layout: auto; | ||
|
||
td, th { | ||
border: 0.5px solid #979797; | ||
padding: 4px; | ||
text-align: center; | ||
|
||
&.temperatureAndPressure { | ||
max-width: 100px; | ||
} | ||
&.type { | ||
max-width: 200px; | ||
} | ||
} | ||
|
||
td.notes { | ||
min-width: 200px; | ||
text-align: left; | ||
} | ||
} | ||
} | ||
|
||
.snapshots { | ||
// This will result in flex-grow: 1 and ensure that the snapshots will be as wide as possible. | ||
flex: 1; | ||
min-width: 30%; | ||
// Limit max size when snapshots are displayed in the report and user is using a big screen. In this case, | ||
// image could become much bigger than its native size. | ||
max-width: 1000px; | ||
|
||
.imgContainer { | ||
position: relative; | ||
width: 100%; | ||
margin-bottom: 5px; | ||
cursor: pointer; | ||
|
||
img { | ||
width: 100%; | ||
} | ||
|
||
svg { | ||
display: block; | ||
position: absolute; | ||
bottom: 3px; | ||
right: 3px; | ||
height: 30px; | ||
pointer-events: none; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.