diff --git a/src/wirecloud/commons/static/js/StyledElements/CodeArea.js b/src/wirecloud/commons/static/js/StyledElements/CodeArea.js index 164a133b1..dcc4bae4c 100644 --- a/src/wirecloud/commons/static/js/StyledElements/CodeArea.js +++ b/src/wirecloud/commons/static/js/StyledElements/CodeArea.js @@ -148,6 +148,7 @@ if (!window.monaco) { // If monaco is not available, use the TextArea class se.CodeArea = se.TextArea; + se.__Testing__CodeArea = CodeAreaClass; // For testing purposes } else { se.CodeArea = CodeAreaClass; } diff --git a/src/wirecloud/commons/utils/template/parsers/json.py b/src/wirecloud/commons/utils/template/parsers/json.py index 0c1fe5af6..c2723d892 100644 --- a/src/wirecloud/commons/utils/template/parsers/json.py +++ b/src/wirecloud/commons/utils/template/parsers/json.py @@ -242,16 +242,35 @@ def _init(self): self._check_string_fields(('title',), place=tab, required=False) self._check_array_fields(('resources',), place=tab) for widget in tab['resources']: - rendering = widget.get('rendering', {}) - self._check_integer_fields(('layout',), place=rendering, default=0, allow_cast=True) - layout = rendering['layout'] - self._check_boolean_fields(('relwidth',), place=rendering, default=True) - self._check_boolean_fields(('relheight',), place=rendering, default=(layout != 1)) - - position = widget.get('position', {}) - self._check_string_fields(('anchor',), place=position, default="top-left") - self._check_boolean_fields(('relx',), place=position, default=True) - self._check_boolean_fields(('rely',), place=position, default=(layout != 1)) + screenSizes = widget.get('screenSizes', None) + if screenSizes is None: + screenSizes = [ + { + 'moreOrEqual': 0, + 'lessOrEqual': -1, + 'id': 0, + 'rendering': widget.get('rendering', {}), + 'position': widget.get('position', {}) + } + ] + + layout = screenSizes[0]['rendering'].get('layout', 0) + widget['layout'] = layout + else: + layout = widget.get('layout', 0) + + for screenSize in screenSizes: + self._check_integer_fields(('moreOrEqual', 'lessOrEqual', 'id'), place=screenSize, required=True) + + rendering = screenSize.get('rendering', {}) + self._check_integer_fields(('layout',), place=rendering, default=0, allow_cast=True) + self._check_boolean_fields(('relwidth',), place=rendering, default=True) + self._check_boolean_fields(('relheight',), place=rendering, default=(layout != 1)) + + position = screenSize.get('position', {}) + self._check_string_fields(('anchor',), place=position, default="top-left") + self._check_boolean_fields(('relx',), place=position, default=True) + self._check_boolean_fields(('rely',), place=position, default=(layout != 1)) for preference in self._info['params']: self._check_string_fields(('name', 'type'), place=preference, required=True) diff --git a/src/wirecloud/commons/utils/template/parsers/xml.py b/src/wirecloud/commons/utils/template/parsers/xml.py index 62d31d175..e69d674ea 100644 --- a/src/wirecloud/commons/utils/template/parsers/xml.py +++ b/src/wirecloud/commons/utils/template/parsers/xml.py @@ -75,6 +75,7 @@ TAB_XPATH = 't:tab' RESOURCE_XPATH = 't:resource' POSITION_XPATH = 't:position' +SCREEN_SIZES_XPATH = 't:screensizes' RENDERING_XPATH = 't:rendering' PARAM_XPATH = 't:preferences/t:preference' EMBEDDEDRESOURCE_XPATH = 't:embedded/t:resource' @@ -568,10 +569,21 @@ def _parse_workspace_info(self): } for widget in self._xpath(RESOURCE_XPATH, tab): - position = self.get_xpath(POSITION_XPATH, widget) - rendering = self.get_xpath(RENDERING_XPATH, widget) + position = self.get_xpath(POSITION_XPATH, widget, required=False) + screenSizes = self.get_xpath(SCREEN_SIZES_XPATH, widget, required=False) + rendering = self.get_xpath(RENDERING_XPATH, widget, required=False) + + if (position is None or rendering is None) and screenSizes is None: + raise TemplateParseException(_("Missing position/rendering or screensizes element")) + + if (rendering is None and not widget.get('layout')): + raise TemplateParseException(_("Missing layout in resource or rendering element")) + + if rendering is None: + layout = int(str(widget.get('layout'))) + else: + layout = int(str(rendering.get('layout'))) - layout = int(str(rendering.get('layout'))) widget_info = { 'id': str(widget.get('id')), 'name': str(widget.get('name')), @@ -579,28 +591,67 @@ def _parse_workspace_info(self): 'version': str(widget.get('version')), 'title': str(widget.get('title')), 'readonly': widget.get('readonly', '').lower() == 'true', + 'layout': layout, 'properties': {}, - 'preferences': {}, - 'position': { - 'anchor': str(position.get('anchor', 'top-left')), - 'relx': position.get('relx', 'true').lower() == 'true', - 'rely': position.get('rely', 'true' if layout != 1 else 'false').lower() == 'true', - 'x': str(position.get('x')), - 'y': str(position.get('y')), - 'z': str(position.get('z')), - }, - 'rendering': { - 'fulldragboard': rendering.get('fulldragboard', 'false').lower() == 'true', - 'minimized': rendering.get('minimized', 'false').lower() == 'true', - 'relwidth': rendering.get('relwidth', 'true').lower() == 'true', - 'relheight': rendering.get('relheight', 'true' if layout != 1 else 'false').lower() == 'true', - 'width': str(rendering.get('width')), - 'height': str(rendering.get('height')), - 'layout': layout, - 'titlevisible': rendering.get('titlevisible', 'true').lower() == 'true', - }, + 'preferences': {} } + if screenSizes is not None: + widget_info['screenSizes'] = [] + for screenSize in screenSizes: + position = self.get_xpath(POSITION_XPATH, screenSize) + rendering = self.get_xpath(RENDERING_XPATH, screenSize) + screen_size_info = { + 'moreOrEqual': int(screenSize.get('moreOrEqual')), + 'lessOrEqual': int(screenSize.get('lessOrEqual')), + 'id': int(screenSize.get('id')), + 'position': { + 'anchor': str(position.get('anchor', 'top-left')), + 'relx': position.get('relx', 'true').lower() == 'true', + 'rely': position.get('rely', 'true' if layout != 1 else 'false').lower() == 'true', + 'x': int(float(position.get('x'))), + 'y': int(float(position.get('y'))), + 'z': int(float(position.get('z'))), + }, + 'rendering': { + 'fulldragboard': rendering.get('fulldragboard', 'false').lower() == 'true', + 'minimized': rendering.get('minimized', 'false').lower() == 'true', + 'relwidth': rendering.get('relwidth', 'true').lower() == 'true', + 'relheight': rendering.get('relheight', 'true' if layout != 1 else 'false').lower() == 'true', + 'width': int(float(rendering.get('width'))), + 'height': int(float(rendering.get('height'))), + 'titlevisible': rendering.get('titlevisible', 'true').lower() == 'true', + } + } + + widget_info['screenSizes'].append(screen_size_info) + else: + widget_info['screenSizes'] = [ + { + 'moreOrEqual': 0, + 'lessOrEqual': -1, + 'id': 0, + 'position': { + 'anchor': str(position.get('anchor', 'top-left')), + 'relx': position.get('relx', 'true').lower() == 'true', + 'rely': position.get('rely', 'true' if layout != 1 else 'false').lower() == 'true', + 'x': str(position.get('x')), + 'y': str(position.get('y')), + 'z': str(position.get('z')), + }, + 'rendering': { + 'fulldragboard': rendering.get('fulldragboard', 'false').lower() == 'true', + 'minimized': rendering.get('minimized', 'false').lower() == 'true', + 'relwidth': rendering.get('relwidth', 'true').lower() == 'true', + 'relheight': rendering.get('relheight', 'true' if layout != 1 else 'false').lower() == 'true', + 'width': str(rendering.get('width')), + 'height': str(rendering.get('height')), + 'layout': layout, + 'titlevisible': rendering.get('titlevisible', 'true').lower() == 'true', + } + } + ] + for prop in self._xpath(PROPERTIES_XPATH, widget): prop_value = prop.get('value') widget_info['properties'][str(prop.get('name'))] = { diff --git a/src/wirecloud/commons/utils/template/schemas/xml_schema.xsd b/src/wirecloud/commons/utils/template/schemas/xml_schema.xsd index 0d292c03c..6ea79f0f8 100644 --- a/src/wirecloud/commons/utils/template/schemas/xml_schema.xsd +++ b/src/wirecloud/commons/utils/template/schemas/xml_schema.xsd @@ -51,6 +51,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -762,19 +791,25 @@ - - + - - - - - - - - + + + + + + + + + + + + + + + @@ -792,6 +827,7 @@ + diff --git a/src/wirecloud/commons/utils/template/writers/xml.py b/src/wirecloud/commons/utils/template/writers/xml.py index 241a2b26a..d49c878dc 100644 --- a/src/wirecloud/commons/utils/template/writers/xml.py +++ b/src/wirecloud/commons/utils/template/writers/xml.py @@ -78,7 +78,7 @@ def addPreferenceValues(resource, preferences): addAttribute(pref, element, 'value', type='string', default=None, required=False) addAttributes(pref, element, ('readonly', 'hidden'), default='false', type='boolean') - +# TODO Adrian handle multiple screen sizes def write_mashup_tree(doc, resources, options): # Params @@ -122,24 +122,35 @@ def write_mashup_tree(doc, resources, options): if iwidget.get('readonly', False): resource.set('readonly', 'true') - layout = iwidget['rendering']['layout'] - - position = etree.SubElement( - resource, - 'position', - anchor=str(iwidget['position']['anchor']), - x=str(iwidget['position']['x']), - y=str(iwidget['position']['y']), - z=str(iwidget['position']['z']) - ) - addAttributes(iwidget['position'], position, ('relx',), default='true', type='boolean') - addAttributes(iwidget['position'], position, ('rely',), default=('true' if layout != 1 else 'false'), type='boolean') - - rendering = etree.SubElement(resource, 'rendering') - addAttributes(iwidget['rendering'], rendering, ('height', 'width', 'layout'), required=True) - addAttributes(iwidget['rendering'], rendering, ('minimized', 'fulldragboard'), default='false', type='boolean') - addAttributes(iwidget['rendering'], rendering, ('relwidth', 'titlevisible'), default='true', type='boolean') - addAttributes(iwidget['rendering'], rendering, ('relheight',), default=('true' if layout != 1 else 'false'), type='boolean') + layout = iwidget['layout'] + + addAttributes(iwidget, resource, ('layout',), required=True) + + screenSizesElem = etree.SubElement(resource, 'screensizes') + for screenSize in iwidget.get('screenSizes', []): + screenSizeElem = etree.SubElement(screenSizesElem, + 'screensize', + moreOrEqual=str(screenSize['moreOrEqual']), + lessOrEqual=str(screenSize['lessOrEqual']), + id=str(screenSize['id'])) + + position = etree.SubElement( + screenSizeElem, + 'position', + anchor=str(screenSize['position']['anchor']), + x=str(int(float(screenSize['position']['x']))), + y=str(int(float(screenSize['position']['y']))), + z=str(int(float(screenSize['position']['z']))) + ) + addAttributes(screenSize['position'], position, ('relx',), default='true', type='boolean') + addAttributes(screenSize['position'], position, ('rely',), default=('true' if layout != 1 else 'false'), type='boolean') + + rendering = etree.SubElement(screenSizeElem, 'rendering', + height=str(int(float(screenSize['rendering']['height']))), + width=str(int(float(screenSize['rendering']['width'])))), + addAttributes(screenSize['rendering'], rendering, ('minimized', 'fulldragboard'), default='false', type='boolean') + addAttributes(screenSize['rendering'], rendering, ('relwidth', 'titlevisible'), default='true', type='boolean') + addAttributes(screenSize['rendering'], rendering, ('relheight',), default=('true' if layout != 1 else 'false'), type='boolean') addPreferenceValues(resource, iwidget['preferences']) diff --git a/src/wirecloud/defaulttheme/static/css/workspace/dragboard.scss b/src/wirecloud/defaulttheme/static/css/workspace/dragboard.scss index 71a3d3c4d..264c2c126 100644 --- a/src/wirecloud/defaulttheme/static/css/workspace/dragboard.scss +++ b/src/wirecloud/defaulttheme/static/css/workspace/dragboard.scss @@ -123,6 +123,7 @@ padding: 10px; border-radius: 7px; right: 50px; + top: 39px; } .wc-editing-interval-close { diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/SidebarLayout.js b/src/wirecloud/platform/static/js/wirecloud/ui/SidebarLayout.js index f852c7ef7..118b25b58 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/SidebarLayout.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/SidebarLayout.js @@ -136,6 +136,10 @@ return result; } + removeHandle() { + this.handle.remove(); + } + removeWidget(widget, affectsDragboard) { const result = super.removeWidget(widget, affectsDragboard); @@ -205,7 +209,7 @@ } else { offset = 0; } - element.style.left = this.getColumnOffset(widget.position, true); + element.style.left = this.getColumnOffset(widget.position, null, true); element.style.right = ""; if (this.position === "top") { element.style.top = offset + "px"; diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/WidgetView.js b/src/wirecloud/platform/static/js/wirecloud/ui/WidgetView.js index ee36fe870..7f15b8ae1 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/WidgetView.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/WidgetView.js @@ -842,6 +842,9 @@ }; this.layout.removeWidgetEventListeners(this); + if ('removeHandle' in this.layout) { + this.layout.removeHandle(); + } this.layout = null; this.setPosition(newPos, false); diff --git a/src/wirecloud/platform/workspace/mashupTemplateGenerator.py b/src/wirecloud/platform/workspace/mashupTemplateGenerator.py index 224584ecd..cd1380bc2 100644 --- a/src/wirecloud/platform/workspace/mashupTemplateGenerator.py +++ b/src/wirecloud/platform/workspace/mashupTemplateGenerator.py @@ -41,6 +41,7 @@ def get_workspace_description(workspace): return get_iwidgets_description(included_iwidgets) +# TODO Adrian handle multiple screen sizes def process_iwidget(workspace, iwidget, wiring, parametrization, readOnlyWidgets, cache_manager): widget = iwidget.widget @@ -136,35 +137,46 @@ def process_iwidget(workspace, iwidget, wiring, parametrization, readOnlyWidgets 'value': value, } - return { + screenSizes = [] + for configuration in iwidget.positions['configurations']: + screenSizes.append({ + 'moreOrEqual': configuration['moreOrEqual'], + 'lessOrEqual': configuration['lessOrEqual'], + 'id': configuration['id'], + 'position': { + 'anchor': configuration['widget'].get('anchor', 'top-left'), + 'relx': configuration['widget'].get('relx', True), + 'rely': configuration['widget'].get('rely', True if iwidget.layout != 1 else False), + 'x': str(configuration['widget']['left']), + 'y': str(configuration['widget']['top']), + 'z': str(configuration['widget']['zIndex']) + }, + 'rendering': { + 'relwidth': configuration['widget'].get('relwidth', True), + 'relheight': configuration['widget'].get('relheight', True if iwidget.layout != 1 else False), + 'width': str(configuration['widget']['width']), + 'height': str(configuration['widget']['height']), + 'fulldragboard': bool(configuration['widget']['fulldragboard']), + 'minimized': bool(configuration['widget']['minimized']), + 'titlevisible': bool(configuration['widget'].get('titlevisible', True)), + }, + }) + + iwidget_data = { 'id': iwidget_id, 'vendor': iwidget.widget.resource.vendor, 'name': iwidget.widget.resource.short_name, 'version': iwidget.widget.resource.version, 'title': iwidget.name, + 'layout': iwidget.layout, 'readonly': readOnlyWidgets, 'properties': properties, 'preferences': preferences, - 'position': { - 'anchor': iwidget.positions['widget'].get('anchor', 'top-left'), - 'relx': iwidget.positions['widget'].get('relx', True), - 'rely': iwidget.positions['widget'].get('rely', True if iwidget.layout != 1 else False), - 'x': str(iwidget.positions['widget']['left']), - 'y': str(iwidget.positions['widget']['top']), - 'z': str(iwidget.positions['widget']['zIndex']), - }, - 'rendering': { - 'relwidth': iwidget.positions['widget'].get('relwidth', True), - 'relheight': iwidget.positions['widget'].get('relheight', True if iwidget.layout != 1 else False), - 'width': str(iwidget.positions['widget']['width']), - 'height': str(iwidget.positions['widget']['height']), - 'layout': iwidget.layout, - 'fulldragboard': bool(iwidget.positions['widget']['fulldragboard']), - 'minimized': bool(iwidget.positions['widget']['minimized']), - 'titlevisible': bool(iwidget.positions['widget'].get('titlevisible', True)), - }, + 'screenSizes': screenSizes } + return iwidget_data + def build_json_template_from_workspace(options, workspace, user): options['type'] = 'mashup' diff --git a/src/wirecloud/platform/workspace/mashupTemplateParser.py b/src/wirecloud/platform/workspace/mashupTemplateParser.py index d280035de..034d95de4 100644 --- a/src/wirecloud/platform/workspace/mashupTemplateParser.py +++ b/src/wirecloud/platform/workspace/mashupTemplateParser.py @@ -225,27 +225,38 @@ def fillWorkspaceUsingTemplate(workspace, template): for resource in tab_entry['resources']: - position = resource['position'] - rendering = resource['rendering'] - widget = get_or_add_widget_from_catalogue(resource.get('vendor'), resource.get('name'), resource.get('version'), user) iwidget_data = { "widget": widget.uri, "title": resource.get('title'), - "left": float(position.get('x')), - "top": float(position.get('y')), "icon_left": 0, "icon_top": 0, - "zIndex": int(position.get('z')), - "width": float(rendering.get('width')), - "height": float(rendering.get('height')), - "layout": int(rendering.get('layout')), - "minimized": rendering['minimized'], - "fulldragboard": rendering['fulldragboard'], - "titlevisible": rendering['titlevisible'], + "layout": int(resource.get('layout')), + "layoutConfigurations": [] } + for configuration in resource["screenSizes"]: + position = configuration['position'] + rendering = configuration['rendering'] + + iwidget_layoutConfig = { + 'moreOrEqual': configuration['moreOrEqual'], + 'lessOrEqual': configuration['lessOrEqual'], + 'id': configuration['id'], + "left": float(position.get('x')), + "top": float(position.get('y')), + "zIndex": int(position.get('z')), + "width": float(rendering.get('width')), + "height": float(rendering.get('height')), + "minimized": rendering['minimized'], + "fulldragboard": rendering['fulldragboard'], + "titlevisible": rendering['titlevisible'], + 'action': 'update' + } + + iwidget_data['layoutConfigurations'].append(iwidget_layoutConfig) + iwidget = SaveIWidget(iwidget_data, user, tab, commit=False) if resource.get('readonly'): iwidget.readOnly = True