@jsreport/jsreport-assets
Advanced tools
Comparing version 3.1.0 to 3.2.0
@@ -13,3 +13,3 @@ const fs = require('fs/promises') | ||
async function readAsset (reporter, definition, { id, name, encoding, currentPath }, req) { | ||
async function readAsset (reporter, definition, { id, name, encoding, currentDirectoryPath }, req) { | ||
const allowAssetsLinkedToFiles = definition.options.allowAssetsLinkedToFiles !== false | ||
@@ -67,4 +67,6 @@ | ||
assetName = [...pathParts].pop() | ||
const result = await reporter.folders.resolveEntityFromPath(name, 'assets', { currentPath }, req) | ||
const resolvedCurrentDirectoryPath = currentDirectoryPath != null ? await currentDirectoryPath() : null | ||
const result = await reporter.folders.resolveEntityFromPath(name, 'assets', { currentPath: resolvedCurrentDirectoryPath }, req) | ||
if (result) { | ||
@@ -71,0 +73,0 @@ assets = [result.entity] |
@@ -13,2 +13,3 @@ const fs = require('fs/promises') | ||
forceUpdate: { type: 'Edm.Boolean' }, | ||
sharedHelpersScope: { type: 'Edm.String', schema: { type: 'null', enum: [null, 'global', 'folder'] } }, | ||
isSharedHelper: { type: 'Edm.Boolean' }, | ||
@@ -15,0 +16,0 @@ link: { type: 'Edm.String' } |
@@ -112,3 +112,3 @@ const util = require('util') | ||
read: async (path, encoding, moduleMode = false) => { | ||
const r = await readAsset(reporter, definition, { id: null, name: path, encoding, moduleMode, currentPath: proxy.currentPath }, req) | ||
const r = await readAsset(reporter, definition, { id: null, name: path, encoding, moduleMode, currentDirectoryPath: proxy.currentDirectoryPath }, req) | ||
return r.content | ||
@@ -118,7 +118,84 @@ }, | ||
evaluateShared: async () => { | ||
const sharedHelpersAssets = await reporter.documentStore.collection('assets').find({ isSharedHelper: true }, req) | ||
const getSorterByName = () => { | ||
return (a, b) => { | ||
const nameA = a.name.toUpperCase() | ||
const nameB = b.name.toUpperCase() | ||
if (nameA < nameB) { | ||
return -1 | ||
} | ||
if (nameA > nameB) { | ||
return 1 | ||
} | ||
return 0 | ||
} | ||
} | ||
let globalAssetsHelpers = await reporter.documentStore.collection('assets').find({ | ||
$or: [ | ||
{ isSharedHelper: true }, | ||
{ sharedHelpersScope: 'global' } | ||
] | ||
}, req) | ||
globalAssetsHelpers = globalAssetsHelpers.filter((asset) => asset.sharedHelpersScope == null || asset.sharedHelpersScope === 'global') | ||
globalAssetsHelpers.sort(getSorterByName()) | ||
const folderAssetsHelpers = [] | ||
if (req.context.resolvedTemplate != null) { | ||
let currentEntity = req.context.resolvedTemplate | ||
const assetsHelpersByLevel = [] | ||
do { | ||
const folderQuery = currentEntity.folder != null ? { shortid: currentEntity.folder.shortid } : null | ||
const assetsHelpers = await reporter.documentStore.collection('assets').find({ | ||
sharedHelpersScope: 'folder', | ||
folder: folderQuery | ||
}, req) | ||
if (assetsHelpers.length > 0) { | ||
assetsHelpersByLevel.push([...assetsHelpers]) | ||
} | ||
if (currentEntity.folder != null) { | ||
currentEntity = await reporter.documentStore.collection('folders').findOne({ | ||
shortid: currentEntity.folder.shortid | ||
}, req) | ||
} else { | ||
currentEntity = null | ||
} | ||
} while (currentEntity != null) | ||
assetsHelpersByLevel.reverse() | ||
for (const currentAssetHelpers of assetsHelpersByLevel) { | ||
currentAssetHelpers.sort(getSorterByName()) | ||
folderAssetsHelpers.push(...currentAssetHelpers) | ||
} | ||
} else { | ||
// if anonymous request just search for asset helpers with scope "folder" at the top level | ||
const folders = await reporter.documentStore.collection('assets').find({ | ||
sharedHelpersScope: 'folder', | ||
folder: null | ||
}, req) | ||
folderAssetsHelpers.push(...folders) | ||
// sort alphabetically asc | ||
folderAssetsHelpers.sort(getSorterByName()) | ||
} | ||
const sharedHelpersAssets = [ | ||
...globalAssetsHelpers, | ||
...folderAssetsHelpers | ||
] | ||
for (const a of sharedHelpersAssets) { | ||
const asset = await readAsset(reporter, definition, { id: a._id, name: null, encoding: 'utf8' }, req) | ||
const functionNames = getTopLevelFunctions(asset.content.toString()) | ||
const userCode = `(() => { ${asset.content.toString()}; | ||
const userCode = `(async () => { ${asset.content.toString()}; | ||
__topLevelFunctions = {...__topLevelFunctions, ${functionNames.map(h => `"${h}": ${h}`).join(',')}} | ||
@@ -129,5 +206,6 @@ })()` | ||
source: userCode, | ||
entitySet: 'assets', | ||
entity: { | ||
...a, | ||
content: a.content.toString() | ||
content: asset.content.toString() | ||
} | ||
@@ -139,3 +217,3 @@ }) | ||
registerHelpers: async (path) => { | ||
const asset = await readAsset(reporter, definition, { id: null, name: path, encoding: 'utf8', currentPath: proxy.currentPath }, req) | ||
const asset = await readAsset(reporter, definition, { id: null, name: path, encoding: 'utf8', currentDirectoryPath: proxy.currentDirectoryPath }, req) | ||
@@ -149,2 +227,3 @@ const functionNames = getTopLevelFunctions(asset.content.toString()) | ||
source: userCode, | ||
entitySet: 'assets', | ||
entity: { | ||
@@ -158,8 +237,8 @@ ...asset.entity, | ||
require: async (path) => { | ||
const r = await readAsset(reporter, definition, { id: null, name: path, encoding: 'utf8', currentPath: proxy.currentPath }, req) | ||
const r = await readAsset(reporter, definition, { id: null, name: path, encoding: 'utf8', currentDirectoryPath: proxy.currentDirectoryPath }, req) | ||
const userCode = [ | ||
`;(() => { function moduleWrap(exports, require, module, __filename, __dirname) { ${r.content} \n};\n`, | ||
`;(async () => { async function moduleWrap(exports, require, module, __filename, __dirname) { ${r.content} \n};\n`, | ||
`const m = { exports: { }}; | ||
const r = moduleWrap(m.exports, require, m); | ||
const r = await moduleWrap(m.exports, require, m); | ||
return m.exports; | ||
@@ -172,2 +251,3 @@ })()` | ||
source: userCode, | ||
entitySet: 'assets', | ||
entity: r.entity | ||
@@ -174,0 +254,0 @@ }) |
{ | ||
"name": "@jsreport/jsreport-assets", | ||
"version": "3.1.0", | ||
"version": "3.2.0", | ||
"description": "jsreport extension embedding static assets like fonts or helpers into the templates", | ||
@@ -29,3 +29,3 @@ "keywords": [ | ||
"start": "jsreport-studio-start", | ||
"test": "mocha test --timeout 99999999 --exit && standard", | ||
"test": "mocha test --timeout 8000 --exit && standard", | ||
"test:watch": "mocha test --watch" | ||
@@ -45,7 +45,7 @@ }, | ||
"devDependencies": { | ||
"@jsreport/jsreport-core": "3.2.0", | ||
"@jsreport/jsreport-express": "3.2.0", | ||
"@jsreport/jsreport-core": "3.3.0", | ||
"@jsreport/jsreport-express": "3.2.1", | ||
"@jsreport/jsreport-handlebars": "3.0.0", | ||
"@jsreport/jsreport-jsrender": "3.0.0", | ||
"@jsreport/jsreport-scripts": "3.0.1", | ||
"@jsreport/jsreport-scripts": "3.1.0", | ||
"@jsreport/studio-dev": "3.0.1", | ||
@@ -52,0 +52,0 @@ "binary-extensions": "1.12.0", |
import React, { Component } from 'react' | ||
import scopeOptions from './scopeOptions' | ||
import Studio from 'jsreport-studio' | ||
export default class AssetProperties extends Component { | ||
class AssetProperties extends Component { | ||
static title (entity, entities) { | ||
return `asset ${entity.link ? '(link)' : ''}` | ||
let suffix = entity.link ? ' (link)' : '' | ||
if (entity.sharedHelpersScope != null) { | ||
suffix += ` (shared helper, scope: ${entity.sharedHelpersScope})` | ||
} | ||
return `asset${suffix}` | ||
} | ||
componentDidMount () { | ||
this.normalizeScope() | ||
} | ||
componentDidUpdate () { | ||
this.normalizeScope() | ||
} | ||
normalizeScope () { | ||
const { entity, onChange } = this.props | ||
if (entity.isSharedHelper === true && entity.sharedHelpersScope == null) { | ||
onChange({ _id: entity._id, sharedHelpersScope: 'global', isSharedHelper: false }) | ||
} | ||
} | ||
render () { | ||
const { entity, onChange } = this.props | ||
const currentScopeValue = entity.sharedHelpersScope != null ? entity.sharedHelpersScope : 'global' | ||
const currentScopeOption = scopeOptions.find((opt) => opt.value === currentScopeValue) | ||
return ( | ||
@@ -27,8 +53,30 @@ <div> | ||
<div className='form-group'> | ||
<label>shared helpers attached to each template</label> | ||
<label>shared helpers attached to templates</label> | ||
<input | ||
type='checkbox' checked={entity.isSharedHelper === true} | ||
onChange={(v) => onChange({ _id: entity._id, isSharedHelper: v.target.checked })} | ||
type='checkbox' checked={entity.sharedHelpersScope != null} | ||
onChange={(v) => { | ||
onChange({ | ||
_id: entity._id, | ||
sharedHelpersScope: v.target.checked === false ? null : 'global' | ||
}) | ||
}} | ||
/> | ||
</div> | ||
{entity.sharedHelpersScope != null && ( | ||
<div className='form-group'> | ||
<label>scope</label> | ||
<select | ||
value={currentScopeValue} | ||
onChange={(v) => { | ||
const newScope = v.target.value | ||
onChange({ _id: entity._id, sharedHelpersScope: newScope }) | ||
}} | ||
> | ||
{scopeOptions.map((opt) => ( | ||
<option key={opt.key} value={opt.value} title={opt.desc}>{opt.title}</option> | ||
))} | ||
</select> | ||
<em>{currentScopeOption.desc}</em> | ||
</div> | ||
)} | ||
</div> | ||
@@ -38,1 +86,3 @@ ) | ||
} | ||
export default AssetProperties |
@@ -12,3 +12,3 @@ import AssetEditor from './AssetEditor.js' | ||
onNew: (options) => Studio.openModal(NewAssetModal, options), | ||
referenceAttributes: ['isSharedHelper'], | ||
referenceAttributes: ['isSharedHelper', 'scope'], | ||
entityTreePosition: 700 | ||
@@ -15,0 +15,0 @@ }) |
import React, { Component } from 'react' | ||
import AssetUploadButton from './AssetUploadButton.js' | ||
import scopeOptions from './scopeOptions' | ||
import AssetUploadButton from './AssetUploadButton' | ||
import Studio from 'jsreport-studio' | ||
@@ -11,3 +12,3 @@ | ||
this.linkRef = React.createRef() | ||
this.state = { isLink: false } | ||
this.state = { isLink: false, isSharedHelper: false, scope: null } | ||
} | ||
@@ -45,2 +46,8 @@ | ||
if (this.state.isSharedHelper) { | ||
entity.sharedHelpersScope = this.state.scope | ||
} else { | ||
entity.sharedHelpersScope = null | ||
} | ||
try { | ||
@@ -70,10 +77,16 @@ if (Studio.workspaces) { | ||
render () { | ||
const { isLink, error } = this.state | ||
const { isLink, isSharedHelper, scope, error } = this.state | ||
const currentScopeValue = scope != null ? scope : 'global' | ||
const currentScopeOption = scopeOptions.find((opt) => opt.value === currentScopeValue) | ||
return ( | ||
<div> | ||
<div className='form-group'> | ||
<label>New asset</label> | ||
</div> | ||
{isLink | ||
? ( | ||
<div className='form-group'> | ||
<label>Relative or absolute path to existing file</label> | ||
<label>relative or absolute path to existing file</label> | ||
<input | ||
@@ -88,3 +101,3 @@ type='text' | ||
<div className='form-group'> | ||
<label>Name</label> | ||
<label>name</label> | ||
<input | ||
@@ -111,2 +124,33 @@ type='text' | ||
<div className='form-group'> | ||
<label>shared helpers attached to templates</label> | ||
<input | ||
type='checkbox' checked={isSharedHelper === true} | ||
onChange={(v) => { | ||
this.setState({ | ||
isSharedHelper: v.target.checked, | ||
scope: v.target.checked === false ? null : 'global' | ||
}) | ||
}} | ||
/> | ||
</div> | ||
{isSharedHelper && ( | ||
<div className='form-group'> | ||
<label>scope</label> | ||
<select | ||
value={currentScopeValue} | ||
onChange={(v) => { | ||
const newScope = v.target.value | ||
this.setState({ | ||
scope: newScope | ||
}) | ||
}} | ||
> | ||
{scopeOptions.map((opt) => ( | ||
<option key={opt.key} value={opt.value} title={opt.desc}>{opt.title}</option> | ||
))} | ||
</select> | ||
<em>{currentScopeOption.desc}</em> | ||
</div> | ||
)} | ||
<div className='form-group'> | ||
<span | ||
@@ -113,0 +157,0 @@ style={{ color: 'red', display: error ? 'block' : 'none' }} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
221928
20
3454