diff --git a/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/Archive.zip b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/Archive.zip new file mode 100644 index 0000000..45686ff Binary files /dev/null and b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/Archive.zip differ diff --git a/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/index.json b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/index.json new file mode 100644 index 0000000..787a076 --- /dev/null +++ b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/index.json @@ -0,0 +1,73 @@ +{ + "eula": "", + "vendor": "SAP", + "license": "", + "id": "com.sap.sac.sample.init.example.echarts.sunburst", + "icon": "data:image/png;base64,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", + "version": "1.0.0", + "supportsMobile": true, + "supportsBookmark": true, + "supportsLinkedAnalysisFilterOnSelection": true, + "name": "EChartsSunburstStyling", + "newInstancePrefix": "EChartsSunburstStyling", + "description": "A Sample Sunburst Chart with Styling Panel", + "webcomponents": [ + { + "kind": "main", + "tag": "com-sap-sample-init-example-echarts-sunburst", + "url": "/main.js", + "integrity": "", + "ignoreIntegrity": true + }, + { + "kind": "styling", + "tag": "com-sap-sample-init-example-echarts-sunburst-styling", + "url": "/styling.js", + "integrity": "", + "ignoreIntegrity": true + } + ], + "properties": { + "width": { + "type": "integer", + "default": 600 + }, + "height": { + "type": "integer", + "default": 320 + }, + "drillUpArea": { + "type": "string", + "default": "#ffffff" + }, + "stops": { + "type": "string[]", + "default": ["#0070F2", "#4CB1FF", "#A6E0FF", "#D2EFFF", "#0057D2"] + }, + "showAll": { + "type": "boolean", + "default": false + }, + "labelAll": { + "type": "string" + } + }, + "methods": {}, + "events": {}, + "dataBindings": { + "dataBinding": { + "feeds": [ + { + "id": "dimensions", + "description": "Dimensions", + "type": "dimension" + }, + { + "id": "measures", + "description": "Measures", + "type": "mainStructureMember" + } + ] + } + } +} \ No newline at end of file diff --git a/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/main.js b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/main.js new file mode 100644 index 0000000..208c6a1 --- /dev/null +++ b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/main.js @@ -0,0 +1,189 @@ +/*var getScriptPromisify = (src) => { + return new Promise((resolve) => { + $.getScript(src, resolve); + }); +};*/ + +var getScriptPromisify = (src) => { + // Workaround with conflict between geo widget and echarts. + const __define = define + define = undefined + return new Promise(resolve => { + $.getScript(src, () => { + define = __define + resolve() + }) + }) +} + +(function () { + const parseMetadata = metadata => { + const { dimensions: dimensionsMap, mainStructureMembers: measuresMap } = metadata + const dimensions = [] + for (const key in dimensionsMap) { + const dimension = dimensionsMap[key] + dimensions.push({ key, ...dimension }) + } + const measures = [] + for (const key in measuresMap) { + const measure = measuresMap[key] + measures.push({ key, ...measure }) + } + return { dimensions, measures, dimensionsMap, measuresMap } + } + + const appendSuperRoot = (data, labelAll) => { + data = JSON.parse(JSON.stringify(data)) + const superRoot = { + dimensions_0: { id: 'superRoot', label: labelAll }, + measures_0: { raw: 0 } + } + data.forEach(data => { + if (data.dimensions_0.parentId) { return } + data.dimensions_0.parentId = 'superRoot' + superRoot.measures_0.raw += data.measures_0.raw + }) + return [superRoot].concat(data) + } + + const findDp = (seriesData, id, depth = 1) => { + for (let i = 0; i < seriesData.length; i++) { + const dp = seriesData[i] + if (dp.id === id) { return { dp, depth } } + if (dp.children) { + const found = findDp(dp.children, id, depth + 1) + if (found) { return found } + } + } + } + + class Renderer { + constructor(root) { + this._root = root + this._echart = null + } + + async render(dataBinding, drillUpArea, stops, showAll, labelAll) { + await getScriptPromisify("https://cdn.staticfile.org/echarts/5.3.0/echarts.min.js"); + this.dispose() + + if (dataBinding.state !== 'success') { return } + + let { data, metadata } = dataBinding + const { dimensions, measures } = parseMetadata(metadata) + + if (dimensions.length !== 1) { return } + + const levels = [{ + itemStyle: { color: drillUpArea } + }] + stops.forEach(stop => { + levels.push({ + itemStyle: { color: stop } + }) + }) + const seriesData = [] + if (showAll) { + data = appendSuperRoot(data, labelAll) + } + data.forEach(row => { + const { id, label, parentId } = row[dimensions[0].key] + const { raw } = row[measures[0].key] + const dp = findDp(seriesData, id) || { id } + dp.name = label + dp.value = raw + + if (parentId) { + const parent = findDp(seriesData, parentId) + if (!parent) { console.error('Please check: "Include Parent Node"') } + + parent.dp.children = parent.dp.children || [] + parent.dp.children.push(dp) + } else { + seriesData.push(dp) + } + }) + + this._echart = echarts.init(this._root) + // https://echarts.apache.org/en/option.html + this._echart.setOption({ + series: { + type: 'sunburst', + data: seriesData, + levels, + radius: [0, '90%'], + label: { + rotate: 'radial' + } + } + }) + } + + dispose() { + if (this._echart) { + echarts.dispose(this._echart) + } + } + } + + const template = document.createElement('template') + template.innerHTML = ` + +
+
+
+ ` + + class Main extends HTMLElement { + constructor () { + super() + + this._shadowRoot = this.attachShadow({ mode: 'open' }) + this._shadowRoot.appendChild(template.content.cloneNode(true)) + this._root = this._shadowRoot.getElementById('root') + this._renderer = new Renderer(this._root) + } + + // ------------------ + // LifecycleCallbacks + // ------------------ + async onCustomWidgetBeforeUpdate(changedProps) { + } + + async onCustomWidgetAfterUpdate(changedProps) { + this.render() + } + + async onCustomWidgetResize(width, height) { + this.render() + } + + async onCustomWidgetDestroy() { + this.dispose() + } + + // ------------------ + // + // ------------------ + dispose() { + this._renderer.dispose() + } + + render() { + if (!document.contains(this)) { + // Delay the render to assure the custom widget is appended on dom + setTimeout(this.render.bind(this), 0) + return + } + + this._renderer.render(this.dataBinding, this.drillUpArea, this.stops, this.showAll, this.labelAll) + } + } + + customElements.define('com-sap-sample-init-example-echarts-sunburst', Main) +})() \ No newline at end of file diff --git a/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/styling.js b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/styling.js new file mode 100644 index 0000000..afca080 --- /dev/null +++ b/Custom-Widget-Samples/Sunbrust Chart with Styling Panel/styling.js @@ -0,0 +1,114 @@ +(function () { + let template = document.createElement("template"); + template.innerHTML = ` + +
+
All
+
+ +
+ +
Label
+
+ +
+
Drill Up Area
+
+ +
+
Colors
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ `; + + class Styling extends HTMLElement { + constructor () { + super() + + this._shadowRoot = this.attachShadow({ mode: 'open' }) + this._shadowRoot.appendChild(template.content.cloneNode(true)) + this._root = this._shadowRoot.getElementById('root') + + this._button = this._shadowRoot.getElementById('button') + this._button.addEventListener('click', () => { + const drillUpArea = this._shadowRoot.getElementById('drillUpArea').value + const stops = [ + this._shadowRoot.getElementById('stop0').value, + this._shadowRoot.getElementById('stop1').value, + this._shadowRoot.getElementById('stop2').value, + this._shadowRoot.getElementById('stop3').value, + this._shadowRoot.getElementById('stop4').value + ] + const showAll = this._shadowRoot.getElementById('showAll').checked + const labelAll = this._shadowRoot.getElementById('labelAll').value + this.dispatchEvent(new CustomEvent('propertiesChanged', { detail: { properties: { drillUpArea, stops, showAll, labelAll } } })) + }) + } + + // ------------------ + // LifecycleCallbacks + // ------------------ + async onCustomWidgetBeforeUpdate (changedProps) { + } + + async onCustomWidgetAfterUpdate (changedProps) { + if (changedProps.drillUpArea) { + this._shadowRoot.getElementById('drillUpArea').value = changedProps.drillUpArea + } + if (changedProps.stops) { + this._shadowRoot.getElementById('stop0').value = changedProps.stops[0] + this._shadowRoot.getElementById('stop1').value = changedProps.stops[1] + this._shadowRoot.getElementById('stop2').value = changedProps.stops[2] + this._shadowRoot.getElementById('stop3').value = changedProps.stops[3] + this._shadowRoot.getElementById('stop4').value = changedProps.stops[4] + } + if (changedProps.showAll !== undefined) { + this._shadowRoot.getElementById('showAll').checked = changedProps.showAll + } + if (changedProps.labelAll !== undefined) { + this._shadowRoot.getElementById('labelAll').value = changedProps.labelAll + } + } + + async onCustomWidgetResize (width, height) { + } + + async onCustomWidgetDestroy () { + this.dispose() + } + + // ------------------ + // + // ------------------ + + dispose () { + } + } + + customElements.define('com-sap-sample-init-example-echarts-sunburst-styling', Styling); +})(); \ No newline at end of file