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.frontDescription}
+
+
+
${params.frontCaption}
+
+
+
+
+
+
${params.backDescription}
+
+
+
${params.backCaption}
+
+
+
`;
+
+ if (params.url && params.url.length > 0) {
+ innerHtml = `${innerHtml}`;
+ }
+
+ return `
+
+
+
+
+
+
+
+ `;
+ },
+ _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