diff --git a/src/hos_core_types/schema/core/types/color/command.json b/src/hos_core_types/schema/core/types/color/command.json index d8421161..88406502 100644 --- a/src/hos_core_types/schema/core/types/color/command.json +++ b/src/hos_core_types/schema/core/types/color/command.json @@ -25,5 +25,5 @@ } }, "additionalProperties": false, - "required": [ "type", "colormode", "set" ] + "required": [ "colormode", "set" ] } \ No newline at end of file diff --git a/src/hos_cosgi_sitemap/examples/test01.json b/src/hos_cosgi_sitemap/examples/test01.json index c0ee7f29..dabd8869 100644 --- a/src/hos_cosgi_sitemap/examples/test01.json +++ b/src/hos_cosgi_sitemap/examples/test01.json @@ -31,17 +31,13 @@ "id": "dummySwitch0", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } - }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%}}" }, { "type": "sitemap/sitemap_template#/definitions/text_element", "label": "Slider0", "icon" : "some_icon01", "format" : "Value: %1%", + "linkedPage" : "page02", "device": { "id": "dummyDimmer0", "pointer": "/dimmer/value" @@ -50,6 +46,7 @@ "type": "sitemap/sitemap_template#/definitions/slider_element", "label": "Slider0", "icon" : "some_icon03", + "linkedPage" : "page02", "device": { "id": "dummyDimmer0", "pointer": "/dimmer/value" @@ -57,12 +54,16 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "dimmer": { - "set": null - } - }, - "commandValuePointer": "/dimmer/set" + "commandTemplate": "{\"dimmer\": {\"set\": %1%}}" + }, { + "type": "sitemap/sitemap_template#/definitions/colorpicker_element", + "label": "color0", + "icon" : "some_icon01", + "linkedPage" : "page02", + "device": { + "id": "dummyDimmer0", + "pointer": "/dimmer/value" + } } ] }, @@ -88,12 +89,7 @@ "id": "dummySwitch1", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } - }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%}}" }, { "type": "sitemap/sitemap_template#/definitions/text_element", "label": "Slider1", @@ -114,12 +110,7 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "dimmer": { - "set": null - } - }, - "commandValuePointer": "/dimmer/set" + "commandTemplate": "{\"dimmer\": {\"set\": %1%}}" } ] }, @@ -145,12 +136,7 @@ "id": "dummySwitch2", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } - }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%}}" }, { "type": "sitemap/sitemap_template#/definitions/text_element", "label": "Slider2", @@ -171,12 +157,7 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "dimmer": { - "set": null - } - }, - "commandValuePointer": "/dimmer/set" + "commandTemplate": "{\"dimmer\": {\"set\": %1%}}" } ] }, @@ -202,12 +183,16 @@ "id": "dummySwitch3", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } + "commandTemplate": "{\"switch\": {\"set\": %1%}}" + }, { + "type": "sitemap/sitemap_template#/definitions/switch_element", + "label": "Switch3 fast", + "icon" : "some_icon02", + "device": { + "id": "dummySwitch3", + "pointer": "/switch/value" }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"dimmer\": {\"set\": %1%},\"advproperties\": {\"transitiontime\": 1}}" }, { "type": "sitemap/sitemap_template#/definitions/text_element", "label": "Slider3", @@ -228,12 +213,7 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "dimmer": { - "set": null - } - }, - "commandValuePointer": "/dimmer/set" + "commandTemplate": "{\"dimmer\": {\"set\": %1%}}" } ] } diff --git a/src/hos_cosgi_sitemap/examples/test02.json b/src/hos_cosgi_sitemap/examples/test02.json index f6fa14a4..6ec83d05 100644 --- a/src/hos_cosgi_sitemap/examples/test02.json +++ b/src/hos_cosgi_sitemap/examples/test02.json @@ -20,29 +20,30 @@ "id": "huelight1", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } - }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%}}" }, { "type": "sitemap/sitemap_template#/definitions/slider_element", "label": "Lightstrips 1 Slider", "icon" : "some_icon03", - "device": { + "device": { "id": "huelight1", "pointer": "/brightness/value" }, "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "brightness": { - "set": null - } + "commandTemplate": "{\"brightness\": {\"set\": %1%}}" + }, { + "type": "sitemap/sitemap_template#/definitions/colorpicker_element", + "label": "color0", + "icon" : "some_icon01", + "linkedPage" : "page02", + "colormode" : "hsv", + "device": { + "id": "huelight1", + "pointer": ["/color/value[0]", "/color/value[1]", "/brightness/value"] }, - "commandValuePointer": "/brightness/set" + "commandTemplate": "{\"color\": {\"set\": [%1%, %2%], \"colormode\": \"hs\"}, \"brightness\": {\"set\": %3%}}" } ] }, { @@ -58,12 +59,7 @@ "id": "huelight2", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } - }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%}}" }, { "type": "sitemap/sitemap_template#/definitions/slider_element", "label": "Lightstrips 2 Slider", @@ -75,12 +71,7 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "brightness": { - "set": null - } - }, - "commandValuePointer": "/brightness/set" + "commandTemplate": "{\"brightness\": {\"set\": %1%}}" } ] }, { @@ -96,12 +87,16 @@ "id": "huelight3", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } + "commandTemplate": "{\"switch\": {\"set\": %1%}}" + }, { + "type": "sitemap/sitemap_template#/definitions/switch_element", + "label": "ZimmerLampe Switch fast", + "icon" : "some_icon02", + "device": { + "id": "huelight3", + "pointer": "/switch/value" }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%},\"brightness\": {\"set\": 1}, \"advproperties\": {\"transitiontime\": 0}}" }, { "type": "sitemap/sitemap_template#/definitions/slider_element", "label": "ZimmerLampe Slider", @@ -113,12 +108,7 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "brightness": { - "set": null - } - }, - "commandValuePointer": "/brightness/set" + "commandTemplate": "{\"brightness\": {\"set\": %1%}}" } ] }, { @@ -134,12 +124,7 @@ "id": "huelight4", "pointer": "/switch/value" }, - "commandTemplate": { - "switch": { - "set": null - } - }, - "commandValuePointer": "/switch/set" + "commandTemplate": "{\"switch\": {\"set\": %1%}}" }, { "type": "sitemap/sitemap_template#/definitions/slider_element", "label": "TischLampe Slider", @@ -151,12 +136,7 @@ "min": 0, "max": 1, "step": 0.1, - "commandTemplate": { - "brightness": { - "set": null - } - }, - "commandValuePointer": "/brightness/set" + "commandTemplate": "{\"brightness\": {\"set\": %1%}}" } ] } diff --git a/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h index 13210af7..df0fb007 100644 --- a/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h +++ b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h @@ -119,7 +119,8 @@ enum class ElementType { // atomic elements Text, Switch, - Slider + Slider, + ColorPicker }; class Element @@ -169,7 +170,7 @@ public: virtual std::weak_ptr getParent() noexcept = 0; virtual const std::string& getDeviceID() noexcept = 0; virtual std::weak_ptr getDevice() noexcept = 0; - virtual const std::string& getPointer() noexcept = 0; + virtual const libvariant::Variant& getPointer() noexcept = 0; virtual bool deviceExists() noexcept = 0; virtual void sendCommand(const libvariant::Variant& cmd) = 0; }; diff --git a/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json b/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json index 570fe90f..daebbd64 100644 --- a/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json +++ b/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json @@ -69,7 +69,8 @@ "anyOf": [ { "$ref": "#/definitions/text_element" }, { "$ref": "#/definitions/slider_element" }, - { "$ref": "#/definitions/switch_element" } + { "$ref": "#/definitions/switch_element" }, + { "$ref": "#/definitions/colorpicker_element" } ] }, @@ -177,6 +178,20 @@ ], "required": ["type"] }, + "colorpicker_element": { + "allOf": [ + { "$ref": "#/definitions/atomic_element_base" }, + { + "properties": { + "type": { + "type": "string", + "pattern": "sitemap/sitemap_template#/definitions/colorpicker_element" + } + } + } + ], + "required": ["type"] + }, "device": { "type": "object", @@ -185,7 +200,15 @@ "type": "string" }, "pointer": { - "type": "string" + "anyOf": [ + { "type": "string" }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] } }, "required": ["id"] diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp index 1805c47d..a819c693 100644 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp @@ -23,7 +23,8 @@ _elementTypeInfo elementTypeInfo[] = { { "sitemap/sitemap_template#/definitions/frame_element", "sitemap/sitemap#/definitions/frame_element", ElementType::Frame, true }, { "sitemap/sitemap_template#/definitions/text_element", "sitemap/sitemap#/definitions/text_element", ElementType::Text, false }, { "sitemap/sitemap_template#/definitions/slider_element", "sitemap/sitemap#/definitions/slider_element", ElementType::Slider, false }, - { "sitemap/sitemap_template#/definitions/switch_element", "sitemap/sitemap#/definitions/switch_element", ElementType::Switch, false } + { "sitemap/sitemap_template#/definitions/switch_element", "sitemap/sitemap#/definitions/switch_element", ElementType::Switch, false }, + { "sitemap/sitemap_template#/definitions/colorpicker_element", "sitemap/sitemap#/definitions/colorpicker_element", ElementType::ColorPicker, false } }; } @@ -85,22 +86,19 @@ std::weak_ptr SitemapTemplateImpl::getPageElement(size_t& uid) noexcept return std::weak_ptr(); } -std::shared_ptr SitemapTemplateImpl::createDevice(const libvariant::Variant& param, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer) { +std::shared_ptr SitemapTemplateImpl::createDevice(const libvariant::Variant& param, const std::string& commandTemplate) { auto idRaw = param["id"]; if (!idRaw.IsString()) { throw std::runtime_error("id is not a string."); } std::string id = idRaw.AsString(); - std::string pointer; - auto pointerRaw = param["pointer"]; - if (!pointerRaw.IsString()) { - throw std::runtime_error("pointer is not a string."); - } else if (pointerRaw.IsString()) { - pointer = pointerRaw.AsString(); + auto pointer = param["pointer"]; + if (!pointer.IsString() && !pointer.IsList()) { + throw std::runtime_error("pointer is not a string or an array."); } auto devRepo = parent.getDeviceRepository(); auto device = devRepo->getDevice(id); - std::shared_ptr newDevice = std::make_shared(id, device, pointer, commandTemplate, commandValuePointer); + std::shared_ptr newDevice = std::make_shared(id, device, pointer, commandTemplate); devices.insert({id, newDevice}); return newDevice; } @@ -180,17 +178,12 @@ std::shared_ptr SitemapTemplateImpl::createElement(PageImpl& page, if (!deviceRaw.IsMap()) { throw std::runtime_error("device is not a map."); } else { - libvariant::Variant commandTemplate; - std::string commandValuePointer; - if (param.Contains("commandTemplate")) { - commandTemplate = param["commandTemplate"]; + std::string commandTemplate; + if (param.Contains("commandTemplate") && param["commandTemplate"].IsString()) { + commandTemplate = param["commandTemplate"].AsString(); addParams.Erase("commandTemplate"); } - if (param.Contains("commandValuePointer") && param["commandValuePointer"].IsString()) { - commandValuePointer = param["commandValuePointer"].AsString(); - addParams.Erase("commandValuePointer"); - } - device = createDevice(deviceRaw, commandTemplate, commandValuePointer); + device = createDevice(deviceRaw, commandTemplate); addParams.Erase("device"); } } @@ -214,6 +207,9 @@ std::shared_ptr SitemapTemplateImpl::createElement(PageImpl& page, case ElementType::Switch: newAElement = std::make_shared(page, info->typeString, label, icon, format, device, addParams, parent); break; + case ElementType::ColorPicker: + newAElement = std::make_shared(page, info->typeString, label, icon, format, device, addParams, parent); + break; default: throw std::runtime_error((boost::format("Registered element type %1% is unknown.") % info->typeName).str()); } @@ -387,9 +383,25 @@ libvariant::Variant AtomicElementImpl::_getDeviceValue() { libvariant::Variant devState; if (device && device->deviceExists()) { try { - devState = device->getDevice().lock()->getCurrentState(); - if (!device->getPointer().empty()) { - devState = devState.GetPath(device->getPointer()); + auto devStateRaw = device->getDevice().lock()->getCurrentState(); + auto& pointer = device->getPointer(); + if (pointer.IsString()) { + auto str = pointer.AsString(); + if (!str.empty()) { + devState = devStateRaw.GetPath(str); + } else { + devState = devStateRaw; + } + } else { + devState = libvariant::Variant::List(); + for (auto p : pointer.AsList()) { + auto str = p.AsString(); + if (!str.empty()) { + devState.Append(devStateRaw.GetPath(str)); + } else { + devState.Append(devStateRaw); + } + } } } catch (...) { devState = "NaN"; @@ -407,42 +419,6 @@ libvariant::Variant AtomicElementImpl::_getDeviceValue() { return devState; } -libvariant::Variant SliderElementImpl::_getDeviceValue() { - libvariant::Variant devState; - if (device->deviceExists()) { - try { - devState = device->getDevice().lock()->getCurrentState(); - if (!device->getPointer().empty()) { - devState = devState.GetPath(device->getPointer()); - } - devState = devState.AsDouble(); - } catch (...) { - devState = "NaN"; - } - } else { - devState = "NaN"; - } - return devState; -} - -libvariant::Variant SwitchElementImpl::_getDeviceValue() { - libvariant::Variant devState; - if (device->deviceExists()) { - try { - devState = device->getDevice().lock()->getCurrentState(); - if (!device->getPointer().empty()) { - devState = devState.GetPath(device->getPointer()); - } - devState = devState.AsBool(); - } catch (...) { - devState = "NaN"; - } - } else { - devState = "NaN"; - } - return devState; -} - void DeviceImpl::resolveDevice() noexcept { if (!parent.expired()) { auto devRepo = parent.lock()->getPage()->getSiteMap()->getParent()->getDeviceRepository(); @@ -451,10 +427,27 @@ void DeviceImpl::resolveDevice() noexcept { } void DeviceImpl::sendCommand(const libvariant::Variant& cmd) { - if (!device.expired() && commandTemplate.IsMap() && !commandValuePointer.empty()) { + if (!device.expired() && !commandTemplate.empty()) { + static void (*_handleArgs)(boost::format& ,const libvariant::Variant&) + = [](boost::format& format ,const libvariant::Variant& arg){ + if (arg.IsList()) { + for (auto e : arg.AsList()) { + _handleArgs(format, e); + } + } else if (arg.IsString()) { + format % arg.AsString(); + } else if (arg.IsFloat()) { + format % arg.AsDouble(); + } else if (arg.IsInt()) { + format % arg.AsInt(); + } else if (arg.IsBool()) { + format % (arg.AsBool() ? "true" : "false"); + } + }; std::cout << "DeviceImpl::sendCommand: " << libvariant::SerializeJSON(cmd) << std::endl; - auto msg = commandTemplate.Copy(); - msg.SetPath(commandValuePointer, cmd); + auto formatobj = boost::format(commandTemplate); + _handleArgs(formatobj, cmd); + auto msg = libvariant::DeserializeYAML(formatobj.str()); device.lock()->sendCommand(msg); } } diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h index b65f887e..e9df8d70 100644 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h @@ -71,7 +71,7 @@ public: std::shared_ptr addPage(const std::string& name, const libvariant::Variant& page); bool setRootPageName(const std::string& name) noexcept; - std::shared_ptr createDevice(const libvariant::Variant& param, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer); + std::shared_ptr createDevice(const libvariant::Variant& param, const std::string& commandTemplate); std::shared_ptr createElement(PageImpl& page, const libvariant::Variant& param, CompositeElementImpl* parent); virtual SitemapService* getParent() noexcept override { return dynamic_cast(&parent); } @@ -227,8 +227,6 @@ public: class SliderElementImpl : public AtomicElementImpl { -private: - virtual libvariant::Variant _getDeviceValue() override; public: SliderElementImpl(PageImpl& page, std::string typeStr, const std::string& label, const std::string& icon, const std::string& format, std::shared_ptr device, libvariant::Variant additionalParams, CompositeElementImpl* parent = nullptr) @@ -237,8 +235,6 @@ public: class SwitchElementImpl : public AtomicElementImpl { -private: - virtual libvariant::Variant _getDeviceValue() override; public: SwitchElementImpl(PageImpl& page, std::string typeStr, const std::string& label, const std::string& icon, const std::string& format, std::shared_ptr device, libvariant::Variant additionalParams, CompositeElementImpl* parent = nullptr) @@ -246,6 +242,14 @@ public: }; +class ColorPickerElementImpl : public AtomicElementImpl { +public: + ColorPickerElementImpl(PageImpl& page, std::string typeStr, const std::string& label, const std::string& icon, const std::string& format, + std::shared_ptr device, libvariant::Variant additionalParams, CompositeElementImpl* parent = nullptr) + : AtomicElementImpl(page, ElementType::ColorPicker, typeStr, label, icon, format, device, additionalParams, parent) {} +}; + + class DeviceImpl : public virtual Device, @@ -253,14 +257,13 @@ class DeviceImpl private: std::string deviceID; std::weak_ptr device; - std::string pointer; + libvariant::Variant pointer; std::weak_ptr parent; - libvariant::Variant commandTemplate; - std::string commandValuePointer; + std::string commandTemplate; public: - DeviceImpl(const std::string& deviceID, std::weak_ptr device, const std::string& pointer, const libvariant::Variant& commandTemplate, const std::string& commandValuePointer) - : deviceID(deviceID), device(device), pointer(pointer), commandTemplate(commandTemplate), commandValuePointer(commandValuePointer) {} + DeviceImpl(const std::string& deviceID, std::weak_ptr device, const libvariant::Variant& pointer, const std::string& commandTemplate) + : deviceID(deviceID), device(device), pointer(pointer), commandTemplate(commandTemplate) {} virtual std::weak_ptr getParent() noexcept override { return parent; } void setParent(std::weak_ptr parent) noexcept { this->parent = parent; } @@ -269,7 +272,7 @@ public: virtual const std::string& getDeviceID() noexcept override { return deviceID; } virtual std::weak_ptr getDevice() noexcept override { return device; } - virtual const std::string& getPointer() noexcept override { return pointer; } + virtual const libvariant::Variant& getPointer() noexcept override { return pointer; } virtual bool deviceExists() noexcept override { return !device.expired(); } virtual void sendCommand(const libvariant::Variant& cmd) override; }; diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Page.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Page.js index 40343d2a..0484c2bf 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Page.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Page.js @@ -1,12 +1,17 @@ define([ "dojo/_base/config", 'dojo/_base/declare', + 'dojo/_base/lang', "dojo/Deferred", "dojo/dom", "dojo/dom-construct", + "dojo/dom-style", "dijit/layout/ContentPane", - "hos/sitemap/PageElementFactory" -], function(config, declare, Deferred, dom, domConstruct, ContentPane, PageElementFactory) { + "hos/sitemap/PageElementFactory", + "dojox/mobile/View", + "dojox/mobile/Pane", + "dojox/mobile/EdgeToEdgeList" +], function(config, declare, lang, Deferred, dom, domConstruct, domStyle, ContentPane, PageElementFactory, View, Pane, EdgeToEdgeList) { /* * Class representing a page. @@ -35,30 +40,19 @@ define([ }); }, - /* returns string representation for debugging. */ - toString: function() { - var str = "Page \"" + this.name + "\" {
\n"; - this.elements.forEach(function(e) { - str += e.toString() + "
\n"; - }); - str += "} "; - return str; - }, - /* * Build the DOM. */ buildDom: function() { - var nodes = [] - this.elements.forEach(function(e) { - nodes.push(e.domNode); - }); - this.widget = new ContentPane({ - title: this.title, - id: this.name, - content: nodes, - style: "height: 100%; width: 100%;" + + this.widget = new View({ + id: this.name }); + this.elementList = new EdgeToEdgeList(); + this.elements.forEach(lang.hitch(this, function(e) { + this.elementList.addChild(e); + })); + this.widget.addChild(this.elementList); this.domNode = this.widget.domNode; } diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/PageElementFactory.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/PageElementFactory.js index 7d0625c2..74879507 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/PageElementFactory.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/PageElementFactory.js @@ -8,6 +8,7 @@ define([ "hos/sitemap/pageelements/TextElement", "hos/sitemap/pageelements/SwitchElement", "hos/sitemap/pageelements/SliderElement", + "hos/sitemap/pageelements/ColorPickerElement", "hos/sitemap/pageelements/ErrorElement", ], function( config, @@ -19,6 +20,7 @@ define([ TextElement, SwitchElement, SliderElement, + ColorPickerElement, ErrorElement ) { @@ -41,6 +43,8 @@ define([ element = new SwitchElement(page, data, this, parent); } else if (data["type"] == "sitemap/sitemap#/definitions/slider_element") { element = new SliderElement(page, data, this, parent); + } else if (data["type"] == "sitemap/sitemap#/definitions/colorpicker_element") { + element = new ColorPickerElement(page, data, this, parent); } else { element = new ErrorElement(page, data, this, parent); } diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Sitemap.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Sitemap.js index fee1a682..de71d1d7 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Sitemap.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/Sitemap.js @@ -44,7 +44,6 @@ define([ this.api = api; this.name = name; // parse json data - this.rootPageName = data["rootpage"]; this.title = data["title"]; // Create pages this.pages = {} @@ -55,39 +54,32 @@ define([ this.pages[_pageName] = _page } } + rootPageName = data["rootpage"]; + this.rootPage = this.pages[rootPageName]; this.buildDom(); }, - /* - * Dictionary containing all page elements. - */ - pageElements: {}, + rootPage: null, /* - * Stack containing name of visited pages. + * Stack containing visited pages. * Needed for bread crumbs and back button. */ - pageNameStack: [], + pageStack: [], - /* returns string representation for debugging. */ - toString: function() { - var str = "Sitemap \"" + this.name + "\" {
\n"; - for (var pageName in this.pages) { - str += this.pages[pageName].toString() + "
\n"; - } - str += "} "; - return str; - }, + pageElements: {}, /* * Build the DOM. */ buildDom: function() { - this.widget = new SitemapWidget({sitemap: this}); + this.widget = new SitemapWidget({ + sitemap: this + }); for (var pageName in this.pages) { var page = this.pages[pageName]; page.buildDom(); - this.widget.stackContainer.addChild(page.widget); + this.widget.addPage(page); } this.domNode = this.widget.domNode; }, @@ -97,36 +89,55 @@ define([ */ startup: function() { this.widget.startup(); - this.goToRootPage(); + this.widget.showPage(this.rootPage); + this.updateBreadCrumbs(); this.enableUpdates(); }, + getCurrentPage() { + if (this.pageStack.length > 0) { + return this.pageStack[this.pageStack.length-1]; + } else { + return this.rootPage; + } + }, + /* * Update the bread crumbs in the ui. */ updateBreadCrumbs: function() { - var str = "> " + this.rootPageName; - this.pageNameStack.forEach(function(e) { - str += " > " + e; - }); - this.widget.setBreadCrumbs(str); + var pages = [ this.rootPage ]; + if (this.pageStack.length > 0) { + this.widget.setTitle(this.title + ": " + this.getCurrentPage().title); + this.widget.setBackButtonVisibility(true); + pages = pages.concat(this.pageStack); + } else { + this.widget.setTitle(this.title); + this.widget.setBackButtonVisibility(false); + } + this.widget.setBreadCrumbs(pages); }, /* * Go to page with given name. */ goToPage: function(/*string*/ name) { - this.pageNameStack.push(name); - this.widget.stackContainer.selectChild(name, true); - this.updateBreadCrumbs(); + var page = this.pages[name]; + if (page) { + this.widget.goToPage(page, 1); + this.pageStack.push(page); + this.updateBreadCrumbs(); + return true; + } + return false; }, /* * Go to root page. */ goToRootPage: function() { - this.pageNameStack = []; - this.widget.stackContainer.selectChild(this.rootPageName); + this.widget.goToPage(this.rootPage, -99); + this.pageStack = []; this.updateBreadCrumbs(); }, @@ -134,13 +145,14 @@ define([ * Go one page back. */ goBack: function() { - if (this.pageNameStack.length > 0) { - this.pageNameStack.pop(); - if (this.pageNameStack.length > 0) { - this.goToPage(this.pageNameStack.pop()); - } else { - this.goToRootPage(); + if (this.pageStack.length > 0) { + var bp = this.rootPage; + if (this.pageStack.length > 1) { + bp = this.pageStack[this.pageStack.length-2]; } + this.widget.goToPage(bp, -1); + this.pageStack.pop(); + this.updateBreadCrumbs(); return true; } else { return false; @@ -195,16 +207,14 @@ define([ * Send command. */ sendPageElementCommand: function(uid, value) { - if (this._updateSocket) { - var msg = {eventtype: "sitemap_element_command", uid: uid, value: value}; - xhr.post(config.hos.sitemapUrl + "/" + this.name, { - data: {method: 'command', value: JSON.stringify(msg)} - }).then(function(data){ - console.log("sendPageElementCommand ok: " + data) - }, function(err){ - console.log("sendPageElementCommand error: " + err) - }); - } + var msg = {eventtype: "sitemap_element_command", uid: uid, value: value}; + xhr.post(config.hos.sitemapUrl + "/" + this.name, { + data: {method: 'command', value: JSON.stringify(msg)} + }).then(function(data){ + console.log("sendPageElementCommand ok: " + data) + }, function(err){ + console.log("sendPageElementCommand error: " + err) + }); } }); diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/ColorPickerElement.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/ColorPickerElement.js new file mode 100644 index 00000000..1e1a874b --- /dev/null +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/ColorPickerElement.js @@ -0,0 +1,71 @@ +define([ + "dojo/_base/config", + "dojo/_base/lang", + "dojo/_base/declare", + "dojo/Deferred", + "dojo/dom", + "dojo/dom-construct", + "hos/sitemap/pageelements/AtomicElement", + "dojox/mobile/Button", + "dojox/mobile/ListItem", + "dojox/mobile/Overlay", + "dojox/widget/ColorPicker", + "dojox/color" +], function(config, lang, declare, Deferred, dom, domConstruct, AtomicElement, Button, ListItem, Overlay, ColorPicker, Color) { + + return declare([AtomicElement], { + + /* returns string representation for debugging. */ + toString: function() { + var str = " SwitchElement (" + this.uid + ") "; + return str; + }, + + setColor: function(h, s, v) { + this.page.sitemap.sendPageElementCommand(this.uid, [h, s, v]); + }, + + /* + * Build the DOM. + */ + buildDom: function() { + this.widget = new ListItem({ + label: this.label, + onClick: lang.hitch(this, function() { + this.goToLinkedPage(); + }), + variableHeight: true + }); + this.colorWidget = ColorPicker({ + "class": "mblListItemLayoutRight", + onChange: lang.hitch(this, function(hex){ + var color = Color.fromHex(hex).toHsv(); + this.setColor(color["h"]/359, color["s"]/100, color["v"]/100); + }) + }); + this.widget.addChild(this.colorWidget, 0); + this.updateDom(); + this.domNode = this.widget.domNode; + }, + + /* + * Update data. + */ + updateData: function(data) { + this.inherited(arguments); + this.updateDom(); + }, + + /* + * Update DOM. + */ + updateDom: function() { + this.widget.set("label", this.label); + var color = Color.fromHsv(this.value[0]*359, this.value[1]*100, this.value[2]*100); + console.log("Color: " + color.toHex()); + this.colorWidget.setColor(color.toHex(), false); + } + + }); + +}); \ No newline at end of file diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/CompositeElement.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/CompositeElement.js index 3cc6b504..20b3cb81 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/CompositeElement.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/CompositeElement.js @@ -1,11 +1,12 @@ define([ "dojo/_base/config", 'dojo/_base/declare', + 'dojo/_base/lang', "dojo/Deferred", "dojo/dom", "dojo/dom-construct", "hos/sitemap/pageelements/ElementBase" -], function(config, declare, Deferred, dom, domConstruct, ElementBase) { +], function(config, declare, lang, Deferred, dom, domConstruct, ElementBase) { return declare([ElementBase], { @@ -22,12 +23,11 @@ define([ */ constructor: function(/*hos.sitemap.Page*/ page, /*json object*/ data, /*hos.sitemap.PageElementFactory*/ factory, /*hos/sitemap/pageelements/CompositeElement*/ parent) { this.elements = [] - var _this = this; - data["elements"].forEach(function(data) { - var element = factory.createPageElement(page, data, _this) - _this.page.sitemap.pageElements[element.uid] = element; - _this.elements.push(element) - }); + data["elements"].forEach(lang.hitch(this, function(data) { + var element = factory.createPageElement(page, data, this) + this.page.sitemap.pageElements[element.uid] = element; + this.elements.push(element) + })); } }); diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/FrameElement.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/FrameElement.js index 0ea47a13..339c8a0d 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/FrameElement.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/FrameElement.js @@ -1,12 +1,16 @@ define([ "dojo/_base/config", 'dojo/_base/declare', + 'dojo/_base/lang', "dojo/Deferred", "dojo/dom", "dojo/dom-construct", + "dojo/dom-style", "hos/sitemap/pageelements/CompositeElement", - "dijit/TitlePane" -], function(config, declare, Deferred, dom, domConstruct, CompositeElement, TitlePane) { + "dojox/mobile/RoundRectList", + "dojox/mobile/Pane", + "dojox/mobile/ListItem" +], function(config, declare, lang, Deferred, dom, domConstruct, domStyle, CompositeElement, RoundRectList, Pane, ListItem) { return declare([CompositeElement], { @@ -24,14 +28,21 @@ define([ * Build the DOM. */ buildDom: function() { - var nodes = [] - this.elements.forEach(function(e) { - nodes.push(e.domNode); + this.widget = Pane(); + //this.heading = domConstruct.toDom("
" + this.label + "
"); + //domConstruct.place(this.heading, this.widget.domNode); + this.elementList = new RoundRectList({ + baseClass: "mblRoundRectList" }); - this.widget = new TitlePane({ - title:this.label, - content:nodes + this.headerItem = new ListItem({ + label: this.label, + header: true }); + this.elementList.addChild(this.headerItem); + this.elements.forEach(lang.hitch(this, function(e) { + this.elementList.addChild(e); + })); + domConstruct.place(this.elementList.domNode, this.widget.domNode); this.domNode = this.widget.domNode } diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SliderElement.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SliderElement.js index 6817552a..3208b455 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SliderElement.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SliderElement.js @@ -6,9 +6,9 @@ define([ "dojo/dom", "dojo/dom-construct", "hos/sitemap/pageelements/AtomicElement", - "hos/sitemap/pageelements/widgets/ElementWidget", + "dojox/mobile/ListItem", "dojox/mobile/Slider" -], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ElementWidget, Slider) { +], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ListItem, Slider) { return declare([AtomicElement], { @@ -46,21 +46,26 @@ define([ * Build the DOM. */ buildDom: function() { - this.widget = new ElementWidget({baseClass: "SliderElementWidget"}); - /*this.sliderWidget = HorizontalSlider({ - minimum: this.min, - maximum: this.max, - value: this.value, - onChange: lang.hitch(this, this.setSliderValue) - });*/ + this.widget = new ListItem({ + label: this.label, + onClick: lang.hitch(this, function() { + this.goToLinkedPage(); + }) + }); this.sliderWidget = Slider({ minimum: this.min*100, maximum: this.max*100, value: this.value*100, - style: "width: 95%;", - onChange: lang.hitch(this, this.setSliderValue) + onClick: lang.hitch(this, function() { + console.log("onClick"); + }), + onChange: lang.hitch(this, this.setSliderValue), + style: { + width: "40%" + }, + "data-mobile-layout": "right" }); - this.widget.setValue(this.sliderWidget.domNode); + this.widget.addChild(this.sliderWidget, 0); this.updateDom(); this.domNode = this.widget.domNode; }, @@ -77,22 +82,13 @@ define([ * Update DOM. */ updateDom: function() { - if (typeof(this.linkedPageName) != "undefined") { - var tmp = domConstruct.create("a",{ - href: "javascript:void(0)", - innerHTML: "" + this.label + "", - onclick: lang.hitch(this, this.goToLinkedPage) - }); - this.widget.setLabel(tmp); - var tmp2 = domConstruct.create("div",{ - innerHTML: " >> ", - onclick: lang.hitch(this, this.goToLinkedPage) - }); - this.widget.setLink(tmp2); + this.widget.set("label", this.label); + this.sliderWidget.set("value", this.value*100, false); + if (this.linkedPageName) { + this.widget.set("clickable", true); } else { - this.widget.setLabel(domConstruct.toDom("" + this.label + "")); + this.widget.set("clickable", false); } - this.sliderWidget.set("value", this.value*100); } }); diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SwitchElement.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SwitchElement.js index 31c71798..e96cbe4f 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SwitchElement.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/SwitchElement.js @@ -6,9 +6,9 @@ define([ "dojo/dom", "dojo/dom-construct", "hos/sitemap/pageelements/AtomicElement", - "hos/sitemap/pageelements/widgets/ElementWidget", - "dojox/mobile/Switch" -], function(config, lang, declare, Deferred, dom, domConstruct, AtomicElement, ElementWidget, Switch) { + "dojox/mobile/Switch", + "dojox/mobile/ListItem" +], function(config, lang, declare, Deferred, dom, domConstruct, AtomicElement, Switch, ListItem) { return declare([AtomicElement], { @@ -22,11 +22,22 @@ define([ * Build the DOM. */ buildDom: function() { - this.widget = new ElementWidget({baseClass: "SwitchElementWidget"}); - this.buttonWidget = Switch({ + this.widget = new ListItem({ + label: this.label, + onClick: lang.hitch(this, function() { + this.goToLinkedPage(); + }) }); - this.buttonWidget.on("stateChanged", lang.hitch(this, this.setSwitch)); - this.widget.setValue(this.buttonWidget.domNode); + this.buttonWidget = Switch({ + onClick: lang.hitch(this, function() { + this.setSwitch(this.buttonWidget.get("value") == "on" ? "off" : "on"); + return false; + }), + style: { + "margin-right": "30px" + } + }); + this.widget.addChild(this.buttonWidget); this.updateDom(); this.domNode = this.widget.domNode; }, @@ -37,16 +48,24 @@ define([ toggleSwitch: function() { this.value = !this.value; this.updateDom(); - this.page.sitemap.sendPageElementCommand(this.uid, this.value); + if (this.page.sitemap.sendPageElementCommand(this.uid, this.value)) { + return true; + } else { + return false; + } }, - + /* * Set switch. */ setSwitch: function(value) { this.value = (value == "on"); this.updateDom(); - this.page.sitemap.sendPageElementCommand(this.uid, this.value); + if (this.page.sitemap.sendPageElementCommand(this.uid, this.value)) { + return true; + } else { + return false; + } }, /* @@ -61,22 +80,13 @@ define([ * Update DOM. */ updateDom: function() { - if (typeof(this.linkedPageName) != "undefined") { - var tmp = domConstruct.create("a",{ - href: "javascript:void(0)", - innerHTML: "" + this.label + "", - onclick: lang.hitch(this, this.goToLinkedPage) - }); - this.widget.setLabel(tmp); - var tmp2 = domConstruct.create("div",{ - innerHTML: " >> ", - onclick: lang.hitch(this, this.goToLinkedPage) - }); - this.widget.setLink(tmp2); + this.widget.set("label", this.label); + this.buttonWidget.set("value", this.value ? "on" : "off", false); + if (this.linkedPageName) { + this.widget.set("clickable", true); } else { - this.widget.setLabel(domConstruct.toDom("" + this.label + "")); + this.widget.set("clickable", false); } - this.buttonWidget.set("value", this.value ? "on" : "off"); } }); diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/TextElement.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/TextElement.js index f06b6b32..ca88a81b 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/TextElement.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/pageelements/TextElement.js @@ -6,8 +6,8 @@ define([ "dojo/dom", "dojo/dom-construct", "hos/sitemap/pageelements/AtomicElement", - "hos/sitemap/pageelements/widgets/ElementWidget" -], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ElementWidget) { + "dojox/mobile/ListItem" +], function(config, declare, lang, Deferred, dom, domConstruct, AtomicElement, ListItem) { return declare([AtomicElement], { @@ -21,7 +21,13 @@ define([ * Build the DOM. */ buildDom: function() { - this.widget= new ElementWidget({baseClass: "TextElementWidget"}); + this.widget = new ListItem({ + label: this.label, + rightText: this.value, + onClick: lang.hitch(this, function() { + this.goToLinkedPage(); + }) + }); this.updateDom(); this.domNode = this.widget.domNode; }, @@ -38,22 +44,13 @@ define([ * Update DOM. */ updateDom: function() { - if (typeof(this.linkedPageName) != "undefined") { - var tmp = domConstruct.create("a",{ - href: "javascript:void(0)", - innerHTML: "" + this.label + "", - onclick: lang.hitch(this, this.goToLinkedPage) - }); - this.widget.setLabel(tmp); - var tmp2 = domConstruct.create("div",{ - innerHTML: " >> ", - onclick: lang.hitch(this, this.goToLinkedPage) - }); - this.widget.setLink(tmp2); + this.widget.set("label", this.label); + this.widget.set("rightText", this.value); + if (this.linkedPageName) { + this.widget.set("clickable", true); } else { - this.widget.setLabel(domConstruct.toDom("" + this.label + "")); + this.widget.set("clickable", false); } - this.widget.setValue(domConstruct.toDom("" + this.value + "")); } }); diff --git a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/widgets/SitemapWidget.js b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/widgets/SitemapWidget.js index 5073b1dc..d4e5135b 100644 --- a/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/widgets/SitemapWidget.js +++ b/src/hos_cosgi_testwebapp/webroot/libs/hos/sitemap/widgets/SitemapWidget.js @@ -3,66 +3,75 @@ define([ "dojo/_base/lang", "dojo/dom", "dojo/dom-construct", - "dijit/_WidgetBase", - "dijit/layout/BorderContainer", - "dijit/layout/StackContainer", - "dijit/layout/ContentPane", - "dijit/form/Button" -], function(declare, lang, dom, domConstruct, _WidgetBase, BorderContainer, StackContainer, ContentPane, Button) { + "dojo/dom-style", + "dijit/_WidgetBase", + "dojox/mobile/ScrollablePane", + "dojox/mobile/Container", + "dojox/mobile/Heading", + "dojox/mobile/ScrollablePane", + "dojox/mobile/ToolBarButton", + "dojox/mobile/RoundRect" +], function(declare, lang, dom, domConstruct, domStyle, _WidgetBase, ScrollablePane, Container, Heading, ScrollablePane, ToolBarButton, RoundRect) { return declare([_WidgetBase], { + /* + * + */ + addPage: function(page) { + this.widget.addChild(page.widget); + }, + + /* + * + */ + goToPage: function(page, direction) { + var curpage = this.sitemap.getCurrentPage(); + curpage.widget.performTransition(page.name, direction, "slide"); + }, + + showPage: function(page, noEvents) { + page.widget.show(noEvents); + }, + /* * buildRendering function. */ buildRendering: function() { if(!this._rendered){ - - // create a BorderContainer as the top widget in the hierarchy - this.bc = new BorderContainer({ - style: "width: 100%; height: 100%;" - }); - - // create a ContentPane as the left pane in the BorderContainer - /*this.cp1 = new ContentPane({ - region: "left", - splitter: true, - style: "width: 150px;", - content: "

Sitemap/Navigation

  • ToDo
" - }); - this.bc.addChild(this.cp1);*/ - - this.stackContainer = StackContainer(); - this.backButton = new Button({ + this.scrollPane = new ScrollablePane({ + scrollableParams: { + scrollBar: true, + scrollDir: "v" + } + }); + this.widget = new Container(); + this.widget.placeAt(this.scrollPane); + this.h1 = new Heading({ + label: this.sitemap.title + }); + this.backButton = new ToolBarButton({ + arrow: "left", label: "Back", - onClick: lang.hitch(this, function(){ - this.sitemap.goBack(); - }) - }); - this.homeButton = new Button({ + onClick: lang.hitch(this.sitemap, this.sitemap.goBack) + }); + this.backButton.placeAt(this.h1.domNode); + this.homeButton = new ToolBarButton({ label: "Home", - onClick: lang.hitch(this, function(){ - this.sitemap.goToRootPage(); - }) - }); - // create a ContentPane as the center pane in the BorderContainer - this.cp2 = new ContentPane({ - region: "center", - content: [this.stackContainer.domNode, this.backButton.domNode, this.homeButton.domNode] - }); - this.bc.addChild(this.cp2); - - var contentNode = domConstruct.toDom("Home Operating System:
bread crumbs here
"); - this.breadCrumbNode = dom.byId("breadCrumbNode", contentNode) - // create a ContentPane as the top pane in the BorderContainer - this.cp3 = new ContentPane({ - region: "top", - content: contentNode - }); - this.bc.addChild(this.cp3); - - this.domNode = this.bc.domNode; + onClick: lang.hitch(this.sitemap, this.sitemap.goToRootPage) + }); + this.homeButton.placeAt(this.h1.domNode); + this.widget.addChild(this.h1); + + this.breadCrumbs = new RoundRect({ + innerHTML: "Bread crumbs here", + shadows: true + }); + this.widget.addChild(this.breadCrumbs); + + + this.domNode = this.scrollPane.domNode; } this.inherited(arguments); this._rendered = true; @@ -72,14 +81,27 @@ define([ * startup function. */ startup: function() { - this.bc.startup(); + this.scrollPane.startup(); + }, + + setTitle: function(title) { + this.h1.set("label", title); }, /* * Set bread crumbs. */ - setBreadCrumbs: function(/*string*/ text) { - this.breadCrumbNode.innerHTML=text + setBreadCrumbs: function(/*array*/ pages) { + var text = ""; + pages.forEach(lang.hitch(this, function(p){ + text += "> " + p.title + " "; + })); + this.breadCrumbs.set("innerHTML", text); + }, + + setBackButtonVisibility: function(value) { + domStyle.set(this.backButton.domNode, "display", value ? "" : "none"); + domStyle.set(this.homeButton.domNode, "display", value ? "" : "none"); } }); diff --git a/src/hos_cosgi_testwebapp/webroot/sitemap01.html b/src/hos_cosgi_testwebapp/webroot/sitemap01.html index 5376c8d3..d82ebc59 100644 --- a/src/hos_cosgi_testwebapp/webroot/sitemap01.html +++ b/src/hos_cosgi_testwebapp/webroot/sitemap01.html @@ -2,11 +2,14 @@ + + Sitemap Test 01 - - - + +