-
-
Save joepie91/3d6f1df5dacfee258a71405c79fd1ae4 to your computer and use it in GitHub Desktop.
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
app.engine("jsx", expressAsyncReact.createEngine({ | |
prepare: (template, locals) => { | |
return Promise.try(() => { | |
if (template.query != null) { | |
let queryArguments = (template.queryArguments != null) | |
? template.queryArguments(locals) | |
: {}; | |
return apiQuery(template.query, queryArguments); | |
} | |
}).then((result) => { | |
if (result == null) { | |
return {}; | |
} else { | |
if (result.errors != null && result.errors.length > 0) { | |
throw result.errors[0]; | |
} else { | |
return { | |
data: result.data | |
}; | |
} | |
} | |
}); | |
} | |
})); | |
app.set("view engine", "jsx"); | |
app.set("views", projectPath("src/views")); |
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
"use strict"; | |
const React = require("react"); | |
const classnames = require("classnames"); | |
const gql = require("../../../packages/graphql-interface/tag"); | |
const treecutter = require("../../../packages/treecutter"); | |
const Layout = require("../layout"); | |
function Indented({ depth, children }) { | |
return ( | |
<div style={{ paddingLeft: depth * 10 }}> | |
{children} | |
</div> | |
); | |
} | |
function MountEntry({ mount }) { | |
return <div className="mountpoint">{mount.mountpoint}</div>; | |
} | |
function PartitionEntry({partition, isLast}) { | |
function PartitionIndent({ children }) { | |
return ( | |
<Indented depth={partition._treecutterDepth}> | |
{children} | |
</Indented> | |
); | |
} | |
return ( | |
<tr className={classnames("partition", {last: isLast})}> | |
<td> | |
<PartitionIndent> | |
{partition.name} | |
</PartitionIndent> | |
</td> | |
<td> | |
<PartitionIndent> | |
{partition.size.toString()} | |
</PartitionIndent> | |
</td> | |
<td colSpan={5}> | |
<PartitionIndent> | |
{(partition.mounts.length > 0) | |
? partition.mounts.map((mount) => <MountEntry mount={mount} />) | |
: <span className="notMounted">(not mounted)</span> | |
} | |
</PartitionIndent> | |
</td> | |
</tr> | |
); | |
} | |
function DriveEntry({drive}) { | |
let hasPartitions = (drive.partitions.length > 0); | |
return (<> | |
<tr className={classnames({hasPartitions})}> | |
<td className={classnames("smart", drive.smartHealth)} rowSpan={1 + drive.partitions.length} /> | |
<td>{drive.path}</td> | |
<td>{drive.size.toDisplay(2).toString()}</td> | |
<td> | |
{(drive.rpm != null) | |
? `${drive.rpm} RPM` | |
: null | |
} | |
</td> | |
<td>{drive.serialNumber}</td> | |
<td>{drive.model}</td> | |
<td>{drive.modelFamily}</td> | |
<td>{drive.firmwareVersion}</td> | |
</tr> | |
{drive.partitions.map((partition, i) => { | |
let isLast = (i === drive.partitions.length - 1); | |
return <PartitionEntry partition={partition} isLast={isLast} />; | |
})} | |
</>); | |
} | |
module.exports = { | |
query: gql` | |
query { | |
hardware { | |
drives { | |
path | |
smartHealth | |
size | |
rpm | |
serialNumber | |
model | |
modelFamily | |
firmwareVersion | |
blockDevice { | |
name | |
} | |
partitions: allBlockDevices { | |
_treecutterDepth | |
_treecutterSequenceNumber | |
name | |
size | |
mounts { | |
mountpoint | |
} | |
} | |
} | |
} | |
} | |
`, | |
template: function StorageDeviceList({data}) { | |
return ( | |
<Layout title="Storage Devices"> | |
<table className="drives"> | |
<tr> | |
<th>SMART</th> | |
<th>Device</th> | |
<th>Total size</th> | |
<th>RPM</th> | |
<th>Serial number</th> | |
<th>Model</th> | |
<th>Family</th> | |
<th>Firmware version</th> | |
</tr> | |
{data.hardware.drives.map((drive) => <DriveEntry drive={drive} />)} | |
</table> | |
</Layout> | |
); | |
} | |
}; |
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
"use strict"; | |
const Promise = require("bluebird"); | |
const React = require("react"); | |
const ReactDOMServer = require("react-dom/server"); | |
const defaultValue = require("default-value"); | |
const dotty = require("dotty"); | |
const registerBabel = require("./register-babel"); | |
const clearRequireCache = require("./clear-require-cache"); | |
/* FILEBUG: Express does not copy symbol-keyed properties from app.locals, but it probably should? */ | |
// let ExpressReact = Symbol("ExpressReact"); | |
let ExpressReact = "__EXPRESS_REACT_SETTINGS"; | |
let LocalsContext = React.createContext({}); | |
function componentAtPath(moduleRoot, componentPath) { | |
if (componentPath == null) { | |
return moduleRoot; | |
} else { | |
return dotty.get(moduleRoot, componentPath); | |
} | |
} | |
function renderComponent(component, locals, doctype = "<!DOCTYPE html>") { | |
let tree = React.createElement(LocalsContext.Provider, {value: locals}, | |
React.createElement(component, locals) | |
); | |
try { | |
/* TODO: Expose internals? Like koa-react */ | |
return doctype + ReactDOMServer.renderToStaticMarkup(tree); | |
} catch (err) { | |
if (/Element type is invalid:/.test(err.message)) { | |
throw new Error(`Expected a React component, but got '${component}' - maybe you forgot to specify a componentPath?`); | |
} else { | |
throw err; | |
} | |
} | |
} | |
module.exports = { | |
Settings: ExpressReact, | |
LocalsContext: LocalsContext, | |
createEngine: function createEngine({ prepare } = {}) { | |
let babelRegistered = false; | |
return function asyncRender(filename, options, callback) { | |
return Promise.try(() => { | |
let viewPaths = options.settings.views; | |
if (!babelRegistered) { | |
registerBabel(viewPaths); | |
babelRegistered = true; | |
} | |
let {componentPath} = defaultValue(options[ExpressReact], {}); | |
return Promise.try(() => { | |
let templateFile = require(filename); | |
let moduleRoot = defaultValue(templateFile.exports, templateFile); | |
return Promise.try(() => { | |
if (prepare != null) { | |
return prepare(moduleRoot, options); | |
} | |
}).then((result) => { | |
console.log("QUERY RESULT:", require("util").inspect(result, { colors: true, depth: null })); | |
let mergedOptions = Object.assign({}, options, result); | |
return renderComponent(componentAtPath(moduleRoot, componentPath), mergedOptions); | |
}); | |
}).finally(() => { | |
if (options.settings.env === "development") { | |
clearRequireCache(viewPaths); | |
} | |
}); | |
}).asCallback(callback); | |
}; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment