diff --git a/advanced/wizard/sample-cards/wz-clock-card/package.json b/advanced/wizard/sample-cards/wz-clock-card/package.json new file mode 100644 index 0000000..d83920f --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/package.json @@ -0,0 +1,18 @@ +{ + "name": "sap-it-wz-cards-clock", + "version": "1.28.0", + "description": "", + "private": true, + "scripts": { + "start": "ui5 serve --o /test-resources/manual/index.html", + "eslint": "eslint src", + "build": "rimraf dist && ui5 build && zip sap-it-wz-cards-clock.zip -r ./dist" + }, + "devDependencies": { + "@openui5/sap.ui.core": "1.77.2", + "@openui5/sap.ui.integration": "1.77.2", + "@ui5/cli": "2.2.3", + "eslint": "5.16.0", + "rimraf": "2.6.2" + } +} diff --git a/advanced/wizard/sample-cards/wz-clock-card/sap-it-wz-cards-clock.zip b/advanced/wizard/sample-cards/wz-clock-card/sap-it-wz-cards-clock.zip new file mode 100644 index 0000000..21cde9b Binary files /dev/null and b/advanced/wizard/sample-cards/wz-clock-card/sap-it-wz-cards-clock.zip differ diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/Component.js b/advanced/wizard/sample-cards/wz-clock-card/src/Component.js new file mode 100644 index 0000000..be667dd --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/Component.js @@ -0,0 +1,23 @@ +/* + * ! ${copyright} + */ +sap.ui.define(["sap/ui/core/UIComponent"], function (UIComponent) { + "use strict"; + var ChatbotComponent = UIComponent.extend("sap.it.wz.cards.clock.component.Component", { + onCardReady: function (oCard) { + // Holds the card for use inside the controller + this.card = oCard; + + // Can get all parameters with method getCombinedParameters + oCard.getCombinedParameters(); + + // Get any section of the card manifest with method getManifestEntry + oCard.getManifestEntry("/sap.card"); + + // When in context of a Host, like in Work Zone you can use the following methods + // oCard.getHostInstance(); + // oCard.resolveDestination("myDestination"); // check more in the destinations sample + } + }); + return ChatbotComponent; +}); diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/control/Frame.js b/advanced/wizard/sample-cards/wz-clock-card/src/control/Frame.js new file mode 100644 index 0000000..ee64f16 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/control/Frame.js @@ -0,0 +1,350 @@ +/* + * ! ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/Control", + "sap/ui/core/Core", + "sap/m/MessageStrip" +], function ( + Control, + Core, + MessageStrip +) { + "use strict"; + + var oStaticArea = Core.getStaticAreaRef(); + + function getScrollTop() { + var B = document.body; + var D = document.documentElement; + D = (D.clientHeight) ? D : B; + return D.scrollTop; + } + + function getScrollLeft() { + var B = document.body; + var D = document.documentElement; + D = (D.clientWidth) ? D : B; + return D.scrollLeft; + } + + function getZIndex(e) { + var z = window.getComputedStyle(e).getPropertyValue('z-index'); + if (isNaN(z)) { + if (e.parentNode && e.parentNode.nodeType === 1) { + return getZIndex(e.parentNode); + } else { + return "auto"; + } + } else { + return z; + } + } + + //Registers an animation frame timer to check whether the position of oDomRef changed + //and calls the handler if it did + var VisibleRectObserver = function (oDomRef, fnHandler) { + if (!VisibleRectObserver._instance) { + VisibleRectObserver._instance = this; + this._elements = []; + this._sizes = []; + this._handlers = []; + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + } + + if (oDomRef && fnHandler) { + VisibleRectObserver._instance.register(oDomRef, fnHandler); + } + return VisibleRectObserver._instance; + }; + + //loops over the elements and checks for size and position changes + VisibleRectObserver.prototype.checkAll = function () { + for (var i = 0; i < this._elements.length; i++) { + this.check(i); + } + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + }; + + //checks size and position changes for an element and calls the handler + VisibleRectObserver.prototype.check = function (i) { + var el = this._elements[i]; + var size = el.getBoundingClientRect(), + s = JSON.stringify(size); + if (this._sizes[i] !== s) { + this._sizes[i] = s; + this._handlers[i](el, size); + } + }; + + //registers a dom element and handler to be observed for size and position changes + VisibleRectObserver.prototype.register = function (oDomElement, fnHandler) { + if (this._elements.indexOf(oDomElement) > -1) { + return; + } + this._elements.push(oDomElement); + this._sizes.push(""); + this._handlers.push(fnHandler); + this.check(VisibleRectObserver._instance._sizes.length - 1); + }; + + //deregisters a dom element from observation + VisibleRectObserver.prototype.deregister = function (oDomElement) { + var iIndex = this._elements.indexOf(oDomElement); + if (iIndex === -1) { + return; + } + this._elements.splice(iIndex, 1); + this._sizes.splice(iIndex, 1); + this._handlers.splice(iIndex, 1); + }; + + + var Frame = Control.extend("sap.it.wz.cards.twitter.control.Frame", { + metadata: { + properties: { + src: { + type: "string" + }, + preview: { + type: "object", + defaultValue: null + } + } + }, + renderer: function (oRm, oControl) { + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.addStyle("box-sizing", "border-box"); + oRm.writeStyles(); + oRm.writeElementData(oControl); + oRm.openEnd(); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-before"); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-content"); + oRm.writeStyles(); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-after"); + oRm.openEnd(); + oRm.close("div"); + + oRm.close("div"); + + } + }); + + Frame.prototype.setSrc = function (vValue) { + if (vValue === this.getSrc()) { + return this; + } + //avoid re-rendering + this.setProperty("src", vValue, true); + + this._sRealSource = vValue; + + if (this._oFrameDomRef) { + this._oFrameDomRef.src = this._sRealSource; + } + return this; + }; + + Frame.prototype.init = function () { + this._oVisibleRectObserver = new VisibleRectObserver(); + }; + + Frame.prototype.onBeforeRendering = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + this._hideFrame(); + }; + + Frame.prototype.onAfterRendering = function () { + if (this._sRealSource && this._sRealSource.length < 5) { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + this._sRealSource = ""; + return this; + } + if (false && this._sRealSource.indexOf("http:") === 0) { + this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEHTTPERROR")); + this._sRealSource = ""; + return this; + } + if (this._sRealSource && this._sRealSource.indexOf("https://") !== 0) { + //this._sRealSource = "https://" + this._sRealSource; + } + if (this._sRealSource) { + this._iErrorTimer = window.setTimeout(this._handleError.bind(this), 1000 * 20); + if (!this._oFrameDomRef) { + this._initFrame(); + } + } else { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + } + }; + + Frame.prototype.exit = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + return this; + }; + + Frame.prototype.destroy = function () { + if (this._oFrameDomRef) { + this._oFrameDomRef.parentNode.removeChild(this._oFrameDomRef); + this._oFrameDomRef.src = ""; + } + if (this._oFrameBlockerDomRef) { + this._oFrameBlockerDomRef.parentNode.removeChild(this._oFrameBlockerDomRef); + this._oFrameBlockerDomRef.src = ""; + } + return Control.prototype.destroy.apply(this, arguments); + }; + + Frame.prototype._hideFrame = function () { + //hide the frame until it is loaded + if (!this._oFrameDomRef) { + return; + } + this._oFrameDomRef.style.top = "-10000px"; + this._oFrameDomRef.style.left = "50px"; + }; + + Frame.prototype._initFrame = function () { + var oFrame = document.getElementById("id", this.getId() + "-frame"); + if (oFrame) { + this._oFrameDomRef = oFrame; + return; + } + var iTab = this.getPreview() ? -1 : 0; + this._oFrameDomRef = this._createFrame(this.getId() + "-frame", this._sRealSource, iTab); + oStaticArea.insertBefore(this._oFrameDomRef, oStaticArea.firstChild); + if (this.getPreview()) { + this._oFrameBlockerDomRef = this._createFrame(this.getId() + "-frameblocker", "", iTab); + oStaticArea.insertBefore(this._oFrameBlockerDomRef, oStaticArea.firstChild); + } + }; + + Frame.prototype._createFrame = function (sId, sSource, iTab) { + var oLocalRM = Core.getRenderManager(); + oLocalRM.openStart("iframe"); + oLocalRM.addStyle("position", "absolute"); + oLocalRM.addStyle("border", "none"); + oLocalRM.addStyle("top", "-10000px"); + oLocalRM.addStyle("left", "20px"); + oLocalRM.addStyle("margin", "1px"); + oLocalRM.writeStyles(); + oLocalRM.writeAttribute("tabIndex", "" + iTab); + oLocalRM.writeAttributeEscaped("id", sId); + oLocalRM.writeAttributeEscaped("scrolling", "auto"); + if (sSource) { + oLocalRM.writeAttributeEscaped("src", sSource); + } + oLocalRM.openEnd(); + oLocalRM.close("iframe"); + var div = document.createElement("div"); + oLocalRM.flush(div); + var oFrame = div.firstChild; + oFrame.addEventListener("load", this._handleLoad.bind(this)); + return oFrame; + }; + + Frame.prototype._handleLoad = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + this._oVisibleRectObserver.register(this.getDomRef(), this._syncFramePosition.bind(this)); + }; + + Frame.prototype._handleError = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + //this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEERROR15SEC")); + }; + + Frame.prototype._applyFramePosition = function (oFrame, oElement, oRect) { + if (!oFrame) { + return; + } + if (oRect.height === 0 || oRect.width === 0) { + this._hideFrame(); + return; + } + var iZIndex = getZIndex(oElement); + oFrame.style.zIndex = iZIndex === "auto" ? 2 : iZIndex; + oFrame.style.left = (oRect.left + getScrollLeft()) + "px"; + oFrame.style.top = (oRect.top + getScrollTop()) + "px"; + + if (this.getPreview()) { + var oPreviewInfo = this.getPreview().getTransformContentInfo(); + oFrame.style.width = ((oRect.width - 2) / oPreviewInfo.transformFactor) + "px"; + oFrame.style.height = ((oRect.height - 2) / oPreviewInfo.transformFactor) + "px" + oFrame.style.transform = oPreviewInfo.transformStyle; + oFrame.style.transformOrigin = oPreviewInfo.transformOriginStyle; + oFrame.style.zIndex = oPreviewInfo.zIndex; + } else { + oFrame.style.width = (oRect.width - 2) + "px"; + oFrame.style.height = (oRect.height - 2) + "px"; + } + }; + + Frame.prototype._syncFramePosition = function (oElement, oRect) { + this._applyFramePosition(this._oFrameDomRef, oElement, oRect); + this._applyFramePosition(this._oFrameBlockerDomRef, oElement, oRect); + }; + + Frame.prototype._showMessage = function (sType, sText) { + if (this._oMessage) { + this._oMessage.destroy(); + } + this._oMessage = new MessageStrip(this.getId() + "-message", { + text: sText, + type: sType, + showIcon: true + }); + var oDomRef = this.getDomRef(); + if (oDomRef) { + this._oMessage.placeAt(oDomRef); + } + }; + function focusAfter() { + this.getDomRef("after").focus(); + window.removeEventListener("focus", focusAfter); + } + Frame.prototype.onsaptabnext = function (oEvent) { + if (oEvent.target === this.getDomRef("before")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + + } + } + }; + + Frame.prototype.onsaptabprevious = function (oEvent) { + if (oEvent.target === this.getDomRef("after")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + } + } + }; + return Frame; + +}); diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/controller/Card.controller.js b/advanced/wizard/sample-cards/wz-clock-card/src/controller/Card.controller.js new file mode 100644 index 0000000..d04ecc9 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/controller/Card.controller.js @@ -0,0 +1,149 @@ +/* + * ! ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/mvc/Controller" +], function (Controller) { + "use strict"; + + return Controller.extend("sap.it.wz.cards.clock.controller.Card", { + onInit: function () { + if (!this.getOwnerComponent().card) { + return; + } + let oCard = this.getOwnerComponent().card; + let mParameters = oCard.getCombinedParameters(); + + let backgroundColor = mParameters.backgroundColor + let clockColor = mParameters.clockColor + let fontSize = mParameters.fontSize + let offset = mParameters.offset + let showSeconds = mParameters.showSeconds + let digit24Mode = mParameters.digit24Mode + + let content = this._getIframeDigitalClock(backgroundColor, clockColor, fontSize, offset, digit24Mode,showSeconds); + + + var src = URL.createObjectURL(new Blob([content], { type: "text/html" })); + var oFrame = this.byId("frame"); + oFrame.setSrc(src); + + if (oCard.editor) { + oFrame.setPreview(oCard.editor.preview); + } + + var iPixelHeight = Math.max(mParameters.height, oCard.getCardContent().getDomRef().offsetHeight); + this.getView().setHeight(iPixelHeight + "px"); + }, + _getIframeDigitalClock: function (backgroundColor, clockColor, fontSize, offset, digit24Mode, showSeconds) { + return ` + + + + + +
+

+
+ + + `; + } + + }); +}); + + +function calculate12time(h, m, s) { + var session = "AM"; + if(h>24){ + h= h-24 + } + if(h<0){ + session = "PM" + h+=12 + } + if(h == 12){ + session = "PM" + } + if(h == 0){ + h = 12; + } + if(h > 12){ + h = h - 12; + if(h==12){ + session=="AM" + } + else{ + session = "PM" + } + } + + + h = (h < 10) ? "0" + h : h; + m = (m < 10) ? "0" + m : m; + s = (s < 10) ? "0" + s : s; + + return s == 0 ? h + ":" + m + " " + session : h + ":" + m + ":" + s + " " + session +} + + +function calculate24time(h, m, s) { + if (h >= 24) { + h = h - 24 + } + if (h < 0) { + h = h + 24 + } + h = (h < 10) ? "0" + h : h + m = (m < 10) ? "0" + m : m + s = (s < 10) ? "0" + s : s + return s == 0 ? h + ":" + m : h + ":" + m + ":" + s +} + diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/dt/configuration.js b/advanced/wizard/sample-cards/wz-clock-card/src/dt/configuration.js new file mode 100644 index 0000000..e1094ff --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/dt/configuration.js @@ -0,0 +1,192 @@ +sap.ui.define(["sap/ui/integration/Designtime" +], function (Designtime) { + "use strict"; + + var Configuration = Designtime.extend("sap.workzone.cpkg.card.sample.Configuration"); + Configuration.prototype.create = function () { + return { + form: { + items: { + "headerGroup": { + "label": "Header options", + "type": "group", + "hint": "In case of troubles please visit SAP Work Zone Help Center" + }, + "headerVisibility": { + "manifestpath": "/sap.card/header/visible", + "type": "boolean", + "label": "Visible Header", + "defaultValue" : true + }, + "title": { + "manifestpath": "/sap.card/header/title", + "type": "string", + "defaultValue": "Clock", + "label": "Title", + "visible": "{items>headerVisibility/value}" + }, + "subTitle": { + "manifestpath": "/sap.card/header/subTitle", + "type": "string", + "defaultValue": "", + "label": "Subtitle", + "visible": "{items>headerVisibility/value}" + }, + "headericon": { + "manifestpath": "/sap.card/header/icon/src", + "type": "string", + "label": "Card Icon", + "allowDynamicValues": false, + "allowSettings": false, + "visualization": { + "type": "IconSelect", + "settings": { + "value": "{currentSettings>value}", + "editable": "{currentSettings>editable}" + } + }, + "visible": "{items>headerVisibility/value}" + }, + "bodyGroup": { + "label": "Body options", + "type": "group" + }, + "offset": { + "manifestpath": "/sap.card/configuration/parameters/offset/value", + "values": { + "data": { + "json": [ + { "key": "-11", "text": "-11" }, + { "key": "-10", "text": "-10" }, + { "key": "-9", "text": "-9" }, + { "key": "-8", "text": "-8" }, + { "key": "-7", "text": "-7" }, + { "key": "-6", "text": "-6" }, + { "key": "-5", "text": "-5" }, + { "key": "-4", "text": "-4" }, + { "key": "-3", "text": "-3" }, + { "key": "-2", "text": "-2" }, + { "key": "-1", "text": "-1" }, + { "key": "0", "text": "0" }, + { "key": "1", "text": "+1" }, + { "key": "2", "text": "+2" }, + { "key": "3", "text": "+3" }, + { "key": "4", "text": "+4" }, + { "key": "5", "text": "+5" }, + { "key": "6", "text": "+6" }, + { "key": "7", "text": "+7" }, + { "key": "8", "text": "+8" }, + { "key": "9", "text": "+9" }, + { "key": "10", "text": "+10" }, + { "key": "11", "text": "+11" }, + { "key": "12", "text": "+12" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "1", + "label": "Select UTC zone", + "type": "string" + }, + "digit24Mode": { + "manifestpath": "/sap.card/configuration/parameters/digit24Mode/value", + "type": "boolean", + "label": "24h mode", + "defaultValue" : false + }, + "showSeconds": { + "manifestpath": "/sap.card/configuration/parameters/showSeconds/value", + "type": "boolean", + "label": "Show seconds", + "defaultValue" : false + }, + "backgroundColor": { + "manifestpath": "/sap.card/configuration/parameters/backgroundColor/value", + "values": { + "data": { + "json": [ + { "key": "#FFFFFF", "text": "White" }, + { "key": "#000000", "text": "Black" }, + { "key": "#1D2D3E", "text": "Dark" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "Dark", + "label": "Select background color", + "type": "string" + }, + "clockColor": { + "manifestpath": "/sap.card/configuration/parameters/clockColor/value", + "values": { + "data": { + "json": [ + { "key": "#FFFFFF", "text": "White" }, + { "key": "#000000", "text": "Black" }, + { "key": "#1D2D3E", "text": "Dark" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "White", + "label": "Select clock color", + "type": "string" + }, + "fontSize": { + "manifestpath": "/sap.card/configuration/parameters/fontSize/value", + "type": "integer", + "defaultValue": 45, + "label": "Font size in pixels", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 5, + "max": 100, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + }, + "height": { + "manifestpath": "/sap.card/configuration/parameters/height/value", + "type": "integer", + "defaultValue": 100, + "label": "Height in pixels", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 30, + "max": 600, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + } + } + }, + preview: { + modes: "Live" + } + }; + }; + return Configuration; +}); + + diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/manifest.json b/advanced/wizard/sample-cards/wz-clock-card/src/manifest.json new file mode 100644 index 0000000..001ae4a --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/manifest.json @@ -0,0 +1,95 @@ +{ + "sap.app": { + "id": "sap.it.wz.cards.clock", + "type": "card", + "title": "Clock", + "subTitle": "Clock", + "applicationVersion": { + "version": "0.2.4" + }, + "shortTitle": "Clock", + "info": "Clock", + "description": "Select time zone to display", + "tags": { + "keywords": [ + "Clock", + "SAP IT" + ] + } + }, + "sap.ui": { + "technology": "UI5", + "icons": { + "icon": "sap-icon://away" + } + }, + "sap.ui5": { + "dependencies": { + "minUI5Version": "1.77.2", + "libs": { + "sap.ui.core": {}, + "sap.m": {} + } + }, + "rootView": { + "viewName": "sap.it.wz.cards.clock.view.Card", + "type": "XML", + "async": true, + "id": "app" + }, + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "sap.it.wz.cards.clock.i18n.i18n" + } + } + } + }, + "sap.platform.mobilecards": { + "_version": "1.0.0", + "compatible": false + }, + "sap.card": { + "type": "Component", + "designtime": "dt/configuration", + "header": { + "title": "Clock", + "icon": { + "src": "sap-icon://away" + }, + "visible" : true + }, + "configuration": { + "parameters": { + "showCardHeader": { + "value": true + }, + "offset" : { + "value" : "1" + }, + "digitMode" : { + "value" : true + }, + "digit24Mode" : { + "value" : false + }, + "showSeconds" : { + "value" : false + }, + "backgroundColor" : { + "value" : "#1D2D3E" + }, + "clockColor" : { + "value" : "#FFFFFF" + }, + "fontSize":{ + "value" : 45 + }, + "height": { + "value": 100 + } + } + } + } +} \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/test-resources/manual/index.html b/advanced/wizard/sample-cards/wz-clock-card/src/test-resources/manual/index.html new file mode 100644 index 0000000..72c56ae --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/test-resources/manual/index.html @@ -0,0 +1,73 @@ + + + + + + + sap.it.wz.cards.twitter + + + + + + + +
+ + + +
+
+ +
+ + + + \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-clock-card/src/view/Card.view.xml b/advanced/wizard/sample-cards/wz-clock-card/src/view/Card.view.xml new file mode 100644 index 0000000..d2c54af --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/src/view/Card.view.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/advanced/wizard/sample-cards/wz-clock-card/ui5.yaml b/advanced/wizard/sample-cards/wz-clock-card/ui5.yaml new file mode 100644 index 0000000..2ca4b5b --- /dev/null +++ b/advanced/wizard/sample-cards/wz-clock-card/ui5.yaml @@ -0,0 +1,16 @@ +specVersion: "2.0" +metadata: + name: sap-it-wz-cards-clock + copyright: |- + SAP Work Zone + * (c) Copyright 2009-2024 SAP SE or an SAP affiliate company. +type: application +resources: + configuration: + paths: + webapp: src + propertiesFileSourceEncoding: UTF-8 +builder: + resources: + excludes: + - "test-resources/**" \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-countdown-card/package.json b/advanced/wizard/sample-cards/wz-countdown-card/package.json new file mode 100644 index 0000000..d9ed19b --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/package.json @@ -0,0 +1,19 @@ +{ + "name": "sap-it-wz-cards-countdown", + "version": "1.28.0", + "description": "", + "private": true, + "scripts": { + "start": "ui5 serve --o /test-resources/manual/index.html", + "eslint": "eslint src", + "build": "rimraf dist && ui5 build && zip sap-it-wz-cards-countdown.zip -r ./dist" + }, + "dependencies": {}, + "devDependencies": { + "rimraf": "2.6.2", + "@openui5/sap.ui.core": "1.77.2", + "@openui5/sap.ui.integration": "1.77.2", + "@ui5/cli": "2.2.3", + "eslint": "5.16.0" + } +} diff --git a/advanced/wizard/sample-cards/wz-countdown-card/sap-it-wz-cards-countdown.zip b/advanced/wizard/sample-cards/wz-countdown-card/sap-it-wz-cards-countdown.zip new file mode 100644 index 0000000..eaba2fd Binary files /dev/null and b/advanced/wizard/sample-cards/wz-countdown-card/sap-it-wz-cards-countdown.zip differ diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/Component.js b/advanced/wizard/sample-cards/wz-countdown-card/src/Component.js new file mode 100644 index 0000000..0e9f20a --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/Component.js @@ -0,0 +1,23 @@ +/* + * ! ${copyright} + */ +sap.ui.define(["sap/ui/core/UIComponent"], function (UIComponent) { + "use strict"; + var ChatbotComponent = UIComponent.extend("sap.it.wz.cards.countdown.component.Component", { + onCardReady: function (oCard) { + // Holds the card for use inside the controller + this.card = oCard; + + // Can get all parameters with method getCombinedParameters + oCard.getCombinedParameters(); + + // Get any section of the card manifest with method getManifestEntry + oCard.getManifestEntry("/sap.card"); + + // When in context of a Host, like in Work Zone you can use the following methods + // oCard.getHostInstance(); + // oCard.resolveDestination("myDestination"); // check more in the destinations sample + } + }); + return ChatbotComponent; +}); diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/control/Frame.js b/advanced/wizard/sample-cards/wz-countdown-card/src/control/Frame.js new file mode 100644 index 0000000..3faeda1 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/control/Frame.js @@ -0,0 +1,350 @@ +/* + * ! ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/Control", + "sap/ui/core/Core", + "sap/m/MessageStrip" +], function ( + Control, + Core, + MessageStrip +) { + "use strict"; + + var oStaticArea = Core.getStaticAreaRef(); + + function getScrollTop() { + var B = document.body; + var D = document.documentElement; + D = (D.clientHeight) ? D : B; + return D.scrollTop; + } + + function getScrollLeft() { + var B = document.body; + var D = document.documentElement; + D = (D.clientWidth) ? D : B; + return D.scrollLeft; + } + + function getZIndex(e) { + var z = window.getComputedStyle(e).getPropertyValue('z-index'); + if (isNaN(z)) { + if (e.parentNode && e.parentNode.nodeType === 1) { + return getZIndex(e.parentNode); + } else { + return "auto"; + } + } else { + return z; + } + } + + //Registers an animation frame timer to check whether the position of oDomRef changed + //and calls the handler if it did + var VisibleRectObserver = function (oDomRef, fnHandler) { + if (!VisibleRectObserver._instance) { + VisibleRectObserver._instance = this; + this._elements = []; + this._sizes = []; + this._handlers = []; + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + } + + if (oDomRef && fnHandler) { + VisibleRectObserver._instance.register(oDomRef, fnHandler); + } + return VisibleRectObserver._instance; + }; + + //loops over the elements and checks for size and position changes + VisibleRectObserver.prototype.checkAll = function () { + for (var i = 0; i < this._elements.length; i++) { + this.check(i); + } + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + }; + + //checks size and position changes for an element and calls the handler + VisibleRectObserver.prototype.check = function (i) { + var el = this._elements[i]; + var size = el.getBoundingClientRect(), + s = JSON.stringify(size); + if (this._sizes[i] !== s) { + this._sizes[i] = s; + this._handlers[i](el, size); + } + }; + + //registers a dom element and handler to be observed for size and position changes + VisibleRectObserver.prototype.register = function (oDomElement, fnHandler) { + if (this._elements.indexOf(oDomElement) > -1) { + return; + } + this._elements.push(oDomElement); + this._sizes.push(""); + this._handlers.push(fnHandler); + this.check(VisibleRectObserver._instance._sizes.length - 1); + }; + + //deregisters a dom element from observation + VisibleRectObserver.prototype.deregister = function (oDomElement) { + var iIndex = this._elements.indexOf(oDomElement); + if (iIndex === -1) { + return; + } + this._elements.splice(iIndex, 1); + this._sizes.splice(iIndex, 1); + this._handlers.splice(iIndex, 1); + }; + + + var Frame = Control.extend("sap.it.wz.cards.flip_card.control.Frame", { + metadata: { + properties: { + src: { + type: "string" + }, + preview: { + type: "object", + defaultValue: null + } + } + }, + renderer: function (oRm, oControl) { + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.addStyle("box-sizing", "border-box"); + oRm.writeStyles(); + oRm.writeElementData(oControl); + oRm.openEnd(); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-before"); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-content"); + oRm.writeStyles(); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-after"); + oRm.openEnd(); + oRm.close("div"); + + oRm.close("div"); + + } + }); + + Frame.prototype.setSrc = function (vValue) { + if (vValue === this.getSrc()) { + return this; + } + //avoid re-rendering + this.setProperty("src", vValue, true); + + this._sRealSource = vValue; + + if (this._oFrameDomRef) { + this._oFrameDomRef.src = this._sRealSource; + } + return this; + }; + + Frame.prototype.init = function () { + this._oVisibleRectObserver = new VisibleRectObserver(); + }; + + Frame.prototype.onBeforeRendering = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + this._hideFrame(); + }; + + Frame.prototype.onAfterRendering = function () { + if (this._sRealSource && this._sRealSource.length < 5) { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + this._sRealSource = ""; + return this; + } + if (false && this._sRealSource.indexOf("http:") === 0) { + this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEHTTPERROR")); + this._sRealSource = ""; + return this; + } + if (this._sRealSource && this._sRealSource.indexOf("https://") !== 0) { + //this._sRealSource = "https://" + this._sRealSource; + } + if (this._sRealSource) { + this._iErrorTimer = window.setTimeout(this._handleError.bind(this), 1000 * 20); + if (!this._oFrameDomRef) { + this._initFrame(); + } + } else { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + } + }; + + Frame.prototype.exit = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + return this; + }; + + Frame.prototype.destroy = function () { + if (this._oFrameDomRef) { + this._oFrameDomRef.parentNode.removeChild(this._oFrameDomRef); + this._oFrameDomRef.src = ""; + } + if (this._oFrameBlockerDomRef) { + this._oFrameBlockerDomRef.parentNode.removeChild(this._oFrameBlockerDomRef); + this._oFrameBlockerDomRef.src = ""; + } + return Control.prototype.destroy.apply(this, arguments); + }; + + Frame.prototype._hideFrame = function () { + //hide the frame until it is loaded + if (!this._oFrameDomRef) { + return; + } + this._oFrameDomRef.style.top = "-10000px"; + this._oFrameDomRef.style.left = "50px"; + }; + + Frame.prototype._initFrame = function () { + var oFrame = document.getElementById("id", this.getId() + "-frame"); + if (oFrame) { + this._oFrameDomRef = oFrame; + return; + } + var iTab = this.getPreview() ? -1 : 0; + this._oFrameDomRef = this._createFrame(this.getId() + "-frame", this._sRealSource, iTab); + oStaticArea.insertBefore(this._oFrameDomRef, oStaticArea.firstChild); + if (this.getPreview()) { + this._oFrameBlockerDomRef = this._createFrame(this.getId() + "-frameblocker", "", iTab); + oStaticArea.insertBefore(this._oFrameBlockerDomRef, oStaticArea.firstChild); + } + }; + + Frame.prototype._createFrame = function (sId, sSource, iTab) { + var oLocalRM = Core.getRenderManager(); + oLocalRM.openStart("iframe"); + oLocalRM.addStyle("position", "absolute"); + oLocalRM.addStyle("border", "none"); + oLocalRM.addStyle("top", "-10000px"); + oLocalRM.addStyle("left", "20px"); + oLocalRM.addStyle("margin", "1px"); + oLocalRM.writeStyles(); + oLocalRM.writeAttribute("tabIndex", "" + iTab); + oLocalRM.writeAttributeEscaped("id", sId); + oLocalRM.writeAttributeEscaped("scrolling", "auto"); + if (sSource) { + oLocalRM.writeAttributeEscaped("src", sSource); + } + oLocalRM.openEnd(); + oLocalRM.close("iframe"); + var div = document.createElement("div"); + oLocalRM.flush(div); + var oFrame = div.firstChild; + oFrame.addEventListener("load", this._handleLoad.bind(this)); + return oFrame; + }; + + Frame.prototype._handleLoad = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + this._oVisibleRectObserver.register(this.getDomRef(), this._syncFramePosition.bind(this)); + }; + + Frame.prototype._handleError = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + //this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEERROR15SEC")); + }; + + Frame.prototype._applyFramePosition = function (oFrame, oElement, oRect) { + if (!oFrame) { + return; + } + if (oRect.height === 0 || oRect.width === 0) { + this._hideFrame(); + return; + } + var iZIndex = getZIndex(oElement); + oFrame.style.zIndex = iZIndex === "auto" ? 2 : iZIndex; + oFrame.style.left = (oRect.left + getScrollLeft()) + "px"; + oFrame.style.top = (oRect.top + getScrollTop()) + "px"; + + if (this.getPreview()) { + var oPreviewInfo = this.getPreview().getTransformContentInfo(); + oFrame.style.width = ((oRect.width - 2) / oPreviewInfo.transformFactor) + "px"; + oFrame.style.height = ((oRect.height - 2) / oPreviewInfo.transformFactor) + "px" + oFrame.style.transform = oPreviewInfo.transformStyle; + oFrame.style.transformOrigin = oPreviewInfo.transformOriginStyle; + oFrame.style.zIndex = oPreviewInfo.zIndex; + } else { + oFrame.style.width = (oRect.width - 2) + "px"; + oFrame.style.height = (oRect.height - 2) + "px"; + } + }; + + Frame.prototype._syncFramePosition = function (oElement, oRect) { + this._applyFramePosition(this._oFrameDomRef, oElement, oRect); + this._applyFramePosition(this._oFrameBlockerDomRef, oElement, oRect); + }; + + Frame.prototype._showMessage = function (sType, sText) { + if (this._oMessage) { + this._oMessage.destroy(); + } + this._oMessage = new MessageStrip(this.getId() + "-message", { + text: sText, + type: sType, + showIcon: true + }); + var oDomRef = this.getDomRef(); + if (oDomRef) { + this._oMessage.placeAt(oDomRef); + } + }; + function focusAfter() { + this.getDomRef("after").focus(); + window.removeEventListener("focus", focusAfter); + } + Frame.prototype.onsaptabnext = function (oEvent) { + if (oEvent.target === this.getDomRef("before")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + + } + } + }; + + Frame.prototype.onsaptabprevious = function (oEvent) { + if (oEvent.target === this.getDomRef("after")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + } + } + }; + return Frame; + +}); diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/controller/Card.controller.js b/advanced/wizard/sample-cards/wz-countdown-card/src/controller/Card.controller.js new file mode 100644 index 0000000..627506e --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/controller/Card.controller.js @@ -0,0 +1,38 @@ +sap.ui.define(['sap/ui/core/mvc/Controller'], + function (Controller) { + "use strict"; + + let CardController = Controller.extend("sap.it.wz.cards.countdown.controller.Card", { + onInit: function () { + if (!this.getOwnerComponent().card) { + return; + } + let oCard = this.getOwnerComponent().card; + let mParams = oCard.getCombinedParameters(); + + let oFrame = this.byId("frame"); + oFrame.setSrc(this._getSrcUrl(mParams).href); + + let iPixelHeight = Math.max(mParams.height, + oCard.getCardContent().getDomRef().offsetHeight); + this.getView().setHeight(iPixelHeight + "px"); + + if (oCard.editor) { + oFrame.setPreview(oCard.editor.preview); + } + }, + _getSrcUrl: function (params) { + window.prms = params; + let url = new URL(params.widgetSrc); + for (let param in params) { + if (!params.hasOwnProperty(param) || param == "widgetSrc") { + continue; + } + url.searchParams.append(param, params[param]); + } + return url; + } + }); + + return CardController; + }); diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/dt/Configuration.js b/advanced/wizard/sample-cards/wz-countdown-card/src/dt/Configuration.js new file mode 100644 index 0000000..378e82d --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/dt/Configuration.js @@ -0,0 +1,199 @@ +sap.ui.define(["sap/ui/integration/Designtime" +], function (Designtime) { + "use strict"; + + var Configuration = Designtime.extend("sap.workzone.cpkg.card.sample.Configuration"); + Configuration.prototype.create = function () { + return { + form: { + items: { + "headerGroup": { + "label": "Header options", + "type": "group", + "hint": "In case of troubles please visit SAP Work Zone Help Center" + }, + "headerVisibility": { + "manifestpath": "/sap.card/header/visible", + "type": "boolean", + "label": "Visible Header", + "defaultValue" : true + }, + "title": { + "manifestpath": "/sap.card/header/title", + "type": "string", + "defaultValue": "Countdown", + "label": "Title", + "visible": "{items>headerVisibility/value}" + }, + "subTitle": { + "manifestpath": "/sap.card/header/subTitle", + "type": "string", + "defaultValue": "", + "label": "Subtitle", + "visible": "{items>headerVisibility/value}" + }, + "headericon": { + "manifestpath": "/sap.card/header/icon/src", + "type": "string", + "label": "Card Icon", + "allowDynamicValues": false, + "allowSettings": false, + "visualization": { + "type": "IconSelect", + "settings": { + "value": "{currentSettings>value}", + "editable": "{currentSettings>editable}" + } + }, + "visible": "{items>headerVisibility/value}" + }, + "bodyGroup": { + "label": "Body options", + "type": "group" + }, + "widgetSrc": { + "manifestpath": "/sap.card/configuration/parameters/widgetSrc/value", + "type": "string", + "defaultValue": "https://opensocialgadgets-a426ead53.dispatcher.hana.ondemand.com/cards/countdown/web/index.html", + "label": "Widget Source URL", + "visible" : false + }, + "targetDate": { + "manifestpath": "/sap.card/configuration/parameters/targetDate/value", + "type": "datetime", + "defaultValue": new Date(), + "label": "Final Countdown Date" + }, + "seconds": { + "manifestpath": "/sap.card/configuration/parameters/seconds/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Seconds" + }, + "minutes": { + "manifestpath": "/sap.card/configuration/parameters/minutes/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Minutes" + }, + "hours": { + "manifestpath": "/sap.card/configuration/parameters/hours/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Hours" + }, + "days": { + "manifestpath": "/sap.card/configuration/parameters/days/value", + "type": "boolean", + "defaultValue": true, + "label": "Show Days" + }, + "weeks": { + "manifestpath": "/sap.card/configuration/parameters/weeks/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Weeks" + }, + "months": { + "manifestpath": "/sap.card/configuration/parameters/months/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Months" + }, + "years": { + "manifestpath": "/sap.card/configuration/parameters/years/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Years" + }, + "showCircles": { + "manifestpath": "/sap.card/configuration/parameters/showCircles/value", + "type": "boolean", + "defaultValue": true, + "label": "Display Circles" + }, + "filledStyle": { + "manifestpath": "/sap.card/configuration/parameters/filledStyle/value", + "type": "boolean", + "defaultValue": true, + "label": "Filled Style", + "visible": "{items>showCircles/value}" + }, + "color": { + "manifestpath": "/sap.card/configuration/parameters/color/value", + "values": { + "data": { + "json": [ + { "text": "Black", "key": "#000000" }, + { "text": "Grey", "key": "#40484F" }, + { "text": "Red", "key": "#FF0000" }, + { "text": "Green", "key": "#00FF00" }, + { "text": "Blue", "key": "#0000FF" }, + { "text": "Yellow", "key": "#FFFF00" }, + { "text": "Cyan", "key": "#00FFFF" }, + { "text": "Magenta", "key": "#FF00FF" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "", + "label": "Circles Color", + "type": "string" + }, + "circlesHeight": { + "manifestpath": "/sap.card/configuration/parameters/circlesHeight/value", + "type": "integer", + "defaultValue": 120, + "label": "Circles Height in Pixels" + }, + "url": { + "manifestpath": "/sap.card/configuration/parameters/url/value", + "type": "string", + "defaultValue": "", + "label": "Read More URL" + }, + "startDate": { + "manifestpath": "/sap.card/configuration/parameters/startDate/value", + "type": "datetime", + "defaultValue": new Date(), + "visible": false + }, + "endMessage": { + "manifestpath": "/sap.card/configuration/parameters/endMessage/value", + "type": "string", + "defaultValue": "", + "label": "Countdown End Message" + }, + "height": { + "manifestpath": "/sap.card/configuration/parameters/height/value", + "type": "integer", + "defaultValue": 570, + "label": "Height in pixels", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 30, + "max": 600, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + } + } + }, + preview: { + modes: "Live" + } + }; + }; + return Configuration; +}); + + diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/manifest.json b/advanced/wizard/sample-cards/wz-countdown-card/src/manifest.json new file mode 100644 index 0000000..797eff2 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/manifest.json @@ -0,0 +1,123 @@ +{ + "sap.app": { + "id": "sap.it.wz.cards.countdown", + "type": "card", + "title": "Countdown", + "subTitle": "Countdown", + "applicationVersion": { + "version": "1.1.5" + }, + "shortTitle": "Countdown", + "info": "Countdown", + "description": "Displays a countdown to a chosen date with the option of an end message.", + "tags": { + "keywords": [ + "Countdown", + "SAP IT" + ] + } + }, + "sap.ui": { + "technology": "UI5", + "icons": { + "icon": "sap-icon://fob-watch" + } + }, + "sap.ui5": { + "dependencies": { + "minUI5Version": "1.77.2", + "libs": { + "sap.ui.core": {}, + "sap.m": {} + } + }, + "rootView": { + "viewName": "sap.it.wz.cards.countdown.view.Card", + "type": "XML", + "async": true, + "id": "app" + }, + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "sap.it.wz.cards.countdown.i18n.i18n" + } + } + } + }, + "sap.platform.mobilecards": { + "_version": "1.0.0", + "compatible": false + }, + "sap.card": { + "designtime": "./dt/Configuration", + "type": "Component", + "header": { + "title": "Countdown", + "subTitle": "", + "icon": { + "src": "sap-icon://lateness" + }, + "visible" : true + }, + "configuration": { + "parameters": { + "showCardHeader": { + "value": true + }, + "widgetSrc": { + "value": "https://opensocialgadgets-a426ead53.dispatcher.hana.ondemand.com/cards/countdown/web/index.html" + }, + "targetDate": { + "value": null + }, + "seconds": { + "value": false + }, + "minutes": { + "value": false + }, + "hours": { + "value": false + }, + "days": { + "value": true + }, + "weeks": { + "value": false + }, + "months": { + "value": false + }, + "years": { + "value": false + }, + "showCircles": { + "value": true + }, + "filledStyle": { + "value": false + }, + "color": { + "value": "#40484F" + }, + "circlesHeight": { + "value": 120 + }, + "url": { + "value": "" + }, + "startDate": { + "value": null + }, + "endMessage": { + "value": "" + }, + "height": { + "value": 144 + } + } + } + } +} \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/test-resources/manual/index.html b/advanced/wizard/sample-cards/wz-countdown-card/src/test-resources/manual/index.html new file mode 100644 index 0000000..25b8f9c --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/test-resources/manual/index.html @@ -0,0 +1,73 @@ + + + + + + + sap.it.wz.cards.countdown + + + + + + + +
+ + + +
+
+ +
+ + + + \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-countdown-card/src/view/Card.view.xml b/advanced/wizard/sample-cards/wz-countdown-card/src/view/Card.view.xml new file mode 100644 index 0000000..775a5d8 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/src/view/Card.view.xml @@ -0,0 +1,6 @@ + + + diff --git a/advanced/wizard/sample-cards/wz-countdown-card/ui5.yaml b/advanced/wizard/sample-cards/wz-countdown-card/ui5.yaml new file mode 100644 index 0000000..e3863f7 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-countdown-card/ui5.yaml @@ -0,0 +1,16 @@ +specVersion: "2.0" +metadata: + name: sap-it-wz-cards-countdown + copyright: |- + SAP Work Zone + * (c) Copyright 2009-2024 SAP SE or an SAP affiliate company. +type: application +resources: + configuration: + paths: + webapp: src + propertiesFileSourceEncoding: UTF-8 +builder: + resources: + excludes: + - "test-resources/**" \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/package.json b/advanced/wizard/sample-cards/wz-flip-card-card/package.json new file mode 100644 index 0000000..2d65d92 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/package.json @@ -0,0 +1,18 @@ +{ + "name": "sap-it-wz-cards-flip_card", + "version": "1.28.0", + "description": "", + "private": true, + "scripts": { + "start": "ui5 serve --o /test-resources/manual/index.html", + "eslint": "eslint src", + "build": "rimraf dist && ui5 build && zip sap-it-wz-cards-flip_card.zip -r ./dist" + }, + "devDependencies": { + "@openui5/sap.ui.core": "1.77.2", + "@openui5/sap.ui.integration": "1.77.2", + "@ui5/cli": "2.2.3", + "eslint": "5.16.0", + "rimraf": "2.6.2" + } +} diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/sap-it-wz-cards-flip_card.zip b/advanced/wizard/sample-cards/wz-flip-card-card/sap-it-wz-cards-flip_card.zip new file mode 100644 index 0000000..5e0b07b Binary files /dev/null and b/advanced/wizard/sample-cards/wz-flip-card-card/sap-it-wz-cards-flip_card.zip differ diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/Component.js b/advanced/wizard/sample-cards/wz-flip-card-card/src/Component.js new file mode 100644 index 0000000..793c94c --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/Component.js @@ -0,0 +1,23 @@ +/* + * ! ${copyright} + */ +sap.ui.define(["sap/ui/core/UIComponent"], function (UIComponent) { + "use strict"; + var ChatbotComponent = UIComponent.extend("sap.it.wz.cards.flip_card.component.Component", { + onCardReady: function (oCard) { + // Holds the card for use inside the controller + this.card = oCard; + + // Can get all parameters with method getCombinedParameters + oCard.getCombinedParameters(); + + // Get any section of the card manifest with method getManifestEntry + oCard.getManifestEntry("/sap.card"); + + // When in context of a Host, like in Work Zone you can use the following methods + // oCard.getHostInstance(); + // oCard.resolveDestination("myDestination"); // check more in the destinations sample + } + }); + return ChatbotComponent; +}); diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/control/Frame.js b/advanced/wizard/sample-cards/wz-flip-card-card/src/control/Frame.js new file mode 100644 index 0000000..3faeda1 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/control/Frame.js @@ -0,0 +1,350 @@ +/* + * ! ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/Control", + "sap/ui/core/Core", + "sap/m/MessageStrip" +], function ( + Control, + Core, + MessageStrip +) { + "use strict"; + + var oStaticArea = Core.getStaticAreaRef(); + + function getScrollTop() { + var B = document.body; + var D = document.documentElement; + D = (D.clientHeight) ? D : B; + return D.scrollTop; + } + + function getScrollLeft() { + var B = document.body; + var D = document.documentElement; + D = (D.clientWidth) ? D : B; + return D.scrollLeft; + } + + function getZIndex(e) { + var z = window.getComputedStyle(e).getPropertyValue('z-index'); + if (isNaN(z)) { + if (e.parentNode && e.parentNode.nodeType === 1) { + return getZIndex(e.parentNode); + } else { + return "auto"; + } + } else { + return z; + } + } + + //Registers an animation frame timer to check whether the position of oDomRef changed + //and calls the handler if it did + var VisibleRectObserver = function (oDomRef, fnHandler) { + if (!VisibleRectObserver._instance) { + VisibleRectObserver._instance = this; + this._elements = []; + this._sizes = []; + this._handlers = []; + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + } + + if (oDomRef && fnHandler) { + VisibleRectObserver._instance.register(oDomRef, fnHandler); + } + return VisibleRectObserver._instance; + }; + + //loops over the elements and checks for size and position changes + VisibleRectObserver.prototype.checkAll = function () { + for (var i = 0; i < this._elements.length; i++) { + this.check(i); + } + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + }; + + //checks size and position changes for an element and calls the handler + VisibleRectObserver.prototype.check = function (i) { + var el = this._elements[i]; + var size = el.getBoundingClientRect(), + s = JSON.stringify(size); + if (this._sizes[i] !== s) { + this._sizes[i] = s; + this._handlers[i](el, size); + } + }; + + //registers a dom element and handler to be observed for size and position changes + VisibleRectObserver.prototype.register = function (oDomElement, fnHandler) { + if (this._elements.indexOf(oDomElement) > -1) { + return; + } + this._elements.push(oDomElement); + this._sizes.push(""); + this._handlers.push(fnHandler); + this.check(VisibleRectObserver._instance._sizes.length - 1); + }; + + //deregisters a dom element from observation + VisibleRectObserver.prototype.deregister = function (oDomElement) { + var iIndex = this._elements.indexOf(oDomElement); + if (iIndex === -1) { + return; + } + this._elements.splice(iIndex, 1); + this._sizes.splice(iIndex, 1); + this._handlers.splice(iIndex, 1); + }; + + + var Frame = Control.extend("sap.it.wz.cards.flip_card.control.Frame", { + metadata: { + properties: { + src: { + type: "string" + }, + preview: { + type: "object", + defaultValue: null + } + } + }, + renderer: function (oRm, oControl) { + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.addStyle("box-sizing", "border-box"); + oRm.writeStyles(); + oRm.writeElementData(oControl); + oRm.openEnd(); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-before"); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-content"); + oRm.writeStyles(); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-after"); + oRm.openEnd(); + oRm.close("div"); + + oRm.close("div"); + + } + }); + + Frame.prototype.setSrc = function (vValue) { + if (vValue === this.getSrc()) { + return this; + } + //avoid re-rendering + this.setProperty("src", vValue, true); + + this._sRealSource = vValue; + + if (this._oFrameDomRef) { + this._oFrameDomRef.src = this._sRealSource; + } + return this; + }; + + Frame.prototype.init = function () { + this._oVisibleRectObserver = new VisibleRectObserver(); + }; + + Frame.prototype.onBeforeRendering = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + this._hideFrame(); + }; + + Frame.prototype.onAfterRendering = function () { + if (this._sRealSource && this._sRealSource.length < 5) { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + this._sRealSource = ""; + return this; + } + if (false && this._sRealSource.indexOf("http:") === 0) { + this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEHTTPERROR")); + this._sRealSource = ""; + return this; + } + if (this._sRealSource && this._sRealSource.indexOf("https://") !== 0) { + //this._sRealSource = "https://" + this._sRealSource; + } + if (this._sRealSource) { + this._iErrorTimer = window.setTimeout(this._handleError.bind(this), 1000 * 20); + if (!this._oFrameDomRef) { + this._initFrame(); + } + } else { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + } + }; + + Frame.prototype.exit = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + return this; + }; + + Frame.prototype.destroy = function () { + if (this._oFrameDomRef) { + this._oFrameDomRef.parentNode.removeChild(this._oFrameDomRef); + this._oFrameDomRef.src = ""; + } + if (this._oFrameBlockerDomRef) { + this._oFrameBlockerDomRef.parentNode.removeChild(this._oFrameBlockerDomRef); + this._oFrameBlockerDomRef.src = ""; + } + return Control.prototype.destroy.apply(this, arguments); + }; + + Frame.prototype._hideFrame = function () { + //hide the frame until it is loaded + if (!this._oFrameDomRef) { + return; + } + this._oFrameDomRef.style.top = "-10000px"; + this._oFrameDomRef.style.left = "50px"; + }; + + Frame.prototype._initFrame = function () { + var oFrame = document.getElementById("id", this.getId() + "-frame"); + if (oFrame) { + this._oFrameDomRef = oFrame; + return; + } + var iTab = this.getPreview() ? -1 : 0; + this._oFrameDomRef = this._createFrame(this.getId() + "-frame", this._sRealSource, iTab); + oStaticArea.insertBefore(this._oFrameDomRef, oStaticArea.firstChild); + if (this.getPreview()) { + this._oFrameBlockerDomRef = this._createFrame(this.getId() + "-frameblocker", "", iTab); + oStaticArea.insertBefore(this._oFrameBlockerDomRef, oStaticArea.firstChild); + } + }; + + Frame.prototype._createFrame = function (sId, sSource, iTab) { + var oLocalRM = Core.getRenderManager(); + oLocalRM.openStart("iframe"); + oLocalRM.addStyle("position", "absolute"); + oLocalRM.addStyle("border", "none"); + oLocalRM.addStyle("top", "-10000px"); + oLocalRM.addStyle("left", "20px"); + oLocalRM.addStyle("margin", "1px"); + oLocalRM.writeStyles(); + oLocalRM.writeAttribute("tabIndex", "" + iTab); + oLocalRM.writeAttributeEscaped("id", sId); + oLocalRM.writeAttributeEscaped("scrolling", "auto"); + if (sSource) { + oLocalRM.writeAttributeEscaped("src", sSource); + } + oLocalRM.openEnd(); + oLocalRM.close("iframe"); + var div = document.createElement("div"); + oLocalRM.flush(div); + var oFrame = div.firstChild; + oFrame.addEventListener("load", this._handleLoad.bind(this)); + return oFrame; + }; + + Frame.prototype._handleLoad = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + this._oVisibleRectObserver.register(this.getDomRef(), this._syncFramePosition.bind(this)); + }; + + Frame.prototype._handleError = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + //this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEERROR15SEC")); + }; + + Frame.prototype._applyFramePosition = function (oFrame, oElement, oRect) { + if (!oFrame) { + return; + } + if (oRect.height === 0 || oRect.width === 0) { + this._hideFrame(); + return; + } + var iZIndex = getZIndex(oElement); + oFrame.style.zIndex = iZIndex === "auto" ? 2 : iZIndex; + oFrame.style.left = (oRect.left + getScrollLeft()) + "px"; + oFrame.style.top = (oRect.top + getScrollTop()) + "px"; + + if (this.getPreview()) { + var oPreviewInfo = this.getPreview().getTransformContentInfo(); + oFrame.style.width = ((oRect.width - 2) / oPreviewInfo.transformFactor) + "px"; + oFrame.style.height = ((oRect.height - 2) / oPreviewInfo.transformFactor) + "px" + oFrame.style.transform = oPreviewInfo.transformStyle; + oFrame.style.transformOrigin = oPreviewInfo.transformOriginStyle; + oFrame.style.zIndex = oPreviewInfo.zIndex; + } else { + oFrame.style.width = (oRect.width - 2) + "px"; + oFrame.style.height = (oRect.height - 2) + "px"; + } + }; + + Frame.prototype._syncFramePosition = function (oElement, oRect) { + this._applyFramePosition(this._oFrameDomRef, oElement, oRect); + this._applyFramePosition(this._oFrameBlockerDomRef, oElement, oRect); + }; + + Frame.prototype._showMessage = function (sType, sText) { + if (this._oMessage) { + this._oMessage.destroy(); + } + this._oMessage = new MessageStrip(this.getId() + "-message", { + text: sText, + type: sType, + showIcon: true + }); + var oDomRef = this.getDomRef(); + if (oDomRef) { + this._oMessage.placeAt(oDomRef); + } + }; + function focusAfter() { + this.getDomRef("after").focus(); + window.removeEventListener("focus", focusAfter); + } + Frame.prototype.onsaptabnext = function (oEvent) { + if (oEvent.target === this.getDomRef("before")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + + } + } + }; + + Frame.prototype.onsaptabprevious = function (oEvent) { + if (oEvent.target === this.getDomRef("after")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + } + } + }; + return Frame; + +}); diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/controller/Card.controller.js b/advanced/wizard/sample-cards/wz-flip-card-card/src/controller/Card.controller.js new file mode 100644 index 0000000..4594319 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/controller/Card.controller.js @@ -0,0 +1,213 @@ +sap.ui.define(["sap/ui/core/mvc/Controller"], function (Controller) { + "use strict"; + + return Controller.extend("sap.it.wz.cards.flip_card.controller.Card", { + onInit: function () { + if (!this.getOwnerComponent().card) { + return; + } + let oCard = this.getOwnerComponent().card; + let mParameters = oCard.getCombinedParameters(); + + + let htmlContent = this._getWidgetHtml(mParameters); + let oFrame = this._createIframe(htmlContent); + + if (oCard.editor) { + oFrame.setPreview(oCard.editor.preview); + } + + this.getView().setHeight(mParameters.height + 12 + "px"); + }, + _createIframe: function (content) { + let minimizedContent = content.replaceAll(/\n\s*/g, ''); + let blob = new Blob([minimizedContent], { type: "text/html" }); + let oFrame = this.byId("frame"); + oFrame.setSrc(URL.createObjectURL(blob)); + return oFrame; + }, + _getWidgetHtml: function (params) { + let innerHtml = `
+
+
+

${params.frontHeader}

+
+
+

${params.frontDescription}

+
+
+

${params.frontCaption}

+
+
+
+
+

${params.backHeader}

+
+
+

${params.backDescription}

+
+
+

${params.backCaption}

+
+
+
`; + + if (params.url && params.url.length > 0) { + innerHtml = `${innerHtml}`; + } + + return ` + + + + + +
+
${innerHtml}
+
+ + `; + }, + _getWidgetStyle: function (params) { + function hasText(paramName) { + return params[paramName].length > 0; + } + function getStyleParam(param) { + return (param && param != "" ? param : null); + } + + let frontHeaderHeight = hasText("frontHeader") ? 20 : 0; + let frontCaptionHeight = hasText("frontCaption") ? 20 : 0; + let frontDescriptionHeight = 90 - frontHeaderHeight - frontCaptionHeight; + let backHeaderHeight = hasText("backHeader") ? 20 : 0; + let backCaptionHeight = hasText("backCaption") ? 20 : 0; + let backDescriptionHeight = 90 - backHeaderHeight - backCaptionHeight; + + let frontColor = getStyleParam(params.frontColor); + let frontImage = getStyleParam(params.frontImage); + let frontTextShadow = getStyleParam(params.frontTextShadow); + let backColor = getStyleParam(params.backColor); + let backImage = getStyleParam(params.backImage); + let backTextShadow = getStyleParam(params.backTextShadow); + + return ` + html, body { + height: 100%; + width: 100%; + margin: 0; + overflow: auto; + font-family: Arial, Helvetica, sans-serif; + } + .settings-body { + background-color: #FFF; + } + .flip-card { + background-color: transparent; + width: 200px; + height: 200px; + padding: 5px 0; + perspective: 2500px; + -webkit-perspective: 2500px; + } + .flip-card-inner { + position: relative; + width: 100%; + height: 100%; + text-align: center; + transition: transform 0.8s; + transform-style: preserve-3d; + } + .flip-card:hover .flip-card-inner { + transform: rotateY(180deg); + } + .flip-card-front, + .flip-card-back { + position: absolute; + width: 100%; + height: 100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + } + .flip-card-front { + background-color: white; + color: black; + } + .flip-card-back { + background-color: dodgerblue; + color: white; + transform: rotateY(180deg); + } + .section { + display: flex; + margin: auto; + text-align: center; + overflow: hidden; + } + .header-section, + .caption-section { + height: 20%; + } + .description-section { + height: 50%; + padding-top: 5%; + padding-bottom: 5%; + } + #flip_card p { + margin: auto; + padding: 0 5%; + } + #body { + display: flex; + justify-content: center; + overflow: hidden; + } + .flip-card { + width: ${params.height}px; + height: ${params.height}px; + } + .flip-card-front { + ${frontColor ? `background-color: ${frontColor};` : ""} + ${frontImage ? `background-image: url("${frontImage}");` : ""} + ${frontTextShadow ? `text-shadow: ${frontTextShadow};` : ""} + color: ${params.frontFontColor}; + font-size: ${params.frontFontSize}px; + } + .flip-card-back { + ${backColor ? `background-color: ${backColor};` : ""} + ${backImage ? `background-image: url("${backImage}");` : ""} + ${backTextShadow ? `text-shadow: ${backTextShadow};` : ""} + color: ${params.backFontColor}; + font-size: ${params.backFontSize}px; + } + .flip-card-front .header-section{ + height: ${frontHeaderHeight}%; + font-size: 1.5em; + } + .flip-card-front .description-section { + height: ${frontDescriptionHeight}%; + } + .flip-card-front .caption-section { + height: ${frontCaptionHeight}%; + } + .flip-card-back .header-section{ + height: ${backHeaderHeight}%; + } + .flip-card-back .description-section { + height: ${backDescriptionHeight}%; + } + .flip-card-back .caption-section { + height: ${backCaptionHeight}%; + } + .header-section{ + font-size: 1.5em; + } + .caption-section{ + font-size: 1.2em; + } + `; + }, + }); +}); diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/dt/configuration.js b/advanced/wizard/sample-cards/wz-flip-card-card/src/dt/configuration.js new file mode 100644 index 0000000..def9a30 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/dt/configuration.js @@ -0,0 +1,195 @@ +sap.ui.define(["sap/ui/integration/Designtime" +], function (Designtime) { + "use strict"; + + var Configuration = Designtime.extend("sap.workzone.cpkg.card.sample.Configuration"); + Configuration.prototype.create = function () { + return { + form: { + items: { + "headerGroup": { + "label": "Header options", + "type": "group", + "hint": "In case of troubles please visit SAP Work Zone Help Center" + }, + "headerVisibility": { + "manifestpath": "/sap.card/header/visible", + "type": "boolean", + "label": "Visible Header", + "defaultValue" : true + }, + "title": { + "manifestpath": "/sap.card/header/title", + "type": "string", + "defaultValue": "Flip Card", + "label": "Title", + "visible": "{items>headerVisibility/value}" + }, + "subTitle": { + "manifestpath": "/sap.card/header/subTitle", + "type": "string", + "defaultValue": "", + "label": "Subtitle", + "visible": "{items>headerVisibility/value}" + }, + "headericon": { + "manifestpath": "/sap.card/header/icon/src", + "type": "string", + "label": "Card Icon", + "allowDynamicValues": false, + "allowSettings": false, + "visualization": { + "type": "IconSelect", + "settings": { + "value": "{currentSettings>value}", + "editable": "{currentSettings>editable}" + } + }, + "visible": "{items>headerVisibility/value}" + }, + "bodyGroup": { + "label": "Body options", + "type": "group" + }, + "url": { + "manifestpath": "/sap.card/configuration/parameters/url/value", + "type": "string", + "defaultValue": "", + "label": "Navigation URL" + }, + "height": { + "manifestpath": "/sap.card/configuration/parameters/height/value", + "type": "integer", + "defaultValue": 570, + "label": "Height in pixels", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 30, + "max": 600, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + }, + "group1": { + "label": "Front Side Settings", + "type": "group" + }, + "frontHeader": { + "manifestpath": "/sap.card/configuration/parameters/frontHeader/value", + "type": "string", + "defaultValue": "", + "label": "Header Text" + }, + "frontDescription": { + "manifestpath": "/sap.card/configuration/parameters/frontDescription/value", + "type": "string", + "defaultValue": "", + "label": "Description Text" + }, + "frontCaption": { + "manifestpath": "/sap.card/configuration/parameters/frontCaption/value", + "type": "string", + "defaultValue": "", + "label": "Caption Text" + }, + "frontImage": { + "manifestpath": "/sap.card/configuration/parameters/frontImage/value", + "type": "string", + "defaultValue": "", + "label": "Background Image Link" + }, + "frontColor": { + "manifestpath": "/sap.card/configuration/parameters/frontColor/value", + "type": "string", + "defaultValue": "#EEEEEE", + "label": "Background Color" + }, + "frontFontSize": { + "manifestpath": "/sap.card/configuration/parameters/frontFontSize/value", + "type": "integer", + "defaultValue": 16, + "label": "Font Size in pixel" + }, + "frontFontColor": { + "manifestpath": "/sap.card/configuration/parameters/frontFontColor/value", + "type": "string", + "defaultValue": "#000000", + "label": "Font Color" + }, + "frontTextShadow": { + "manifestpath": "/sap.card/configuration/parameters/frontTextShadow/value", + "type": "string", + "defaultValue": "", + "label": "Text Shadow CSS", + "placeholder": "e.g. grey 1px 1px 0px" + }, + "group2": { + "label": "Back Side Settings", + "type": "group" + }, + "backHeader": { + "manifestpath": "/sap.card/configuration/parameters/backHeader/value", + "type": "string", + "defaultValue": "", + "label": "Header Text" + }, + "backDescription": { + "manifestpath": "/sap.card/configuration/parameters/backDescription/value", + "type": "string", + "defaultValue": "", + "label": "Description Text" + }, + "backCaption": { + "manifestpath": "/sap.card/configuration/parameters/backCaption/value", + "type": "string", + "defaultValue": "", + "label": "Caption Text" + }, + "backImage": { + "manifestpath": "/sap.card/configuration/parameters/backImage/value", + "type": "string", + "defaultValue": "", + "label": "Background Image Link" + }, + "backColor": { + "manifestpath": "/sap.card/configuration/parameters/backColor/value", + "type": "string", + "defaultValue": "#EEEEEE", + "label": "Background Color" + }, + "backFontSize": { + "manifestpath": "/sap.card/configuration/parameters/backFontSize/value", + "type": "integer", + "defaultValue": 16, + "label": "Font Size in pixel" + }, + "backFontColor": { + "manifestpath": "/sap.card/configuration/parameters/backFontColor/value", + "type": "string", + "defaultValue": "#000000", + "label": "Font Color" + }, + "backTextShadow": { + "manifestpath": "/sap.card/configuration/parameters/backTextShadow/value", + "type": "string", + "defaultValue": "", + "label": "Text Shadow CSS", + "placeholder": "e.g. grey 1px 1px 0px" + } + } + }, + preview: { + modes: "Live" + } + }; + }; + return Configuration; +}); + + diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/manifest.json b/advanced/wizard/sample-cards/wz-flip-card-card/src/manifest.json new file mode 100644 index 0000000..6d2b63d --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/manifest.json @@ -0,0 +1,126 @@ +{ + "sap.app": { + "id": "sap.it.wz.cards.flip_card", + "type": "card", + "title": "Flip Card", + "subTitle": "Flip Card", + "applicationVersion": { + "version": "1.2.4" + }, + "shortTitle": "Flip Card", + "info": "Flip Card", + "description": "Enrich your workspace look and feel with flip card animations.", + "tags": { + "keywords": [ + "Flip Card", + "SAP IT" + ] + } + }, + "sap.ui": { + "technology": "UI5", + "icons": { + "icon": "sap-icon://duplicate" + } + }, + "sap.ui5": { + "dependencies": { + "minUI5Version": "1.77.2", + "libs": { + "sap.ui.core": {}, + "sap.m": {} + } + }, + "rootView": { + "viewName": "sap.it.wz.cards.flip_card.view.Card", + "type": "XML", + "async": true, + "id": "app" + }, + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "sap.it.wz.cards.flip_card.i18n.i18n" + } + } + } + }, + "sap.platform.mobilecards": { + "_version": "1.0.0", + "compatible": false + }, + "sap.card": { + "type": "Component", + "designtime": "dt/configuration", + "header": { + "title": "Flip Card", + "subTitle": "by @SAP", + "icon": { + "src": "sap-icon://share" + }, + "visible": true + }, + "configuration": { + "parameters": { + "showCardHeader": { + "value": true + }, + "url": { + "value": "" + }, + "height": { + "value": 200 + }, + "frontHeader": { + "value": "" + }, + "frontDescription": { + "value": "" + }, + "frontCaption": { + "value": "" + }, + "frontImage": { + "value": "" + }, + "frontColor": { + "value": "#EEEEEE" + }, + "frontFontSize": { + "value": 16 + }, + "frontFontColor": { + "value": "#000000" + }, + "frontTextShadow": { + "value": "" + }, + "backHeader": { + "value": "" + }, + "backDescription": { + "value": "" + }, + "backCaption": { + "value": "" + }, + "backImage": { + "value": "" + }, + "backColor": { + "value": "#EEEEEE" + }, + "backFontSize": { + "value": 16 + }, + "backFontColor": { + "value": "#000000" + }, + "backTextShadow": { + "value": "" + } + } + } + } +} \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/test-resources/manual/index.html b/advanced/wizard/sample-cards/wz-flip-card-card/src/test-resources/manual/index.html new file mode 100644 index 0000000..cbe83fd --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/test-resources/manual/index.html @@ -0,0 +1,73 @@ + + + + + + + sap.it.wz.cards.flip_card + + + + + + + +
+ + + +
+
+ +
+ + + + \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/src/view/Card.view.xml b/advanced/wizard/sample-cards/wz-flip-card-card/src/view/Card.view.xml new file mode 100644 index 0000000..9ba860d --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/src/view/Card.view.xml @@ -0,0 +1,6 @@ + + + diff --git a/advanced/wizard/sample-cards/wz-flip-card-card/ui5.yaml b/advanced/wizard/sample-cards/wz-flip-card-card/ui5.yaml new file mode 100644 index 0000000..623d7f8 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-flip-card-card/ui5.yaml @@ -0,0 +1,16 @@ +specVersion: "2.0" +metadata: + name: sap-it-wz-cards-flip_card + copyright: |- + SAP Work Zone + * (c) Copyright 2009-2024 SAP SE or an SAP affiliate company. +type: application +resources: + configuration: + paths: + webapp: src + propertiesFileSourceEncoding: UTF-8 +builder: + resources: + excludes: + - "test-resources/**" \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/package.json b/advanced/wizard/sample-cards/wz-stackoverflow-card/package.json new file mode 100644 index 0000000..d6ceeb4 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-stackoverflow-card/package.json @@ -0,0 +1,19 @@ +{ + "name": "sap-it-wz-cards-stackoverflow", + "version": "1.28.0", + "description": "", + "private": true, + "scripts": { + "start": "ui5 serve --o /test-resources/manual/index.html", + "eslint": "eslint src", + "build": "rimraf dist && ui5 build && zip sap-it-wz-cards-stackoverflow.zip -r ./dist" + }, + "dependencies": {}, + "devDependencies": { + "rimraf": "2.6.2", + "@openui5/sap.ui.core": "1.77.2", + "@openui5/sap.ui.integration": "1.77.2", + "@ui5/cli": "2.2.3", + "eslint": "5.16.0" + } +} diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/sap-it-wz-cards-stackoverflow.zip b/advanced/wizard/sample-cards/wz-stackoverflow-card/sap-it-wz-cards-stackoverflow.zip new file mode 100644 index 0000000..db8f7cf Binary files /dev/null and b/advanced/wizard/sample-cards/wz-stackoverflow-card/sap-it-wz-cards-stackoverflow.zip differ diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/src/dt/Configuration.js b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/dt/Configuration.js new file mode 100644 index 0000000..ea53320 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/dt/Configuration.js @@ -0,0 +1,150 @@ +sap.ui.define(["sap/ui/integration/Designtime" +], function (Designtime) { + "use strict"; + +/* + This is description of configuration ui. Here you can provide your values + to customize your card configuration +*/ + + var Configuration = Designtime.extend("sap.workzone.cpkg.card.sample.Configuration"); + Configuration.prototype.create = function () { + return { + form: { + items: { + "group1": { + "label": "Header options", + "type": "group", + "hint": "In case of troubles please visit SAP Work Zone Help Center" + }, + "headerVisibility": { + "manifestpath": "/sap.card/header/visible", + "type": "boolean", + "label": "Visible Header", + "defaultValue" : true + }, + "title": { + "manifestpath": "/sap.card/header/title", + "type": "string", + "defaultValue": "Stack", + "label": "Title", + "visible": "{items>headerVisibility/value}" + }, + "subTitle": { + "manifestpath": "/sap.card/header/subTitle", + "type": "string", + "defaultValue": "", + "label": "Subtitle", + "visible": "{items>headerVisibility/value}" + }, + "headericon": { + "manifestpath": "/sap.card/header/icon/src", + "type": "string", + "label": "Card Icon", + "allowDynamicValues": false, + "allowSettings": false, + "visualization": { + "type": "IconSelect", + "settings": { + "value": "{currentSettings>value}", + "editable": "{currentSettings>editable}" + } + }, + "visible": "{items>headerVisibility/value}" + }, + "group2": { + "label": "Body options", + "type": "group" + }, + "tagged": { + "manifestpath": "/sap.card/configuration/parameters/tagged/value", + "type": "string", + "defaultValue": "stack-overflow-for-teams", + "label": "Tags divided by semicolon" + }, + "sort": { + "manifestpath": "/sap.card/configuration/parameters/sort/value", + "values": { + "data": { + "json": [ + { "key": "activity", "text": "activity" }, + { "key": "creation", "text": "creation" }, + { "key": "votes", "text": "votes" }, + { "key": "relevance", "text": "relevance" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "activity", + "label": "Sort Type", + "type": "string" + }, + "order": { + "manifestpath": "/sap.card/configuration/parameters/order/value", + "values": { + "data": { + "json": [ + { "key": "desc", "text": "descending" }, + { "key": "asc", "text": "ascending" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "desc", + "label": "Sort Order", + "type": "string" + }, + "date": { + "manifestpath": "/sap.card/configuration/parameters/date/value", + "values": { + "data": { + "json": [ + { "key": "last_activity", "text": "Last activity" }, + { "key": "creation", "text": "Creation" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "creation", + "label": "Date to show", + "type": "string" + }, + "maxItems": { + "manifestpath": "/sap.card/configuration/parameters/maxItems/value", + "type": "integer", + "defaultValue": 5, + "label": "Number of Questions", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 1, + "max": 10, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + } + } + }, + preview: { + modes: "Live" + } + }; + }; + return Configuration; +}); + + diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/src/ext/DataFormatter.js b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/ext/DataFormatter.js new file mode 100644 index 0000000..d28a0f0 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/ext/DataFormatter.js @@ -0,0 +1,129 @@ +sap.ui.define(["sap/ui/integration/Extension"], function (Extension) { + "use strict"; + + var DataFormatter = Extension.extend("sap.it.wz.cards.stackoverflow.extension"); + /* + Here is Extension class which is used to receive data to display on card. + */ + DataFormatter.prototype.init = function () { + Extension.prototype.init.apply(this, arguments); + this.attachAction(this._handleAction.bind(this)); + }; + + + + // CAN BE REPLACED: Name of the function that used as Extension (getData) + DataFormatter.prototype.getData = function () { + + let oCard = this.getCard(); + let oParameters = oCard.getCombinedParameters(); + let url = oParameters.url; + url += "&tagged="+oParameters.tagged + url += "&sort="+oParameters.sort + url += "&order="+oParameters.order + url += "&pagesize="+(oParameters.maxItems) + + return this.getCard().request({ // sending of request with url and dataType parameters + "url": url, + "dataType": "json" + }).then(function (oXMLDocument) { + let aItems = Array.prototype.map.call(oXMLDocument.items, function (oItem) { + + let numberDate + if (oParameters.date == "creation") { + numberDate = oItem.creation_date * 1e3 + } else { + numberDate = oItem.last_activity_date * 1e3 + } + let date = new Date(numberDate) + let highlight + if (oItem.answer_count == 0) { + highlight = "Error" + } + if (oItem.answer_count > 0) { + highlight = "Warning" + } + if (oItem.accepted_answer_id != null) { + highlight = "Success" + } + + oItem.title = replaceAllSymbols(oItem.title) + oItem.owner.display_name = replaceAllSymbols(oItem.owner.display_name) + return { + title: oItem.title.trim(), + link: oItem.link, + pubDate: date, + owner: oItem.owner.display_name, + highlight: highlight + }; + }); + + + return aItems + }); + }; + + + DataFormatter.prototype._handleAction = function (oEvent) { + console.log("handler"); + var sActionType = oEvent.getParameter("type"), + mParams = oEvent.getParameter("parameters"); + + if (sActionType !== "Custom") { + return; + } + + switch (mParams.method) { + case "askQuestion": + this._askQuestion(); + break; + case "goToFeed": + this._goToFeed(); + break; + default: + Log.error("Method" + mParams.method + " not recognized"); + } + }; + + DataFormatter.prototype._askQuestion = function () { + var oCard = this.getCard(); + var params = oCard.getCombinedParameters(); + oCard.triggerAction({ + type: "Navigation", + parameters: { + "url": "https://stackoverflow.com/questions/ask?tags=" + params.tagged + } + }); + }; + + DataFormatter.prototype._goToFeed = function () { + var oCard = this.getCard(); + var params = oCard.getCombinedParameters(); + var tags = params.tagged.split(";").join(" "); + oCard.triggerAction({ + type: "Navigation", + parameters: { + "url": "https://stackoverflow.com/questions/tagged/" + tags + } + }); + }; + + return DataFormatter; + + +}); + + +function replaceAllSymbols(string){ + string = string.replaceAll('"','\"') + string = string.replaceAll(''','\'') + string = string.replaceAll('>','>') + string = string.replaceAll('<','<') + string = string.replaceAll('&','&') + let regexp = /&#\d\d\d;/g + var newString = string.replace(regexp, (match, $1) => { + return String.fromCharCode(match.substring(2,5)) + }); + return newString +} + diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/src/manifest.json b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/manifest.json new file mode 100644 index 0000000..70fc712 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/manifest.json @@ -0,0 +1,113 @@ +{ + "sap.app": { + "id": "sap.it.wz.cards.stackoverflow", + "type": "card", + "title": "Stackoverflow.com (External)", + "subTitle": "Stackoverflow.com (External)", + "applicationVersion": { + "version": "1.2.7" + }, + "shortTitle": "Stackoverflow.com (External)", + "info": "Stackoverflow.com (External)", + "description": "Shows a feed of questions from the public Stack Overflow community.", + "tags": { + "keywords": [ + "Stackoverflow.com (External)", + "SAP IT" + ] + } + }, + "sap.ui": { + "technology": "UI5", + "icons": { + "icon": "sap-icon://question-mark" + } + }, + "sap.platform.mobilecards": { + "_version": "1.0.0", + "compatible": false + }, + "sap.card": { + "type": "List", + "extension": "./ext/DataFormatter", + "designtime": "./dt/Configuration", + "header": { + "title": "Stackoverflow.com", + "subTitle": "Content from the public community", + "icon": { + "src": "sap-icon://question-mark" + }, + "visible" : true, + "actions": [ + { + "type": "Custom", + "parameters": { + "method": "goToFeed" + } + } + ] + }, + "configuration": { + "parameters": { + "url": { + "value": "https://api.stackexchange.com/2.3/search?site=stackoverflow" + }, + "tagged": { + "value": "sap-business-technology-platform" + }, + "sort": { + "value": "activity" + }, + "order": { + "value": "desc" + }, + "date":{ + "value" : "creation" + }, + "maxItems": { + "value": 5 + } + } + }, + "content": { + "data": { + "extension": { + "method": "getData" + } + }, + "item": { + "title": "{title}", + "description": "{owner}", + "info": { + "value": "{= format.dateTime(${pubDate}, {format: 'yyyyMMMdHHmm'}) }" + }, + "highlight": "{highlight}", + "actions": [ + { + "type": "Navigation", + "parameters": { + "url": "{link}" + } + } + ] + }, + "maxItems": "{{parameters.maxItems}}" + }, + "footer": { + "actionsStrip": [ + { + "buttonType": "Accept", + "text": "Ask question", + "actions": [ + { + "type": "Custom", + "parameters": { + "method": "askQuestion" + } + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/src/test-resources/manual/index.html b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/test-resources/manual/index.html new file mode 100644 index 0000000..7de4661 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-stackoverflow-card/src/test-resources/manual/index.html @@ -0,0 +1,73 @@ + + + + + + + sap.it.wz.cards.stack + + + + + + + +
+ + + +
+
+ +
+ + + + \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-stackoverflow-card/ui5.yaml b/advanced/wizard/sample-cards/wz-stackoverflow-card/ui5.yaml new file mode 100644 index 0000000..38c2595 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-stackoverflow-card/ui5.yaml @@ -0,0 +1,16 @@ +specVersion: "2.0" +metadata: + name: sap-it-wz-cards-stackoverflow + copyright: |- + SAP Work Zone + * (c) Copyright 2009-2024 SAP SE or an SAP affiliate company. +type: application +resources: + configuration: + paths: + webapp: src + propertiesFileSourceEncoding: UTF-8 +builder: + resources: + excludes: + - "test-resources/**" \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-twitter-card/package.json b/advanced/wizard/sample-cards/wz-twitter-card/package.json new file mode 100644 index 0000000..f4e66cf --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/package.json @@ -0,0 +1,18 @@ +{ + "name": "sap-it-wz-cards-twitter", + "version": "1.28.0", + "description": "", + "private": true, + "scripts": { + "start": "ui5 serve --o /test-resources/manual/index.html", + "eslint": "eslint src", + "build": "rimraf dist && ui5 build && zip sap-it-wz-cards-twitter.zip -r ./dist" + }, + "devDependencies": { + "@openui5/sap.ui.core": "1.77.2", + "@openui5/sap.ui.integration": "1.77.2", + "@ui5/cli": "2.2.3", + "eslint": "5.16.0", + "rimraf": "2.6.2" + } +} diff --git a/advanced/wizard/sample-cards/wz-twitter-card/sap-it-wz-cards-twitter.zip b/advanced/wizard/sample-cards/wz-twitter-card/sap-it-wz-cards-twitter.zip new file mode 100644 index 0000000..6044329 Binary files /dev/null and b/advanced/wizard/sample-cards/wz-twitter-card/sap-it-wz-cards-twitter.zip differ diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/Component.js b/advanced/wizard/sample-cards/wz-twitter-card/src/Component.js new file mode 100644 index 0000000..99885da --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/Component.js @@ -0,0 +1,23 @@ +/* + * ! ${copyright} + */ +sap.ui.define(["sap/ui/core/UIComponent"], function (UIComponent) { + "use strict"; + var ChatbotComponent = UIComponent.extend("sap.it.wz.cards.twitter.component.Component", { + onCardReady: function (oCard) { + // Holds the card for use inside the controller + this.card = oCard; + + // Can get all parameters with method getCombinedParameters + oCard.getCombinedParameters(); + + // Get any section of the card manifest with method getManifestEntry + oCard.getManifestEntry("/sap.card"); + + // When in context of a Host, like in Work Zone you can use the following methods + // oCard.getHostInstance(); + // oCard.resolveDestination("myDestination"); // check more in the destinations sample + } + }); + return ChatbotComponent; +}); diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/control/Frame.js b/advanced/wizard/sample-cards/wz-twitter-card/src/control/Frame.js new file mode 100644 index 0000000..ee64f16 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/control/Frame.js @@ -0,0 +1,350 @@ +/* + * ! ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/Control", + "sap/ui/core/Core", + "sap/m/MessageStrip" +], function ( + Control, + Core, + MessageStrip +) { + "use strict"; + + var oStaticArea = Core.getStaticAreaRef(); + + function getScrollTop() { + var B = document.body; + var D = document.documentElement; + D = (D.clientHeight) ? D : B; + return D.scrollTop; + } + + function getScrollLeft() { + var B = document.body; + var D = document.documentElement; + D = (D.clientWidth) ? D : B; + return D.scrollLeft; + } + + function getZIndex(e) { + var z = window.getComputedStyle(e).getPropertyValue('z-index'); + if (isNaN(z)) { + if (e.parentNode && e.parentNode.nodeType === 1) { + return getZIndex(e.parentNode); + } else { + return "auto"; + } + } else { + return z; + } + } + + //Registers an animation frame timer to check whether the position of oDomRef changed + //and calls the handler if it did + var VisibleRectObserver = function (oDomRef, fnHandler) { + if (!VisibleRectObserver._instance) { + VisibleRectObserver._instance = this; + this._elements = []; + this._sizes = []; + this._handlers = []; + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + } + + if (oDomRef && fnHandler) { + VisibleRectObserver._instance.register(oDomRef, fnHandler); + } + return VisibleRectObserver._instance; + }; + + //loops over the elements and checks for size and position changes + VisibleRectObserver.prototype.checkAll = function () { + for (var i = 0; i < this._elements.length; i++) { + this.check(i); + } + this._frame = window.requestAnimationFrame(this.checkAll.bind(this)); + }; + + //checks size and position changes for an element and calls the handler + VisibleRectObserver.prototype.check = function (i) { + var el = this._elements[i]; + var size = el.getBoundingClientRect(), + s = JSON.stringify(size); + if (this._sizes[i] !== s) { + this._sizes[i] = s; + this._handlers[i](el, size); + } + }; + + //registers a dom element and handler to be observed for size and position changes + VisibleRectObserver.prototype.register = function (oDomElement, fnHandler) { + if (this._elements.indexOf(oDomElement) > -1) { + return; + } + this._elements.push(oDomElement); + this._sizes.push(""); + this._handlers.push(fnHandler); + this.check(VisibleRectObserver._instance._sizes.length - 1); + }; + + //deregisters a dom element from observation + VisibleRectObserver.prototype.deregister = function (oDomElement) { + var iIndex = this._elements.indexOf(oDomElement); + if (iIndex === -1) { + return; + } + this._elements.splice(iIndex, 1); + this._sizes.splice(iIndex, 1); + this._handlers.splice(iIndex, 1); + }; + + + var Frame = Control.extend("sap.it.wz.cards.twitter.control.Frame", { + metadata: { + properties: { + src: { + type: "string" + }, + preview: { + type: "object", + defaultValue: null + } + } + }, + renderer: function (oRm, oControl) { + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.addStyle("box-sizing", "border-box"); + oRm.writeStyles(); + oRm.writeElementData(oControl); + oRm.openEnd(); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-before"); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.addStyle("min-width", "100%"); + oRm.addStyle("min-height", "100%"); + oRm.addStyle("padding", "1rem"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-content"); + oRm.writeStyles(); + oRm.openEnd(); + oRm.close("div"); + + oRm.openStart("div"); + oRm.writeAttribute("tabindex", "0"); + oRm.writeAttributeEscaped("id", oControl.getId() + "-after"); + oRm.openEnd(); + oRm.close("div"); + + oRm.close("div"); + + } + }); + + Frame.prototype.setSrc = function (vValue) { + if (vValue === this.getSrc()) { + return this; + } + //avoid re-rendering + this.setProperty("src", vValue, true); + + this._sRealSource = vValue; + + if (this._oFrameDomRef) { + this._oFrameDomRef.src = this._sRealSource; + } + return this; + }; + + Frame.prototype.init = function () { + this._oVisibleRectObserver = new VisibleRectObserver(); + }; + + Frame.prototype.onBeforeRendering = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + this._hideFrame(); + }; + + Frame.prototype.onAfterRendering = function () { + if (this._sRealSource && this._sRealSource.length < 5) { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + this._sRealSource = ""; + return this; + } + if (false && this._sRealSource.indexOf("http:") === 0) { + this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEHTTPERROR")); + this._sRealSource = ""; + return this; + } + if (this._sRealSource && this._sRealSource.indexOf("https://") !== 0) { + //this._sRealSource = "https://" + this._sRealSource; + } + if (this._sRealSource) { + this._iErrorTimer = window.setTimeout(this._handleError.bind(this), 1000 * 20); + if (!this._oFrameDomRef) { + this._initFrame(); + } + } else { + this._showMessage("Information", this.getModel("i18n").getProperty("FRAMECONFIGUREURL")); + } + }; + + Frame.prototype.exit = function () { + this._oVisibleRectObserver.deregister(this.getDomRef()); + return this; + }; + + Frame.prototype.destroy = function () { + if (this._oFrameDomRef) { + this._oFrameDomRef.parentNode.removeChild(this._oFrameDomRef); + this._oFrameDomRef.src = ""; + } + if (this._oFrameBlockerDomRef) { + this._oFrameBlockerDomRef.parentNode.removeChild(this._oFrameBlockerDomRef); + this._oFrameBlockerDomRef.src = ""; + } + return Control.prototype.destroy.apply(this, arguments); + }; + + Frame.prototype._hideFrame = function () { + //hide the frame until it is loaded + if (!this._oFrameDomRef) { + return; + } + this._oFrameDomRef.style.top = "-10000px"; + this._oFrameDomRef.style.left = "50px"; + }; + + Frame.prototype._initFrame = function () { + var oFrame = document.getElementById("id", this.getId() + "-frame"); + if (oFrame) { + this._oFrameDomRef = oFrame; + return; + } + var iTab = this.getPreview() ? -1 : 0; + this._oFrameDomRef = this._createFrame(this.getId() + "-frame", this._sRealSource, iTab); + oStaticArea.insertBefore(this._oFrameDomRef, oStaticArea.firstChild); + if (this.getPreview()) { + this._oFrameBlockerDomRef = this._createFrame(this.getId() + "-frameblocker", "", iTab); + oStaticArea.insertBefore(this._oFrameBlockerDomRef, oStaticArea.firstChild); + } + }; + + Frame.prototype._createFrame = function (sId, sSource, iTab) { + var oLocalRM = Core.getRenderManager(); + oLocalRM.openStart("iframe"); + oLocalRM.addStyle("position", "absolute"); + oLocalRM.addStyle("border", "none"); + oLocalRM.addStyle("top", "-10000px"); + oLocalRM.addStyle("left", "20px"); + oLocalRM.addStyle("margin", "1px"); + oLocalRM.writeStyles(); + oLocalRM.writeAttribute("tabIndex", "" + iTab); + oLocalRM.writeAttributeEscaped("id", sId); + oLocalRM.writeAttributeEscaped("scrolling", "auto"); + if (sSource) { + oLocalRM.writeAttributeEscaped("src", sSource); + } + oLocalRM.openEnd(); + oLocalRM.close("iframe"); + var div = document.createElement("div"); + oLocalRM.flush(div); + var oFrame = div.firstChild; + oFrame.addEventListener("load", this._handleLoad.bind(this)); + return oFrame; + }; + + Frame.prototype._handleLoad = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + this._oVisibleRectObserver.register(this.getDomRef(), this._syncFramePosition.bind(this)); + }; + + Frame.prototype._handleError = function () { + if (this._iErrorTimer) { + clearTimeout(this._iErrorTimer); + } + //this._showMessage("Error", this.getModel("i18n").getProperty("FRAMEERROR15SEC")); + }; + + Frame.prototype._applyFramePosition = function (oFrame, oElement, oRect) { + if (!oFrame) { + return; + } + if (oRect.height === 0 || oRect.width === 0) { + this._hideFrame(); + return; + } + var iZIndex = getZIndex(oElement); + oFrame.style.zIndex = iZIndex === "auto" ? 2 : iZIndex; + oFrame.style.left = (oRect.left + getScrollLeft()) + "px"; + oFrame.style.top = (oRect.top + getScrollTop()) + "px"; + + if (this.getPreview()) { + var oPreviewInfo = this.getPreview().getTransformContentInfo(); + oFrame.style.width = ((oRect.width - 2) / oPreviewInfo.transformFactor) + "px"; + oFrame.style.height = ((oRect.height - 2) / oPreviewInfo.transformFactor) + "px" + oFrame.style.transform = oPreviewInfo.transformStyle; + oFrame.style.transformOrigin = oPreviewInfo.transformOriginStyle; + oFrame.style.zIndex = oPreviewInfo.zIndex; + } else { + oFrame.style.width = (oRect.width - 2) + "px"; + oFrame.style.height = (oRect.height - 2) + "px"; + } + }; + + Frame.prototype._syncFramePosition = function (oElement, oRect) { + this._applyFramePosition(this._oFrameDomRef, oElement, oRect); + this._applyFramePosition(this._oFrameBlockerDomRef, oElement, oRect); + }; + + Frame.prototype._showMessage = function (sType, sText) { + if (this._oMessage) { + this._oMessage.destroy(); + } + this._oMessage = new MessageStrip(this.getId() + "-message", { + text: sText, + type: sType, + showIcon: true + }); + var oDomRef = this.getDomRef(); + if (oDomRef) { + this._oMessage.placeAt(oDomRef); + } + }; + function focusAfter() { + this.getDomRef("after").focus(); + window.removeEventListener("focus", focusAfter); + } + Frame.prototype.onsaptabnext = function (oEvent) { + if (oEvent.target === this.getDomRef("before")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + + } + } + }; + + Frame.prototype.onsaptabprevious = function (oEvent) { + if (oEvent.target === this.getDomRef("after")) { + if (this._oFrameDomRef && !this.getPreview()) { + setTimeout(function () { + this._oFrameDomRef.contentWindow.focus(); + }.bind(this), 20); + } + } + }; + return Frame; + +}); diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/controller/Card.controller.js b/advanced/wizard/sample-cards/wz-twitter-card/src/controller/Card.controller.js new file mode 100644 index 0000000..c24a83e --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/controller/Card.controller.js @@ -0,0 +1,127 @@ +/* + * ! ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/mvc/Controller" +], function (Controller) { + "use strict"; + function isDark(rgbcolor) { + rgbcolor = rgbcolor || window.getComputedStyle(document.body).backgroundColor; + var match = /rgb\((\d+).*?(\d+).*?(\d+)\)/.exec(rgbcolor); + if (!match) { + return false; + } + var r = parseInt(match[1]), + g = parseInt(match[2]), + b = parseInt(match[3]), + yiq = (r * 299 + g * 587 + b * 114) / 1000; + return (yiq <= 128); + } + + return Controller.extend("sap.it.wz.cards.twitter.controller.Card", { + onInit: function () { + if (!this.getOwnerComponent().card) { + return; + } + let oCard = this.getOwnerComponent().card; + let mParameters = oCard.getCombinedParameters(); + + + let content = ""; + + let [target, options] = this._getTimelimeParams(mParameters); + switch (mParameters.widgetType) { + case "tweet": + content = this._getTweetScript(mParameters.tweetId, target, options); + break; + default: + content = this._getTimelineScript(target, options); + } + + var src = URL.createObjectURL(new Blob([content], { type: "text/html" })); + var oFrame = this.byId("frame"); + oFrame.setSrc(src); + + if (oCard.editor) { + oFrame.setPreview(oCard.editor.preview); + } + + var iPixelHeight = Math.max(mParameters.height, oCard.getCardContent().getDomRef().offsetHeight); + this.getView().setHeight(iPixelHeight + "px"); + }, + _getTimelineScript: function (target, options = {}) { + let sTarget = JSON.stringify(target); + let sOptions = JSON.stringify(options); + let timelineScript = `twttr.widgets.createTimeline(${sTarget}, element, ${sOptions});` + return this._getIframeHtml(timelineScript); + }, + _getTweetScript: function (id, target, options) { + let sTarget = JSON.stringify(target); + let sOptions = JSON.stringify(options); + let tweetScript = `twttr.widgets.createTweet("${id}", element, ${sOptions});`; + return this._getIframeHtml(tweetScript); + }, + _getIframeHtml: function (sScript) { + let elementId = "widget_container"; + return ` + + + + + + + +
+ + + `; + }, + _getTimelimeParams: function (mParameters) { + let params = {}; + params.sourceType = mParameters.widgetType || "profile"; + let username = mParameters.userName.replace("@", ""); + switch (params.sourceType) { + case "list": + params.ownerScreenName = username; + params.slug = mParameters.listName; + break; + case "collection": + params.id = mParameters.collectionId; + break; + default: + // profile & likes + params.screenName = username; + } + + let options = { dnt: true, ariaPolite: "polite" }; + options.theme = mParameters.theme; + if (mParameters.theme === "auto") { + options.theme = isDark() ? "dark" : "light"; + } + if (mParameters.setTweetsLimit) { + options.tweetLimit = mParameters.numberOfTweets; + } + + let chrome = []; + if (!mParameters.header) chrome.push("noheader"); + if (!mParameters.footer) chrome.push("nofooter"); + options.chrome = chrome.join(","); + + return [params, options]; + } + }); +}); diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/dt/configuration.js b/advanced/wizard/sample-cards/wz-twitter-card/src/dt/configuration.js new file mode 100644 index 0000000..6441bd5 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/dt/configuration.js @@ -0,0 +1,192 @@ +sap.ui.define(["sap/ui/integration/Designtime" +], function (Designtime) { + "use strict"; + + var Configuration = Designtime.extend("sap.workzone.cpkg.card.sample.Configuration"); + Configuration.prototype.create = function () { + return { + form: { + items: { + "headerGroup": { + "label": "Header options", + "type": "group", + "hint": "In case of troubles please visit SAP Work Zone Help Center" + }, + "headerVisibility": { + "manifestpath": "/sap.card/header/visible", + "type": "boolean", + "label": "Visible Header", + "defaultValue" : true + }, + "title": { + "manifestpath": "/sap.card/header/title", + "type": "string", + "defaultValue": "Chatbot", + "label": "Title", + "visible": "{items>headerVisibility/value}" + }, + "subTitle": { + "manifestpath": "/sap.card/header/subTitle", + "type": "string", + "defaultValue": "", + "label": "Subtitle", + "visible": "{items>headerVisibility/value}" + }, + "headericon": { + "manifestpath": "/sap.card/header/icon/src", + "type": "string", + "label": "Card Icon", + "allowDynamicValues": false, + "allowSettings": false, + "visualization": { + "type": "IconSelect", + "settings": { + "value": "{currentSettings>value}", + "editable": "{currentSettings>editable}" + } + }, + "visible": "{items>headerVisibility/value}" + }, + "bodyGroup": { + "label": "Body options", + "type": "group" + }, + "widgetType": { + "manifestpath": "/sap.card/configuration/parameters/widgetType/value", + "values": { + "data": { + "json": [ + { "key": "profile", "text": "User Timeline" }, + { "key": "list", "text": "List Timeline" }, + { "key": "tweet", "text": "Embedded Tweet" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + }, + "defaultValue": "", + "label": "Select Twitter Type", + "type": "string" + }, + "userName": { + "manifestpath": "/sap.card/configuration/parameters/userName/value", + "type": "string", + "defaultValue": "", + "placeholder": "e.g. @twitter", + "label": "Twitter Username (e.g @twitter)", + "visible": "{= ${items>widgetType/value} !== 'tweet' && ${items>widgetType/value} !== 'moment' && ${items>widgetType/value} !== 'collection'}" + }, + "listName": { + "manifestpath": "/sap.card/configuration/parameters/listName/value", + "type": "string", + "defaultValue": "", + "label": "List Name", + "visible": "{= ${items>widgetType/value} === 'list'}" + }, + "tweetId": { + "manifestpath": "/sap.card/configuration/parameters/tweetId/value", + "type": "string", + "defaultValue": "", + "label": "Tweet ID", + "visible": "{= ${items>widgetType/value} === 'tweet'}" + }, + "collectionId": { + "manifestpath": "/sap.card/configuration/parameters/collectionId/value", + "type": "string", + "defaultValue": "", + "label": "Collection ID", + "visible": "{= ${items>widgetType/value} === 'collection'}" + }, + "theme": { + "manifestpath": "/sap.card/configuration/parameters/theme/value", + "values": { + "data": { + "json": [ + { "key": "light", "text": "Light" }, + { "key": "dark", "text": "Dark" }, + { "key": "auto", "text": "Automatic" } + ] + }, + "item": { + "text": "{text}", + "key": "{key}" + } + + }, + "defaultValue": "", + "label": "Color Theme", + "type": "string" + }, + "header": { + "manifestpath": "/sap.card/configuration/parameters/header/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Header", + "visible": "{= ${items>widgetType/value} !== 'tweet'}" + }, + "footer": { + "manifestpath": "/sap.card/configuration/parameters/footer/value", + "type": "boolean", + "defaultValue": false, + "label": "Show Footer", + "visible": "{= ${items>widgetType/value} !== 'tweet'}" + }, + "setTweetsLimit": { + "manifestpath": "/sap.card/configuration/parameters/setTweetsLimit/value", + "type": "boolean", + "defaultValue": false, + "label": "Limit Number of Tweets", + "visible": "{= ${items>widgetType/value} !== 'tweet' && ${items>widgetType/value} !== 'list'}" + }, + "numberOfTweets": { + "manifestpath": "/sap.card/configuration/parameters/numberOfTweets/value", + "type": "integer", + "defaultValue": 20, + "label": "Number of Feeds", + "visible": "{= ${items>setTweetsLimit/value}}", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 1, + "max": 20, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + }, + "height": { + "manifestpath": "/sap.card/configuration/parameters/height/value", + "type": "integer", + "defaultValue": 570, + "label": "Height in pixels", + "visualization": { + "type": "sap/m/Slider", + "settings": { + "value": "{currentSettings>value}", + "min": 30, + "max": 600, + "width": "80%", + "showAdvancedTooltip": true, + "showHandleTooltip": false, + "inputsAsTooltips": true, + "enabled": "{currentSettings>editable}" + } + } + } + } + }, + preview: { + modes: "Live" + } + }; + }; + return Configuration; +}); + + diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/manifest.json b/advanced/wizard/sample-cards/wz-twitter-card/src/manifest.json new file mode 100644 index 0000000..f9ee4dc --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/manifest.json @@ -0,0 +1,108 @@ +{ + "sap.app": { + "id": "sap.it.wz.cards.twitter", + "type": "card", + "title": "Twitter Feed", + "subTitle": "Twitter Feed", + "applicationVersion": { + "version": "1.1.10" + }, + "shortTitle": "Twitter Feed", + "info": "Twitter Feed", + "description": "Select different types of Twitter timelines to be shown.", + "tags": { + "keywords": [ + "Twitter", + "SAP IT" + ] + } + }, + "sap.ui": { + "technology": "UI5", + "icons": { + "icon": "sap-icon://feed" + } + }, + "sap.ui5": { + "dependencies": { + "minUI5Version": "1.77.2", + "libs": { + "sap.ui.core": {}, + "sap.m": {} + } + }, + "rootView": { + "viewName": "sap.it.wz.cards.twitter.view.Card", + "type": "XML", + "async": true, + "id": "app" + }, + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "sap.it.wz.cards.twitter.i18n.i18n" + } + } + } + }, + "sap.platform.mobilecards": { + "_version": "1.0.0", + "compatible": false + }, + "sap.card": { + "type": "Component", + "designtime": "dt/configuration", + "header": { + "title": "Twitter", + "subTitle": "by @SAP", + "icon": { + "src": "sap-icon://newspaper" + }, + "visible": true + }, + "configuration": { + "parameters": { + "widgetType": { + "value": "profile" + }, + "showCardHeader": { + "value": true + }, + "userName": { + "value": "@sap" + }, + "listName": { + "value": "sap-on-twitter" + }, + "collectionId": { + "value": "576828964162965504" + }, + "momentId": { + "value": "788796479838138369" + }, + "tweetId": { + "value": "1328041466707456001" + }, + "theme": { + "value": "auto" + }, + "header": { + "value": false + }, + "footer": { + "value": false + }, + "setTweetsLimit": { + "value": false + }, + "numberOfTweets": { + "value": 20 + }, + "height": { + "value": 500 + } + } + } + } +} \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/test-resources/manual/index.html b/advanced/wizard/sample-cards/wz-twitter-card/src/test-resources/manual/index.html new file mode 100644 index 0000000..72c56ae --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/test-resources/manual/index.html @@ -0,0 +1,73 @@ + + + + + + + sap.it.wz.cards.twitter + + + + + + + +
+ + + +
+
+ +
+ + + + \ No newline at end of file diff --git a/advanced/wizard/sample-cards/wz-twitter-card/src/view/Card.view.xml b/advanced/wizard/sample-cards/wz-twitter-card/src/view/Card.view.xml new file mode 100644 index 0000000..87c5db0 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/src/view/Card.view.xml @@ -0,0 +1,6 @@ + + + diff --git a/advanced/wizard/sample-cards/wz-twitter-card/ui5.yaml b/advanced/wizard/sample-cards/wz-twitter-card/ui5.yaml new file mode 100644 index 0000000..ed690d2 --- /dev/null +++ b/advanced/wizard/sample-cards/wz-twitter-card/ui5.yaml @@ -0,0 +1,16 @@ +specVersion: "2.0" +metadata: + name: sap-it-wz-cards-twitter + copyright: |- + SAP Work Zone + * (c) Copyright 2009-2024 SAP SE or an SAP affiliate company. +type: application +resources: + configuration: + paths: + webapp: src + propertiesFileSourceEncoding: UTF-8 +builder: + resources: + excludes: + - "test-resources/**" \ No newline at end of file