From bd54af6e3ba4d7002143c6655cf74e9e56679e1c Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Mon, 29 Aug 2016 13:21:27 +0300 Subject: [PATCH 01/22] Fix #183 A combo button with a single menu item can be dropped down --- .../combobutton/ToolBarComboButtonBinding.js | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/Website/Composite/scripts/source/top/ui/bindings/buttons/combobutton/ToolBarComboButtonBinding.js b/Website/Composite/scripts/source/top/ui/bindings/buttons/combobutton/ToolBarComboButtonBinding.js index 77e1ec3507..8ab7e86d41 100644 --- a/Website/Composite/scripts/source/top/ui/bindings/buttons/combobutton/ToolBarComboButtonBinding.js +++ b/Website/Composite/scripts/source/top/ui/bindings/buttons/combobutton/ToolBarComboButtonBinding.js @@ -33,6 +33,11 @@ function ToolBarComboButtonBinding() { */ this.keepState = true; + /** + * @type {boolean} + */ + this.hasPopupItems = false; + /** * @type {boolean} */ @@ -59,9 +64,7 @@ ToolBarComboButtonBinding.prototype.onBindingAttach = function () { ToolBarComboButtonBinding.superclass.onBindingAttach.call(this); - this.comboBoxBinding = ComboBoxBinding.newInstance(this.bindingDocument); - this.add(this.comboBoxBinding); - this.comboBoxBinding.attach(); + this.buildCombobox(); this.attachClassName(ToolBarComboButtonBinding.CLASSNAME_COMBOBUTTON); @@ -126,11 +129,31 @@ ToolBarComboButtonBinding.prototype.setPopup = function (arg) { if (latestMenuItemBinding != null) this.setButton(latestMenuItemBinding); + this.updateCombobox(menuItemBindings.getLength() > 1); +} + + +ToolBarComboButtonBinding.prototype.buildCombobox = function () { + + if (!this.comboBoxBinding) { + this.comboBoxBinding = ComboBoxBinding.newInstance(this.bindingDocument); + this.add(this.comboBoxBinding); + this.comboBoxBinding.attach(); + this.updateCombobox(); + } +} + +ToolBarComboButtonBinding.prototype.updateCombobox = function (hasPopupItems) { + + if (hasPopupItems != undefined) { + this.hasPopupItems = hasPopupItems; + } + if (this.comboBoxBinding) { - if (menuItemBindings.getLength() <= 1) { - this.comboBoxBinding.hide(); - } else { + if (this.hasPopupItems) { this.comboBoxBinding.show(); + } else { + this.comboBoxBinding.hide(); } } } From 3b49830e966132ac8b93566c9c2eefe9f540a75a Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Mon, 29 Aug 2016 16:23:27 +0300 Subject: [PATCH 02/22] Fix #189 The client's OpenViewDefinition for Composite.Management.Browser may load URL in a wrong perspective. --- .../top/ui/bindings/views/ViewBinding.js | 317 +++++++++--------- 1 file changed, 163 insertions(+), 154 deletions(-) diff --git a/Website/Composite/scripts/source/top/ui/bindings/views/ViewBinding.js b/Website/Composite/scripts/source/top/ui/bindings/views/ViewBinding.js index 66666b48c7..fbd1b8464d 100644 --- a/Website/Composite/scripts/source/top/ui/bindings/views/ViewBinding.js +++ b/Website/Composite/scripts/source/top/ui/bindings/views/ViewBinding.js @@ -12,7 +12,7 @@ ViewBinding.HORIZONTAL_ADJUST = 1; ViewBinding.VERTICAL_ADJUST = 1; /* - * These strings get attached to + * These strings get attached to * respective views as classnames. */ ViewBinding.TYPE_EXPLORERVIEW = "explorerview"; @@ -24,7 +24,7 @@ ViewBinding.TYPE_DIALOGVIEW = "dialogview"; */ ViewBinding.CLASSNAME_ACTIVE = "active"; - /** + /** * Timeout in seconds before assuming an ASPX error. * @type {int} */ @@ -43,7 +43,7 @@ ViewBinding._instances = new Map (); */ ViewBinding.hasInstance = function (handle) { - return ViewBinding._instances.has(handle); + return ViewBinding._instances.has(ViewBinding.normalizeHandle(handle)); } /** @@ -52,8 +52,8 @@ ViewBinding.hasInstance = function (handle) { * @return {ViewBinding} */ ViewBinding.getInstance = function ( handle ) { - - var result = ViewBinding._instances.get ( handle ); + + var result = ViewBinding._instances.get (ViewBinding.normalizeHandle(handle)); //if ( !result ) { // var cry = "ViewBinding.getInstance: No such instance: " + handle; // SystemLogger.getLogger ( "ViewBinding [static]" ).error ( cry ); @@ -65,6 +65,15 @@ ViewBinding.getInstance = function ( handle ) { return result; } + +ViewBinding.normalizeHandle = function (handle) { + + if (handle === "Composite.Management.Browser" && StageBinding.perspectiveNode) { + return handle + "." + StageBinding.perspectiveNode.getHandle(); + } + return handle; +} + /** * @class */ @@ -74,82 +83,82 @@ function ViewBinding () { * @type {SystemLogger} */ this.logger = SystemLogger.getLogger ( "ViewBinding" ); - + /** * @type {ViewDefinition} */ this._viewDefinition = null; - + /** * @type {boolean} */ this.isVisible = false; - + /** * @type {boolean} */ this._isViewBindingInitialized = false; - + /** * @type {Binding} - */ + */ this._snapBinding = null; - + /** * @type {boolean} */ this.isFreeFloating = false; - + /** * Remember that the window is hidden while attaching due to CSS. * @type {WindowBinding} */ this.windowBinding = null; - + /** * @type {CoverBinding} */ this._coverBinding = null; - + /** * @type {boolean} */ this._isLoaded = false; - + /** * Patches a strange bug in mozilla. */ this._isFirstShow = true; - + /** * Defaults to dockview. * @type {string); */ this._type = ViewBinding.TYPE_DOCKVIEW; - + /** * Points to the currently hosted PageBinding. * @type {PageBinding); */ this._pageBinding = null; - + /** * Backup position to minimize updates. * @type {Point} */ this._lastknownposition = null; - + /** * Backup dimension to minimize updates. * @type {Dimension} */ this._lastknowndimension = null; - + /** * @type {boolean} */ this.isActivated = false; - + /* * Returnable. */ @@ -179,14 +188,14 @@ ViewBinding.prototype.onBindingRegister = function () { this.addActionListener ( PageBinding.ACTION_ATTACHED ); this.addActionListener ( PageBinding.ACTION_INITIALIZED ); this.addActionListener ( ViewBinding.ACTION_DETACH ); - + /* * Performance timing related. */ this.addActionListener ( WizardPageBinding.ACTION_NAVIGATE_NEXT ); this.addActionListener ( WizardPageBinding.ACTION_NAVIGATE_PREVIOUS ); this.addActionListener ( WizardPageBinding.ACTION_FINISH ); - + /* * Tune in on broadcasted closing statements. */ @@ -202,14 +211,14 @@ ViewBinding.prototype.onBindingAttach = function () { ViewBinding.superclass.onBindingAttach.call ( this ); this.attachClassName ( this._type ); - + /* - * Explorer shows a brief flash of white sometimes. Build cover - * for smoother page transitions when window is loaded and unloaded. + * Explorer shows a brief flash of white sometimes. Build cover + * for smoother page transitions when window is loaded and unloaded. */ if ( Client.isExplorer == true ) { this._coverBinding = this.add ( - CoverBinding.newInstance ( this.bindingDocument ) + CoverBinding.newInstance ( this.bindingDocument ) ); this._coverBinding.attach (); } @@ -218,7 +227,7 @@ ViewBinding.prototype.onBindingAttach = function () { { this.setProperty("position", DockBinding.START); } - + /* * Attach window. */ @@ -230,51 +239,51 @@ ViewBinding.prototype.onBindingAttach = function () { * @return */ ViewBinding.prototype.updatePositionDimension = function () { - + var snap = this._snapBinding; - + /* - * For some reason, IE enters here when the user has - * no perspectives. This should be considered a hack. - * TODO: Mozilla is allowed to pass because he doesn't - * fail. IE is blocked. But now the difference is that + * For some reason, IE enters here when the user has + * no perspectives. This should be considered a hack. + * TODO: Mozilla is allowed to pass because he doesn't + * fail. IE is blocked. But now the difference is that * IE is allowed to see the Start-screen. Synch this! */ var isAbort = !System.hasActivePerspectives && Client.isExplorer; - + if ( this.isFreeFloating == true && !isAbort ) { if ( snap.isVisible == true ) { if ( snap.isAttached == true ) { - + var position = snap.boxObject.getGlobalPosition (); var dimension = snap.boxObject.getDimension (); - + /* * Update position. */ if ( !Point.isEqual ( position, this._lastknownposition )) { - + this.setPosition ( position ); this._lastknownposition = position; } - - + + /* * Update dimension. */ if ( !Dimension.isEqual ( dimension, this._lastknowndimension )) { - + this.setDimension ( dimension ); this._lastknowndimension = dimension; - + var result = dimension.h - ViewBinding.VERTICAL_ADJUST; result = result < 0 ? 0 : result; - + this.windowBinding.getBindingElement ().style.height = new String ( result ) + "px"; this.windowBinding.reflex (); - + } else { - + throw "Could not snap to unattached binding!"; } } @@ -286,11 +295,11 @@ ViewBinding.prototype.updatePositionDimension = function () { * @overloads {Binding#onBindingDispose} */ ViewBinding.prototype.onBindingDispose = function () { - + ViewBinding.superclass.onBindingDispose.call ( this ); - + /* - * Cancel the serverside flow in case dispose + * Cancel the serverside flow in case dispose * was instantiated by a clientside action. */ if ( this._viewDefinition != null ) { @@ -299,16 +308,16 @@ ViewBinding.prototype.onBindingDispose = function () { FlowControllerService.CancelFlow ( flowhandle ); } } - + if ( this._viewDefinition != null ) { - + var handle = this._viewDefinition.handle; EventBroadcaster.broadcast ( BroadcastMessages.VIEW_CLOSED, handle ); this.logger.fine ( "ViewBinding closed: \"" + handle + "\"" ); /* - * Odd fact: Mozilla will evaluate this twice unless - * wrapped in a timeout. You can also make it evaluate it - * once by alerting just bofore, but that wont help us. + * Odd fact: Mozilla will evaluate this twice unless + * wrapped in a timeout. You can also make it evaluate it + * once by alerting just bofore, but that wont help us. * var handle = this._viewDefinition.handle; setTimeout ( function () { @@ -317,7 +326,7 @@ ViewBinding.prototype.onBindingDispose = function () { }, 0 ); */ } - + this.dispatchAction ( ViewBinding.ACTION_CLOSED ); } @@ -326,7 +335,7 @@ ViewBinding.prototype.onBindingDispose = function () { * @param {string} type */ ViewBinding.prototype.setType = function ( type ) { - + this._type = type; } @@ -335,16 +344,16 @@ ViewBinding.prototype.setType = function ( type ) { * @return {string} */ ViewBinding.prototype.getType = function () { - + return this._type; } /** * Get handle. Technically, handle of the associated ViewDefinition. - * @return {string} + * @return {string} */ ViewBinding.prototype.getHandle = function () { - + var result = null; if ( this._viewDefinition != null ) { result = this._viewDefinition.handle; @@ -354,7 +363,7 @@ ViewBinding.prototype.getHandle = function () { /** * TODO: update this method description. - * Initialize when associated tab is selected. + * Initialize when associated tab is selected. * This method is called by the {@link StageBinding}. * SNAPTARGET views initialize when snapToBinding is invoked!!! */ @@ -362,8 +371,8 @@ ViewBinding.prototype.initialize = function () { if ( !this._isViewBindingInitialized ) { this._isViewBindingInitialized = true; - this.windowBinding.setURL ( - this._viewDefinition.url + this.windowBinding.setURL ( + this._viewDefinition.url ); EventBroadcaster.broadcast ( BroadcastMessages.VIEW_OPENING, this.getHandle ()); } else { @@ -376,7 +385,7 @@ ViewBinding.prototype.initialize = function () { * @param {ViewDefinition} definition */ ViewBinding.prototype.setDefinition = function ( definition ) { - + this._viewDefinition = definition; if (definition.position == DockBinding.MAIN) { this.subscribe ( BroadcastMessages.CLOSE_VIEWS ); @@ -388,26 +397,26 @@ ViewBinding.prototype.setDefinition = function ( definition ) { * @return {ViewDefinition} */ ViewBinding.prototype.getDefinition = function () { - + return this._viewDefinition; } /** - * Implements (@link IActionListener} + * Implements (@link IActionListener} * @param {Action} action */ ViewBinding.prototype.handleAction = function ( action ) { ViewBinding.superclass.handleAction.call ( this, action ); - + var binding = action.target; switch ( action.type ) { - + case RootBinding.ACTION_PHASE_1 : case RootBinding.ACTION_PHASE_2 : case RootBinding.ACTION_PHASE_3 : - + /* * Activate the root binding? */ @@ -416,14 +425,14 @@ ViewBinding.prototype.handleAction = function ( action ) { binding.onActivate (); } } - + /* - * Consume these events. They are + * Consume these events. They are * intended for ViewBinding content. */ action.consume (); break; - + case Binding.ACTION_DIMENSIONCHANGED : if ( this.isFreeFloating == true ) { if ( binding == this._snapBinding ) { @@ -434,7 +443,7 @@ ViewBinding.prototype.handleAction = function ( action ) { } } break; - + case Binding.ACTION_VISIBILITYCHANGED : // see {DockBinding#interceptDisplayChange} if ( this.isFreeFloating == true ) { if ( binding == this._snapBinding ) { @@ -447,19 +456,19 @@ ViewBinding.prototype.handleAction = function ( action ) { } // can we consume this? break; - + case WindowBinding.ACTION_LOADED : case WindowBinding.ACTION_ONLOAD : - + if ( binding.getContentWindow ().isPostBackDocument ) { // @see {MessageQueue#openView} if ( action.type == WindowBinding.ACTION_ONLOAD ) { var arg = this._viewDefinition.argument; if ( arg != null && arg.list != null && arg.url != null ) { - binding.post ( arg.list, arg.url ); + binding.post ( arg.list, arg.url ); arg.list = null; arg.url = null; - // note that this prevents a repeat! Otherwise, + // note that this prevents a repeat! Otherwise, // the previewwindow would fire this stuff... // TODO: hack this elsehow... } @@ -468,8 +477,8 @@ ViewBinding.prototype.handleAction = function ( action ) { if ( Client.isExplorer == true ) { if ( binding == this.windowBinding ) { var self = this; - DOMEvents.addEventListener ( - binding.getContentWindow (), + DOMEvents.addEventListener ( + binding.getContentWindow (), DOMEvents.UNLOAD, { // beforeunload invoked at random in exploder! handleEvent : function ( e ) { if ( Binding.exists ( self._coverBinding ) == true ) { @@ -485,9 +494,9 @@ ViewBinding.prototype.handleAction = function ( action ) { } } } - + /* - * Show non-framework document now. Otherwise + * Show non-framework document now. Otherwise * we wait for the PageBinding to initialize. */ if ( action.type == WindowBinding.ACTION_ONLOAD ) { @@ -500,9 +509,9 @@ ViewBinding.prototype.handleAction = function ( action ) { } action.consume (); break; - + case PageBinding.ACTION_ATTACHED : - + // reload scenario - PLEASE REFACTOR! if ( !binding.label && this._viewDefinition.label ) { binding.label = this._viewDefinition.label; @@ -510,10 +519,10 @@ ViewBinding.prototype.handleAction = function ( action ) { if ( !binding.image && this._viewDefinition.image ) { binding.image = this._viewDefinition.image; } - + /* - * Pin a reference to the currently mounted PageBinding - * and set the page argument. Notice that all loaded pages + * Pin a reference to the currently mounted PageBinding + * and set the page argument. Notice that all loaded pages * get served the same argument (although not subpages). */ if ( binding.bindingWindow == this.getContentWindow ()) { @@ -522,7 +531,7 @@ ViewBinding.prototype.handleAction = function ( action ) { } case PageBinding.ACTION_INITIALIZED : - + /* * Show myself when the root page initializes. */ @@ -536,19 +545,19 @@ ViewBinding.prototype.handleAction = function ( action ) { } // dont consume - DockBinding and StageDialogBinding are listening! break; - + case Binding.ACTION_DISPOSED : - + if ( this.isFreeFloating && binding == this._snapBinding ) { this.removeActionListener ( Binding.ACTION_DISPOSED ); this.dispose (); action.consume (); } break; - + /* - * + * */ case WizardPageBinding.ACTION_NAVIGATE_NEXT : case WizardPageBinding.ACTION_NAVIGATE_PREVIOUS : @@ -556,16 +565,16 @@ ViewBinding.prototype.handleAction = function ( action ) { EventBroadcaster.broadcast ( BroadcastMessages.VIEW_OPENING, this.getHandle ()); action.consume (); break; - + /* - * Detach view from server control. This happens when the server error page - * is shown (since workflow termination will automatically close the view). + * Detach view from server control. This happens when the server error page + * is shown (since workflow termination will automatically close the view). * Detach is done simply by switching the associated {@link ViewDefinition}. * TODO: Something more elegant? */ case ViewBinding.ACTION_DETACH : this.setDefinition ( ViewDefinitions [ "Composite.Management.Null" ]); - ViewBinding._instances.set ( this._viewDefinition.handle, this ); + ViewBinding._instances.set(ViewBinding.normalizeHandle(this._viewDefinition.handle), this); // don't consume - TabPanelBinding is listening (waiting to un-dirty the tab). break; } @@ -573,27 +582,27 @@ ViewBinding.prototype.handleAction = function ( action ) { /** * Implements (@link IBroadcastListener} - * @param {string} broadcast + * @param {string} broadcast * @param {object} arg */ ViewBinding.prototype.handleBroadcast = function ( broadcast, arg ) { - + ViewBinding.superclass.handleBroadcast.call ( this, broadcast, arg ); - + switch ( broadcast ) { - + case BroadcastMessages.CLOSE_VIEW : if ( arg == this._viewDefinition.handle ) { this.dispatchAction ( ViewBinding.ACTION_ONCLOSE ); } break; - + case BroadcastMessages.CLOSE_VIEWS : if (this._viewDefinition.position == DockBinding.MAIN) { this.dispatchAction ( ViewBinding.ACTION_ONCLOSE_FORCE ); } break; - + case BroadcastMessages.APPLICATION_SHUTDOWN : this.dispose (); // this should happen automatically, but no... break; @@ -604,7 +613,7 @@ ViewBinding.prototype.handleBroadcast = function ( broadcast, arg ) { * On loading completed. */ ViewBinding.prototype._onLoadingCompleted = function () { - + if ( !this._isLoaded ) { this._open (); this._isLoaded = true; @@ -616,37 +625,37 @@ ViewBinding.prototype._onLoadingCompleted = function () { * @see {ViewBinding#onBindingDispose} */ ViewBinding.prototype._open = function () { - - ViewBinding._instances.set ( this._viewDefinition.handle, this ); + + ViewBinding._instances.set(ViewBinding.normalizeHandle(this._viewDefinition.handle), this); this.dispatchAction ( ViewBinding.ACTION_LOADED ); EventBroadcaster.broadcast ( BroadcastMessages.VIEW_OPENED, this._viewDefinition.handle ); this.show (); - + this.logger.fine ( "ViewBinding opened: \"" + this._viewDefinition.handle + "\"" ); } /** - * This method is invoked by the StageBinding when an already open ViewBinding - * gets re-opened. The associated ViewDefinition argument is yet again relayed + * This method is invoked by the StageBinding when an already open ViewBinding + * gets re-opened. The associated ViewDefinition argument is yet again relayed * to the contained PageBinding (if changed since last). * @see {StageBinding#_view} */ ViewBinding.prototype.update = function () { - + this.dispatchAction ( Binding.ACTION_ACTIVATED ); this._injectPageArgument (); } /** - * Relay ViewDefinition argument to contained PageBinding. + * Relay ViewDefinition argument to contained PageBinding. */ ViewBinding.prototype._injectPageArgument = function () { - + var page = this._pageBinding; var def = this._viewDefinition; - + if ( page != null ) { - + var argument = def.argument; if ( argument != null ) { page.setPageArgument ( argument ); @@ -668,15 +677,15 @@ ViewBinding.prototype._injectPageArgument = function () { * @param {Crawler} crawler */ ViewBinding.prototype.handleCrawler = function ( crawler ) { - + ViewBinding.superclass.handleCrawler.call ( this, crawler ); - + switch ( crawler.type ) { - + /* - * Redirect descending crawlers back to DockPanelBinding. - * Otherwise the crawler would continue straight to the - * next view (because it is now crawling the viewset). + * Redirect descending crawlers back to DockPanelBinding. + * Otherwise the crawler would continue straight to the + * next view (because it is now crawling the viewset). */ case NodeCrawler.TYPE_DESCENDING : if ( this.isFreeFloating == true ) { @@ -687,12 +696,12 @@ ViewBinding.prototype.handleCrawler = function ( crawler ) { } } break; - + /* * Relay ascending crawlers to DockPanelBinding. */ case NodeCrawler.TYPE_ASCENDING : - + if ( this.isFreeFloating == true ) { crawler.nextNode = this._snapBinding.bindingElement; } @@ -705,10 +714,10 @@ ViewBinding.prototype.handleCrawler = function ( crawler ) { * @overwrites {Binding#show} */ ViewBinding.prototype.show = function () { - + if ( !this.isVisible ) { if (this.isFreeFloating == true) { - + //Workaround for #4508 if (Client.isWebKit) this.bindingElement.style.display = ""; @@ -729,18 +738,18 @@ ViewBinding.prototype.show = function () { * @overwrites {Binding#hide} */ ViewBinding.prototype.hide = function () { - + if ( this.isVisible == true ) { if ( this.isFreeFloating == true ) { if ( this.windowBinding ) { this.windowBinding.getBindingElement ().style.position = "absolute"; } this.bindingElement.style.top = "-10000px"; - + //Workaround for #4508 if (Client.isWebKit) this.bindingElement.style.display = "none"; - + this.isVisible = false; } else { ViewBinding.superclass.hide.call ( this ); @@ -750,28 +759,28 @@ ViewBinding.prototype.hide = function () { /** * @param {Point} point - */ + */ ViewBinding.prototype.setPosition = function ( point ) { point.x += ViewBinding.HORIZONTAL_ADJUST; - + this.bindingElement.style.left = point.x + "px"; this.bindingElement.style.top = point.y + "px"; } /** * @param {Dimension} dimension - */ + */ ViewBinding.prototype.setDimension = function ( dimension ) { dimension.h -= ViewBinding.VERTICAL_ADJUST; dimension.w -= ViewBinding.HORIZONTAL_ADJUST; - + /* * Something hardcoded here... */ dimension.w -= 1; - + if ( dimension.h < 0 ) { // not sure why this happens... dimension.h = 0; } @@ -787,16 +796,16 @@ ViewBinding.prototype.setDimension = function ( dimension ) { * @param {Binding} binding */ ViewBinding.prototype.snapToBinding = function (binding, floating) { - - // Disable standard flexbox behavior. + + // Disable standard flexbox behavior. // TODO: enable for floating docks???????????????????????????????????????????? this.isFlexBoxBehavior = false; - // Listen for these events instead... + // Listen for these events instead... binding.addActionListener ( Binding.ACTION_DIMENSIONCHANGED, this ); binding.addActionListener ( Binding.ACTION_VISIBILITYCHANGED, this ); binding.addActionListener ( Binding.ACTION_DISPOSED, this ); - + // Unregister any previous snap target. if ( this._snapBinding ) { this._snapBinding.removeActionListener ( Binding.ACTION_DIMENSIONCHANGED, this ); @@ -807,7 +816,7 @@ ViewBinding.prototype.snapToBinding = function (binding, floating) { this._snapBinding = binding; this._snapBinding.viewBinding = this; this.isFreeFloating = floating !== false; // dafault is true - + // Initialize when first shown, creating and loading the WindowBinding if ( !this._isViewBindingInitialized ) { this.initialize (); @@ -815,8 +824,8 @@ ViewBinding.prototype.snapToBinding = function (binding, floating) { } /** - * Very special setup: Migrate all Actions to the snaptarget - * binding! Please note that this breaks the convention of + * Very special setup: Migrate all Actions to the snaptarget + * binding! Please note that this breaks the convention of * Actions travelling upwards in the structural hierarchy. * @overwrites {Binding#getMigrationParent}. */ @@ -832,42 +841,42 @@ ViewBinding.prototype.getMigrationParent = function () { } /** - * Get the window object hosted by this ViewBinding. - * During startup, this may be undefined. + * Get the window object hosted by this ViewBinding. + * During startup, this may be undefined. * @return {DOMDocumentView} */ ViewBinding.prototype.getContentWindow = function () { - + return this.windowBinding.getContentWindow (); } /** - * Get the document object hosted by this ViewBinding. - * During startup, this may be undefined. + * Get the document object hosted by this ViewBinding. + * During startup, this may be undefined. * @return {DOMDocument} */ ViewBinding.prototype.getContentDocument = function () { - + return this.windowBinding.getContentDocument (); } /** - * Get the {@link RootBinding} hosted by this ViewBinding. - * During startup, this may be undefined. + * Get the {@link RootBinding} hosted by this ViewBinding. + * During startup, this may be undefined. * @return {RootBinding} */ ViewBinding.prototype.getRootBinding = function () { - + return this.windowBinding.getRootBinding (); } /** - * Get the {@link RootBinding} hosted by this ViewBinding. - * During startup, this may be undefined. + * Get the {@link RootBinding} hosted by this ViewBinding. + * During startup, this may be undefined. * @return {PageBinding} */ ViewBinding.prototype.getPageBinding = function () { - + return this._pageBinding; } @@ -876,7 +885,7 @@ ViewBinding.prototype.getPageBinding = function () { * @param {boolean} isClearCache Clear the cache in Prism. */ ViewBinding.prototype.reload = function ( isClearCache ) { - + this._isLoaded = false; this.windowBinding.reload ( isClearCache ); EventBroadcaster.broadcast ( BroadcastMessages.VIEW_OPENING, this.getHandle ()); @@ -887,7 +896,7 @@ ViewBinding.prototype.reload = function ( isClearCache ) { * @see {DockBinding#saveContainedEditor} */ ViewBinding.prototype.saveContainedEditor = function () { - + var isSuccess = false; var page = this._pageBinding; if ( page != null && page instanceof EditorPageBinding ) { @@ -902,12 +911,12 @@ ViewBinding.prototype.saveContainedEditor = function () { } /** - * Invoked be ancestor {IActivatable} when activated. - * Invokes similar method on root binding, igniting a + * Invoked be ancestor {IActivatable} when activated. + * Invokes similar method on root binding, igniting a * chain reaction on all descendant root bindings. */ ViewBinding.prototype.onActivate = function () { - + if ( !this.isActivated ) { this.isActivated = true; var root = this.getRootBinding (); @@ -918,11 +927,11 @@ ViewBinding.prototype.onActivate = function () { } /** - * Invoked be ancestor {IActivatable} when deactivated. + * Invoked be ancestor {IActivatable} when deactivated. * See comment above. */ ViewBinding.prototype.onDeactivate = function () { - + if ( this.isActivated == true ) { this.isActivated = false; var root = this.getRootBinding (); From 60ad8b0f097468e820c3aa7ccee76de2bb3baea7 Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Wed, 31 Aug 2016 09:03:10 +0300 Subject: [PATCH 03/22] Fix #126 The selection moves in both the tree and context menu --- .../scripts/source/top/ui/bindings/popups/PopupBinding.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Website/Composite/scripts/source/top/ui/bindings/popups/PopupBinding.js b/Website/Composite/scripts/source/top/ui/bindings/popups/PopupBinding.js index cd5cdd8704..af2232536f 100644 --- a/Website/Composite/scripts/source/top/ui/bindings/popups/PopupBinding.js +++ b/Website/Composite/scripts/source/top/ui/bindings/popups/PopupBinding.js @@ -467,7 +467,10 @@ PopupBinding.prototype.show = function () { this._makeVisible ( true ); if ( this._bodyBinding instanceof MenuBodyBinding ) { - this._bodyBinding.refreshMenuGroups (); + this._bodyBinding.refreshMenuGroups(); + this._bodyBinding.grabKeyboard(); + this._bodyBinding.bindingElement.tabIndex = "-1"; + this._bodyBinding.bindingElement.focus(); } /** From d8dfc99108f419135323d877a0a2b12dc428059a Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Thu, 20 Oct 2016 01:34:28 +0200 Subject: [PATCH 04/22] "Upload and Extract Zip" action added on website file folders (system perspective, layout perspective). --- .../Composite.Workflows.csproj | 10 + ...ploadAndExtractZipFileWorkflow.Designer.cs | 303 ++++++++++++++++++ .../UploadAndExtractZipFileWorkflow.cs | 169 ++++++++++ .../UploadAndExtractZipFileWorkflow.layout | 139 ++++++++ .../Core/ResourceSystem/LocalizationFiles.cs | 32 +- .../WebsiteFileElementProvider.cs | 51 ++- ...ElementProviderUploadAndExtractZipFile.xml | 21 ++ .../icons/svg/website-upload-zip-file.svg | 8 + ...ugins.WebsiteFileElementProvider.en-us.xml | 20 +- Website/WebSite.csproj | 21 +- 10 files changed, 749 insertions(+), 25 deletions(-) create mode 100644 Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.Designer.cs create mode 100644 Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.cs create mode 100644 Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.layout create mode 100644 Website/Composite/content/forms/Administrative/WebsiteFileElementProviderUploadAndExtractZipFile.xml create mode 100644 Website/Composite/images/icons/svg/website-upload-zip-file.svg diff --git a/Composite.Workflows/Composite.Workflows.csproj b/Composite.Workflows/Composite.Workflows.csproj index bb5e5534d7..6abdd51e9e 100644 --- a/Composite.Workflows/Composite.Workflows.csproj +++ b/Composite.Workflows/Composite.Workflows.csproj @@ -92,6 +92,7 @@ + 3.0 @@ -688,6 +689,12 @@ EditVisualFunctionWorkflow.cs + + Component + + + UploadAndExtractZipFileWorkflow.cs + Component @@ -1208,6 +1215,9 @@ EditVisualFunctionWorkflow.cs + + UploadAndExtractZipFileWorkflow.cs + AddNewWebsiteFileWorkflow.cs diff --git a/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.Designer.cs b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.Designer.cs new file mode 100644 index 0000000000..409550527e --- /dev/null +++ b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.Designer.cs @@ -0,0 +1,303 @@ +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Collections; +using System.Drawing; +using System.Reflection; +using System.Workflow.ComponentModel.Compiler; +using System.Workflow.ComponentModel.Serialization; +using System.Workflow.ComponentModel; +using System.Workflow.ComponentModel.Design; +using System.Workflow.Runtime; +using System.Workflow.Activities; +using System.Workflow.Activities.Rules; + +namespace Composite.Plugins.Elements.ElementProviders.WebsiteFileElementProvider +{ + partial class UploadAndExtractZipFileWorkflow + { + #region Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + [System.Diagnostics.DebuggerNonUserCode] + private void InitializeComponent() + { + this.CanModifyActivities = true; + System.Workflow.Activities.CodeCondition codecondition1 = new System.Workflow.Activities.CodeCondition(); + System.Workflow.Activities.CodeCondition codecondition2 = new System.Workflow.Activities.CodeCondition(); + this.setStateActivity7 = new System.Workflow.Activities.SetStateActivity(); + this.setStateActivity4 = new System.Workflow.Activities.SetStateActivity(); + this.closeCurrentViewActivity1 = new Composite.C1Console.Workflow.Activities.CloseCurrentViewActivity(); + this.setStateActivity5 = new System.Workflow.Activities.SetStateActivity(); + this.setStateActivity3 = new System.Workflow.Activities.SetStateActivity(); + this.codeActivity3 = new System.Workflow.Activities.CodeActivity(); + this.ifElseBranchActivity4 = new System.Workflow.Activities.IfElseBranchActivity(); + this.ifElseBranchActivity3 = new System.Workflow.Activities.IfElseBranchActivity(); + this.ifElseBranchActivity2 = new System.Workflow.Activities.IfElseBranchActivity(); + this.ifElseBranchActivity1 = new System.Workflow.Activities.IfElseBranchActivity(); + this.ifElseActivity2 = new System.Workflow.Activities.IfElseActivity(); + this.codeActivity2 = new System.Workflow.Activities.CodeActivity(); + this.setStateActivity6 = new System.Workflow.Activities.SetStateActivity(); + this.cancelHandleExternalEventActivity2 = new Composite.C1Console.Workflow.Activities.CancelHandleExternalEventActivity(); + this.ifElseActivity1 = new System.Workflow.Activities.IfElseActivity(); + this.finishHandleExternalEventActivity1 = new Composite.C1Console.Workflow.Activities.FinishHandleExternalEventActivity(); + this.wizzardFormActivity1 = new Composite.C1Console.Workflow.Activities.DataDialogFormActivity(); + this.setStateActivity2 = new System.Workflow.Activities.SetStateActivity(); + this.codeActivity1 = new System.Workflow.Activities.CodeActivity(); + this.setStateActivity1 = new System.Workflow.Activities.SetStateActivity(); + this.cancelHandleExternalEventActivity1 = new Composite.C1Console.Workflow.Activities.CancelHandleExternalEventActivity(); + this.finalizeStateInitializationActivity = new System.Workflow.Activities.StateInitializationActivity(); + this.cancelEventDrivenActivity = new System.Workflow.Activities.EventDrivenActivity(); + this.finishEventDrivenActivity = new System.Workflow.Activities.EventDrivenActivity(); + this.selectZipStateInitializationActivity = new System.Workflow.Activities.StateInitializationActivity(); + this.initialStateInitializationActivity = new System.Workflow.Activities.StateInitializationActivity(); + this.finalStateActivity = new System.Workflow.Activities.StateActivity(); + this.eventDrivenActivity1 = new System.Workflow.Activities.EventDrivenActivity(); + this.finalizeStateActivity = new System.Workflow.Activities.StateActivity(); + this.selectZipFileStateActivity = new System.Workflow.Activities.StateActivity(); + this.initialState = new System.Workflow.Activities.StateActivity(); + // + // setStateActivity7 + // + this.setStateActivity7.Name = "setStateActivity7"; + this.setStateActivity7.TargetStateName = "selectZipFileStateActivity"; + // + // setStateActivity4 + // + this.setStateActivity4.Name = "setStateActivity4"; + this.setStateActivity4.TargetStateName = "finalStateActivity"; + // + // closeCurrentViewActivity1 + // + this.closeCurrentViewActivity1.Name = "closeCurrentViewActivity1"; + // + // setStateActivity5 + // + this.setStateActivity5.Name = "setStateActivity5"; + this.setStateActivity5.TargetStateName = "selectZipFileStateActivity"; + // + // setStateActivity3 + // + this.setStateActivity3.Name = "setStateActivity3"; + this.setStateActivity3.TargetStateName = "finalizeStateActivity"; + // + // codeActivity3 + // + this.codeActivity3.Name = "codeActivity3"; + this.codeActivity3.ExecuteCode += new System.EventHandler(this.HandleFinish_ExecuteCode); + // + // ifElseBranchActivity4 + // + this.ifElseBranchActivity4.Activities.Add(this.setStateActivity7); + this.ifElseBranchActivity4.Name = "ifElseBranchActivity4"; + // + // ifElseBranchActivity3 + // + this.ifElseBranchActivity3.Activities.Add(this.closeCurrentViewActivity1); + this.ifElseBranchActivity3.Activities.Add(this.setStateActivity4); + codecondition1.Condition += new System.EventHandler(this.ZipWasUploaded); + this.ifElseBranchActivity3.Condition = codecondition1; + this.ifElseBranchActivity3.Name = "ifElseBranchActivity3"; + // + // ifElseBranchActivity2 + // + this.ifElseBranchActivity2.Activities.Add(this.setStateActivity5); + this.ifElseBranchActivity2.Name = "ifElseBranchActivity2"; + // + // ifElseBranchActivity1 + // + this.ifElseBranchActivity1.Activities.Add(this.codeActivity3); + this.ifElseBranchActivity1.Activities.Add(this.setStateActivity3); + codecondition2.Condition += new System.EventHandler(this.HasUserUploaded); + this.ifElseBranchActivity1.Condition = codecondition2; + this.ifElseBranchActivity1.Name = "ifElseBranchActivity1"; + // + // ifElseActivity2 + // + this.ifElseActivity2.Activities.Add(this.ifElseBranchActivity3); + this.ifElseActivity2.Activities.Add(this.ifElseBranchActivity4); + this.ifElseActivity2.Name = "ifElseActivity2"; + // + // codeActivity2 + // + this.codeActivity2.Name = "codeActivity2"; + this.codeActivity2.ExecuteCode += new System.EventHandler(this.FinalizeCodeActivity_ExecuteCode); + // + // setStateActivity6 + // + this.setStateActivity6.Name = "setStateActivity6"; + this.setStateActivity6.TargetStateName = "finalStateActivity"; + // + // cancelHandleExternalEventActivity2 + // + this.cancelHandleExternalEventActivity2.EventName = "Cancel"; + this.cancelHandleExternalEventActivity2.InterfaceType = typeof(Composite.C1Console.Workflow.IFormsWorkflowEventService); + this.cancelHandleExternalEventActivity2.Name = "cancelHandleExternalEventActivity2"; + // + // ifElseActivity1 + // + this.ifElseActivity1.Activities.Add(this.ifElseBranchActivity1); + this.ifElseActivity1.Activities.Add(this.ifElseBranchActivity2); + this.ifElseActivity1.Name = "ifElseActivity1"; + // + // finishHandleExternalEventActivity1 + // + this.finishHandleExternalEventActivity1.EventName = "Finish"; + this.finishHandleExternalEventActivity1.InterfaceType = typeof(Composite.C1Console.Workflow.IFormsWorkflowEventService); + this.finishHandleExternalEventActivity1.Name = "finishHandleExternalEventActivity1"; + // + // wizzardFormActivity1 + // + this.wizzardFormActivity1.ContainerLabel = null; + this.wizzardFormActivity1.FormDefinitionFileName = "/Administrative/WebsiteFileElementProviderUploadAndExtractZipFile.xml"; + this.wizzardFormActivity1.Name = "wizzardFormActivity1"; + // + // setStateActivity2 + // + this.setStateActivity2.Name = "setStateActivity2"; + this.setStateActivity2.TargetStateName = "selectZipFileStateActivity"; + // + // codeActivity1 + // + this.codeActivity1.Name = "codeActivity1"; + this.codeActivity1.ExecuteCode += new System.EventHandler(this.InitializeCodeActivity_ExecuteCode); + // + // setStateActivity1 + // + this.setStateActivity1.Name = "setStateActivity1"; + this.setStateActivity1.TargetStateName = "finalStateActivity"; + // + // cancelHandleExternalEventActivity1 + // + this.cancelHandleExternalEventActivity1.EventName = "Cancel"; + this.cancelHandleExternalEventActivity1.InterfaceType = typeof(Composite.C1Console.Workflow.IFormsWorkflowEventService); + this.cancelHandleExternalEventActivity1.Name = "cancelHandleExternalEventActivity1"; + // + // finalizeStateInitializationActivity + // + this.finalizeStateInitializationActivity.Activities.Add(this.codeActivity2); + this.finalizeStateInitializationActivity.Activities.Add(this.ifElseActivity2); + this.finalizeStateInitializationActivity.Name = "finalizeStateInitializationActivity"; + // + // cancelEventDrivenActivity + // + this.cancelEventDrivenActivity.Activities.Add(this.cancelHandleExternalEventActivity2); + this.cancelEventDrivenActivity.Activities.Add(this.setStateActivity6); + this.cancelEventDrivenActivity.Name = "cancelEventDrivenActivity"; + // + // finishEventDrivenActivity + // + this.finishEventDrivenActivity.Activities.Add(this.finishHandleExternalEventActivity1); + this.finishEventDrivenActivity.Activities.Add(this.ifElseActivity1); + this.finishEventDrivenActivity.Name = "finishEventDrivenActivity"; + // + // selectZipStateInitializationActivity + // + this.selectZipStateInitializationActivity.Activities.Add(this.wizzardFormActivity1); + this.selectZipStateInitializationActivity.Name = "selectZipStateInitializationActivity"; + // + // initialStateInitializationActivity + // + this.initialStateInitializationActivity.Activities.Add(this.codeActivity1); + this.initialStateInitializationActivity.Activities.Add(this.setStateActivity2); + this.initialStateInitializationActivity.Name = "initialStateInitializationActivity"; + // + // finalStateActivity + // + this.finalStateActivity.Name = "finalStateActivity"; + // + // eventDrivenActivity1 + // + this.eventDrivenActivity1.Activities.Add(this.cancelHandleExternalEventActivity1); + this.eventDrivenActivity1.Activities.Add(this.setStateActivity1); + this.eventDrivenActivity1.Name = "eventDrivenActivity1"; + // + // finalizeStateActivity + // + this.finalizeStateActivity.Activities.Add(this.finalizeStateInitializationActivity); + this.finalizeStateActivity.Name = "finalizeStateActivity"; + // + // selectZipFileStateActivity + // + this.selectZipFileStateActivity.Activities.Add(this.selectZipStateInitializationActivity); + this.selectZipFileStateActivity.Activities.Add(this.finishEventDrivenActivity); + this.selectZipFileStateActivity.Activities.Add(this.cancelEventDrivenActivity); + this.selectZipFileStateActivity.Name = "selectZipFileStateActivity"; + // + // initialState + // + this.initialState.Activities.Add(this.initialStateInitializationActivity); + this.initialState.Name = "initialState"; + // + // UploadAndExtractZipFileWorkflow + // + this.Activities.Add(this.initialState); + this.Activities.Add(this.selectZipFileStateActivity); + this.Activities.Add(this.finalizeStateActivity); + this.Activities.Add(this.eventDrivenActivity1); + this.Activities.Add(this.finalStateActivity); + this.CompletedStateName = "finalStateActivity"; + this.DynamicUpdateCondition = null; + this.InitialStateName = "initialState"; + this.Name = "UploadAndExtractZipFileWorkflow"; + this.CanModifyActivities = false; + + } + + + + + + + + + + + + + + + + + + + + + #endregion + + private StateActivity selectZipFileStateActivity; + private StateActivity finalizeStateActivity; + private EventDrivenActivity eventDrivenActivity1; + private StateInitializationActivity initialStateInitializationActivity; + private StateActivity finalStateActivity; + private CodeActivity codeActivity1; + private StateInitializationActivity finalizeStateInitializationActivity; + private StateInitializationActivity selectZipStateInitializationActivity; + private C1Console.Workflow.Activities.DataDialogFormActivity wizzardFormActivity1; + private SetStateActivity setStateActivity2; + private SetStateActivity setStateActivity1; + private C1Console.Workflow.Activities.CancelHandleExternalEventActivity cancelHandleExternalEventActivity1; + private SetStateActivity setStateActivity4; + private CodeActivity codeActivity2; + private SetStateActivity setStateActivity3; + private CodeActivity codeActivity3; + private C1Console.Workflow.Activities.FinishHandleExternalEventActivity finishHandleExternalEventActivity1; + private EventDrivenActivity finishEventDrivenActivity; + private SetStateActivity setStateActivity5; + private IfElseBranchActivity ifElseBranchActivity2; + private IfElseBranchActivity ifElseBranchActivity1; + private IfElseActivity ifElseActivity1; + private C1Console.Workflow.Activities.CloseCurrentViewActivity closeCurrentViewActivity1; + private SetStateActivity setStateActivity6; + private C1Console.Workflow.Activities.CancelHandleExternalEventActivity cancelHandleExternalEventActivity2; + private EventDrivenActivity cancelEventDrivenActivity; + private IfElseBranchActivity ifElseBranchActivity4; + private IfElseBranchActivity ifElseBranchActivity3; + private IfElseActivity ifElseActivity2; + private SetStateActivity setStateActivity7; + private StateActivity initialState; + } +} diff --git a/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.cs b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.cs new file mode 100644 index 0000000000..d104d05871 --- /dev/null +++ b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.cs @@ -0,0 +1,169 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Workflow.Activities; +using Composite.C1Console.Actions; +using Composite.C1Console.Events; +using Composite.C1Console.Forms.CoreUiControls; +using Composite.C1Console.Workflow; +using Composite.C1Console.Workflow.Activities; +using Composite.Core; +using Composite.Core.IO; + +using Texts = Composite.Core.ResourceSystem.LocalizationFiles.Composite_Plugins_WebsiteFileElementProvider; + +namespace Composite.Plugins.Elements.ElementProviders.WebsiteFileElementProvider +{ + [AllowPersistingWorkflow(WorkflowPersistingType.Never)] + public sealed partial class UploadAndExtractZipFileWorkflow : FormsWorkflow + { + [NonSerialized] + bool _zipHasBeenUploaded = false; + + public UploadAndExtractZipFileWorkflow() + { + InitializeComponent(); + } + + + + private void InitializeCodeActivity_ExecuteCode(object sender, EventArgs e) + { + FormsWorkflow workflow = this.GetRoot(); + + string parentFolderPath; + + if (this.EntityToken is WebsiteFileElementProviderRootEntityToken) + { + parentFolderPath = PathUtil.Resolve("~/"); + } + else + { + var token = (WebsiteFileElementProviderEntityToken)this.EntityToken; + parentFolderPath = token.Path; + } + + UploadedFile file = new UploadedFile(); + + workflow.Bindings.Add("UploadedFile", file); + workflow.Bindings.Add("OverwriteExisting", false); + workflow.Bindings.Add("ParentFolderPath", parentFolderPath); + } + + + + private void HandleFinish_ExecuteCode(object sender, EventArgs e) + { + UploadedFile uploadedFile = this.GetBinding("UploadedFile"); + bool overwrite = this.GetBinding("OverwriteExisting"); + string parentFolderPath = this.GetBinding("ParentFolderPath"); + + if (uploadedFile.HasFile) + { + using (System.IO.Stream readStream = uploadedFile.FileStream) + { + ZipArchive zipArchive; + + try + { + zipArchive = new ZipArchive(readStream); + } + catch (Exception) + { + ShowUploadError(Texts.UploadAndExtractZipFile_NotZip); + return; + } + + try + { + foreach (var entry in zipArchive.Entries) + { + string fullPath = Path.Combine(parentFolderPath, entry.FullName); + if (File.Exists(fullPath)) + { + string websiteFilePath = PathUtil.GetWebsitePath(fullPath); + + if (!overwrite) + { + ShowUploadError(Texts.UploadAndExtractZipFile_FileExistsError(websiteFilePath)); + return; + } + + var fileInfo = new FileInfo(fullPath); + + if (fileInfo.IsReadOnly) + { + ShowUploadError(Texts.UploadAndExtractZipFile_ExistingFileReadOnly(websiteFilePath)); + return; + } + } + } + + foreach (var entry in zipArchive.Entries.Where(f => !string.IsNullOrWhiteSpace(f.Name))) + { + using (var zipStream = entry.Open()) + { + string fullPath = Path.Combine(parentFolderPath, entry.FullName); + + DirectoryUtils.EnsurePath(fullPath); + + using (var newFile = File.Create(fullPath, 4096)) + { + zipStream.CopyTo(newFile); + } + } + } + + _zipHasBeenUploaded = true; + } + catch (Exception ex) + { + Log.LogError(nameof(UploadAndExtractZipFileWorkflow), ex); + ShowUploadError(Texts.UploadAndExtractZipFile_UnexpectedError); + } + } + } + } + + + + private void ZipWasUploaded(object sender, ConditionalEventArgs e) + { + e.Result = _zipHasBeenUploaded; + } + + + + private void FinalizeCodeActivity_ExecuteCode(object sender, EventArgs e) + { + AddNewTreeRefresher addNewTreeRefresher = this.CreateAddNewTreeRefresher(this.EntityToken); + + + addNewTreeRefresher.PostRefreshMesseges(this.EntityToken); + } + + + + private void HasUserUploaded(object sender, System.Workflow.Activities.ConditionalEventArgs e) + { + UploadedFile uploadedFile = this.GetBinding("UploadedFile"); + + if (!uploadedFile.HasFile) + { + ShowUploadError(Texts.UploadAndExtractZipFile_FileNotUploaded); + e.Result = false; + return; + } + + e.Result = true; + } + + private void ShowUploadError(string message) + { + this.ShowMessage(DialogType.Error, + Texts.UploadAndExtractZipFile_ErrorDialogLabel, + message); + } + } +} diff --git a/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.layout b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.layout new file mode 100644 index 0000000000..a1be667050 --- /dev/null +++ b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/UploadAndExtractZipFileWorkflow.layout @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Composite/Core/ResourceSystem/LocalizationFiles.cs b/Composite/Core/ResourceSystem/LocalizationFiles.cs index 1314de92df..70617527f7 100644 --- a/Composite/Core/ResourceSystem/LocalizationFiles.cs +++ b/Composite/Core/ResourceSystem/LocalizationFiles.cs @@ -1301,7 +1301,7 @@ public static class Composite_Management { public static string UserElementProvider_UserLoginIsAlreadyUsed=>T("UserElementProvider.UserLoginIsAlreadyUsed"); ///"Add Datafolder" public static string AssociatedDataElementProviderHelper_AddDataFolderTypeLabel=>T("AssociatedDataElementProviderHelper.AddDataFolderTypeLabel"); -///"Add datafolder" +///"Add Datafolder" public static string AssociatedDataElementProviderHelper_AddDataFolderTypeToolTip=>T("AssociatedDataElementProviderHelper.AddDataFolderTypeToolTip"); ///"Add Data" public static string AssociatedDataElementProviderHelper_AddAssociatedDataLabel=>T("AssociatedDataElementProviderHelper.AddAssociatedDataLabel"); @@ -4876,7 +4876,7 @@ public static class Composite_Plugins_StandardFunctions { public static string Composite_Web_Html_Template_CommonMetaTags_param_Designer_help=>T("Composite.Web.Html.Template.CommonMetaTags.param.Designer.help"); ///"Show generator" public static string Composite_Web_Html_Template_CommonMetaTags_param_ShowGenerator_label=>T("Composite.Web.Html.Template.CommonMetaTags.param.ShowGenerator.label"); -///"Show the world you support Orckestra CMS - free open source!" +///"Show the world you support Orckestra CMS Foundation - free open source!" public static string Composite_Web_Html_Template_CommonMetaTags_param_ShowGenerator_help=>T("Composite.Web.Html.Template.CommonMetaTags.param.ShowGenerator.help"); ///"Appends a lang='(language code)' attribute the the parent element, reflecting the language of the current page. You can put this just below the <html /> tag." public static string Composite_Web_Html_Template_LangAttribute_description=>T("Composite.Web.Html.Template.LangAttribute.description"); @@ -6102,6 +6102,34 @@ public static class Composite_Plugins_WebsiteFileElementProvider { public static string UploadFile_Error_WrongTypeTitle=>T("UploadFile.Error.WrongTypeTitle"); ///"Wrong file type" public static string UploadFile_Error_WrongTypeMessage=>T("UploadFile.Error.WrongTypeMessage"); +///"Upload and Extract Zip" +public static string UploadAndExtractZipFileTitle=>T("UploadAndExtractZipFileTitle"); +///"Upload multiple files and folders by providing a Zip file" +public static string UploadAndExtractZipFileToolTip=>T("UploadAndExtractZipFileToolTip"); +///"Upload and Extract Zip File" +public static string UploadAndExtractZipFile_DialogLabel=>T("UploadAndExtractZipFile.DialogLabel"); +///"Zip file" +public static string UploadAndExtractZipFile_FileLabel=>T("UploadAndExtractZipFile.FileLabel"); +///"The file/folder structure of the zip file you select will be extracted and copied to the website" +public static string UploadAndExtractZipFile_FileHelp=>T("UploadAndExtractZipFile.FileHelp"); +///"Overwrite existing" +public static string UploadAndExtractZipFile_OverwriteExistingLabel=>T("UploadAndExtractZipFile.OverwriteExistingLabel"); +///"If you select this option, existing files will be overwritten" +public static string UploadAndExtractZipFile_OverwriteExistingHelp=>T("UploadAndExtractZipFile.OverwriteExistingHelp"); +///"Overwrite existing files" +public static string UploadAndExtractZipFile_OverwriteExistingItemLabel=>T("UploadAndExtractZipFile.OverwriteExistingItemLabel"); +///"File '{0}' exists both in the zip and on the website. Choose to overwrite files to complete this action" +public static string UploadAndExtractZipFile_FileExistsError(object parameter0)=>string.Format(T("UploadAndExtractZipFile.FileExistsError"), parameter0); +///"No file was uploaded" +public static string UploadAndExtractZipFile_FileNotUploaded=>T("UploadAndExtractZipFile.FileNotUploaded"); +///"The uploaded file is not a valid Zip archive" +public static string UploadAndExtractZipFile_NotZip=>T("UploadAndExtractZipFile.NotZip"); +///"Zip upload could not be completed" +public static string UploadAndExtractZipFile_ErrorDialogLabel=>T("UploadAndExtractZipFile.ErrorDialogLabel"); +///"Upload failed unexpectedly. Please see log for details" +public static string UploadAndExtractZipFile_UnexpectedError=>T("UploadAndExtractZipFile.UnexpectedError"); +///"Existing file '{0}' is marked as read only. No files were uploaded" +public static string UploadAndExtractZipFile_ExistingFileReadOnly(object parameter0)=>string.Format(T("UploadAndExtractZipFile.ExistingFileReadOnly"), parameter0); ///"New Folder" public static string AddWebsiteFolderTitle=>T("AddWebsiteFolderTitle"); ///"Add new folder" diff --git a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs index 4ff0dfdc45..ff651966ee 100644 --- a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs +++ b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs @@ -44,6 +44,7 @@ internal sealed class WebsiteFileElementProvider : IHooklessElementProvider, IDa private static ResourceHandle DeleteWebsiteFile { get { return GetIconHandle("website-delete-website-file"); } } private static ResourceHandle EditWebsiteFile { get { return GetIconHandle("website-edit-website-file"); } } private static ResourceHandle UploadWebsiteFile { get { return GetIconHandle("website-upload-website-file"); } } + private static ResourceHandle UploadAndExtractZipFile { get { return GetIconHandle("website-upload-zip-file"); } } private static ResourceHandle DownloadWebsiteFile { get { return GetIconHandle("media-download-file"); } } private static ResourceHandle AddFolderToWhiteList { get { return GetIconHandle("website-add-folder-to-whitelist"); } } private static ResourceHandle RemoveFolderFromWhiteList { get { return GetIconHandle("website-remove-folder-from-whitelist"); } } @@ -56,6 +57,7 @@ internal sealed class WebsiteFileElementProvider : IHooklessElementProvider, IDa private static readonly PermissionType[] _addNewWebsiteFolderPermissionTypes = new PermissionType[] { PermissionType.Add }; private static readonly PermissionType[] _addNewWebsiteFilePermissionTypes = new PermissionType[] { PermissionType.Add }; + private static readonly PermissionType[] _uploadAndExtractZipFileWorkflow = new PermissionType[] { PermissionType.Add }; private static readonly PermissionType[] _deleteWebsiteFolderPermissionTypes = new PermissionType[] { PermissionType.Delete }; private static readonly PermissionType[] _deleteWebsiteFilePermissionTypes = new PermissionType[] { PermissionType.Delete }; private static readonly PermissionType[] _editWebsiteFilePermissionTypes = new PermissionType[] { PermissionType.Edit }; @@ -166,7 +168,29 @@ public IEnumerable GetRoots(SearchToken seachToken) ActionType = ActionType.Add, IsInFolder = false, IsInToolbar = true, - ActionGroup = PrimaryFolderActionGroup + ActionGroup = PrimaryFolderActionGroup, + ActionBundle = "Upload" + } + } + }); + + element.AddAction( + new ElementAction(new ActionHandle(new WorkflowActionToken(WorkflowFacade.GetWorkflowType("Composite.Plugins.Elements.ElementProviders.WebsiteFileElementProvider.UploadAndExtractZipFileWorkflow"), _uploadAndExtractZipFileWorkflow))) + { + VisualData = new ActionVisualizedData + { + Label = StringResourceSystemFacade.GetString("Composite.Plugins.WebsiteFileElementProvider", "UploadAndExtractZipFileTitle"), + ToolTip = StringResourceSystemFacade.GetString("Composite.Plugins.WebsiteFileElementProvider", "UploadAndExtractZipFileToolTip"), + Icon = WebsiteFileElementProvider.UploadAndExtractZipFile, + Disabled = false, + ActivePositions = ElementActionActivePosition.NavigatorTree | ElementActionActivePosition.SelectorTree, + ActionLocation = new ActionLocation + { + ActionType = ActionType.Add, + IsInFolder = false, + IsInToolbar = true, + ActionGroup = PrimaryFolderActionGroup, + ActionBundle = "Upload" } } }); @@ -433,7 +457,30 @@ private IEnumerable GetFolderActions(WebsiteFolder websiteFolder, ActionType = ActionType.Add, IsInFolder = false, IsInToolbar = true, - ActionGroup = PrimaryFolderActionGroup + ActionGroup = PrimaryFolderActionGroup, + ActionBundle = "Upload" + + } + } + }); + + folderActions.Add( + new ElementAction(new ActionHandle(new WorkflowActionToken(WorkflowFacade.GetWorkflowType("Composite.Plugins.Elements.ElementProviders.WebsiteFileElementProvider.UploadAndExtractZipFileWorkflow"), _uploadAndExtractZipFileWorkflow))) + { + VisualData = new ActionVisualizedData + { + Label = StringResourceSystemFacade.GetString("Composite.Plugins.WebsiteFileElementProvider", "UploadAndExtractZipFileTitle"), + ToolTip = StringResourceSystemFacade.GetString("Composite.Plugins.WebsiteFileElementProvider", "UploadAndExtractZipFileToolTip"), + Icon = WebsiteFileElementProvider.UploadAndExtractZipFile, + Disabled = false, + ActivePositions = ElementActionActivePosition.NavigatorTree | ElementActionActivePosition.SelectorTree, + ActionLocation = new ActionLocation + { + ActionType = ActionType.Add, + IsInFolder = false, + IsInToolbar = true, + ActionGroup = PrimaryFolderActionGroup, + ActionBundle = "Upload" } } }); diff --git a/Website/Composite/content/forms/Administrative/WebsiteFileElementProviderUploadAndExtractZipFile.xml b/Website/Composite/content/forms/Administrative/WebsiteFileElementProviderUploadAndExtractZipFile.xml new file mode 100644 index 0000000000..c768eee1cd --- /dev/null +++ b/Website/Composite/content/forms/Administrative/WebsiteFileElementProviderUploadAndExtractZipFile.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Website/Composite/images/icons/svg/website-upload-zip-file.svg b/Website/Composite/images/icons/svg/website-upload-zip-file.svg new file mode 100644 index 0000000000..81a3af9f7b --- /dev/null +++ b/Website/Composite/images/icons/svg/website-upload-zip-file.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Website/Composite/localization/Composite.Plugins.WebsiteFileElementProvider.en-us.xml b/Website/Composite/localization/Composite.Plugins.WebsiteFileElementProvider.en-us.xml index 9f33186986..554b9e312b 100644 --- a/Website/Composite/localization/Composite.Plugins.WebsiteFileElementProvider.en-us.xml +++ b/Website/Composite/localization/Composite.Plugins.WebsiteFileElementProvider.en-us.xml @@ -23,9 +23,25 @@ - - + + + + + + + + + + + + + + + + + + diff --git a/Website/WebSite.csproj b/Website/WebSite.csproj index ce5d48f3d3..b3d3f4ee5b 100644 --- a/Website/WebSite.csproj +++ b/Website/WebSite.csproj @@ -175,6 +175,7 @@ + Designer @@ -219,6 +220,7 @@ + @@ -259,7 +261,6 @@ ASPXCodeBehind - ASPXCodeBehind @@ -1814,10 +1815,8 @@ Designer - - @@ -2489,52 +2488,36 @@ - - - - - - - - - - - - - - - - From f91e0498ef183a6aa2bcb83d9ec947cb4e1be418 Mon Sep 17 00:00:00 2001 From: Morteza Kasravi Date: Thu, 20 Oct 2016 13:12:22 +0200 Subject: [PATCH 05/22] add select action from bundle ability to selectTreeNodeAction + a sample test using it --- .../test/e2e/ApiLang/Notepad++/nightwatch.xml | 1 + .../test/e2e/commands/selectTreeNodeAction.js | 18 +++++++++--- .../file-bulk-upload/ClickBundledAction.js | 29 +++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js diff --git a/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml b/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml index 3bccb54b1d..f11bacea84 100644 --- a/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml +++ b/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml @@ -174,6 +174,7 @@ + diff --git a/Website/test/e2e/commands/selectTreeNodeAction.js b/Website/test/e2e/commands/selectTreeNodeAction.js index b4ea6a9552..7831c01a81 100644 --- a/Website/test/e2e/commands/selectTreeNodeAction.js +++ b/Website/test/e2e/commands/selectTreeNodeAction.js @@ -4,16 +4,26 @@ function SlectTreeNodeAction() { events.EventEmitter.call(this); } -SlectTreeNodeAction.prototype.command = function (node,action) { +SlectTreeNodeAction.prototype.command = function (node,action,bundle) { var content = this.client.api.page.content(); var systemView = this.client.api.page.systemView(); + var browser = this.client.api; systemView .enterActivePerspective() ._rightClickonTreeNode(node); - this.client.api.selectFrame('menuitem[label="' + action + '"]'); - content - .click('menuitem[label="'+action+'"]'); + this.client.api.selectFrame('menuitem[label="' + action + '"]'); + if(bundle==null){ + content + .click('menuitem[label="'+action+'"]'); + } + else{ + this.client.api.moveToElement('menuitem[label="' + bundle + '"]', 5, 5, function(){ + browser.pause(2000); + content + .click('menuitem[label="'+action+'"]'); + }); + } return this.client.api; }; diff --git a/Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js b/Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js new file mode 100644 index 0000000000..7eac1f9353 --- /dev/null +++ b/Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js @@ -0,0 +1,29 @@ +module.exports = { + '@tags': ['Duplicate'], + beforeEach: function (browser) { + browser.url(browser.launchUrl + '/Composite/top.aspx'); + var content = browser.page.content(); + content + .prepare("Content"); + }, + 'Click Bundled Action': function (browser) { + browser + .selectPerspective("Content") + .openTreeNode("Venus Starter Site") + .selectTreeNodeAction("Getting Started", "Add Blog", "Add Page") + .setFieldValue("Page title", "New Blog") + .clickDialogButton("Finish") + .selectDocumentTab("Content") + .closeDocumentTab("New Blog") + .assertTreeNodeHasChild("Getting Started","New Blog") + + .selectTreeNodeAction("New Blog","Delete") + .clickDialogButton("OK") + .assertTreeNodeHasNoChild("New Blog") + + }, + afterEach: function (browser, done) { + done(); + } +} + From 81c3d0602badc470c4936179f6b5ef620bef0523 Mon Sep 17 00:00:00 2001 From: Morteza Kasravi Date: Thu, 20 Oct 2016 13:19:08 +0200 Subject: [PATCH 06/22] change fix timeout value with global --- Website/test/e2e/commands/selectTreeNodeAction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Website/test/e2e/commands/selectTreeNodeAction.js b/Website/test/e2e/commands/selectTreeNodeAction.js index 7831c01a81..f5f0194847 100644 --- a/Website/test/e2e/commands/selectTreeNodeAction.js +++ b/Website/test/e2e/commands/selectTreeNodeAction.js @@ -19,7 +19,7 @@ SlectTreeNodeAction.prototype.command = function (node,action,bundle) { } else{ this.client.api.moveToElement('menuitem[label="' + bundle + '"]', 5, 5, function(){ - browser.pause(2000); + browser.pause(browser.globals.timeouts.little); content .click('menuitem[label="'+action+'"]'); }); From 7c645a1f0c9e61b56e2e65d928f6162bf3908bba Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Thu, 20 Oct 2016 13:26:24 +0200 Subject: [PATCH 07/22] Update README.md Moving up info about having port 8080 ready to answer, above the info on how to launch tests. --- Website/test/e2e/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Website/test/e2e/README.md b/Website/test/e2e/README.md index 0e93060c46..ed2da419f0 100644 --- a/Website/test/e2e/README.md +++ b/Website/test/e2e/README.md @@ -12,10 +12,10 @@ First we need to verify that you have the needed version of node.js, which is us The next step is installing nightwatch itself. This is done by issuing the command `npm install -g nightwatch`. This will install nightwatch as a globally accessible command. There may be some warnings issued by npm as it runs, these can usually be ignored without issue. -Finally, navigate to the root directory of your CMS working copy. This will usually be named `CMS`, but you may have named it otherwise when cloning it. In this directory, you can then start the tests by running `nightwatch` from your command line. This will run the whole test suite, starting with installing the Venus starter site. - Nightwatch expects to find the CMS running on localhost, port 8080. You can either change your Visual Studio or WebMatrix/IIS setup to use this port, or edit the `nightwatch.json` configuration file found in the project root. You can edit the line that says `"launch_url" : "http://localhost:8080"` to reflect the URL used. +Finally, navigate to the root directory of your CMS working copy. This will usually be named `CMS`, but you may have named it otherwise when cloning it. In this directory, you can then start the tests by running `nightwatch` from your command line. This will run the whole test suite, starting with installing the Venus starter site. + Due to certain technical limitations, nightwatch must always be run from the working directory, and cannot be run from any subdirectory. ## Running tests separately From ee169a2e8cc9f1ec44787712b9a5c0be27927440 Mon Sep 17 00:00:00 2001 From: Morteza Kasravi Date: Thu, 20 Oct 2016 14:38:34 +0200 Subject: [PATCH 08/22] add installation note for notepad++ language --- .../ApiLang/Notepad++/{Nightwatch.UDL => Nightwatch.UDL.xml} | 0 Website/test/e2e/ApiLang/Notepad++/installation.txt | 5 +++++ 2 files changed, 5 insertions(+) rename Website/test/e2e/ApiLang/Notepad++/{Nightwatch.UDL => Nightwatch.UDL.xml} (100%) create mode 100644 Website/test/e2e/ApiLang/Notepad++/installation.txt diff --git a/Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL b/Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL.xml similarity index 100% rename from Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL rename to Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL.xml diff --git a/Website/test/e2e/ApiLang/Notepad++/installation.txt b/Website/test/e2e/ApiLang/Notepad++/installation.txt new file mode 100644 index 0000000000..818786d13e --- /dev/null +++ b/Website/test/e2e/ApiLang/Notepad++/installation.txt @@ -0,0 +1,5 @@ +1. copy nightwatch.xml to your notepad++ api directory ( C:\Program Files (x86)\Notepad++\plugins\APIs\ ) +2. in notepad++ select Languages > Define Your Language.. > Import... > (select nightwatch.UML.xml) +3. restart notepad++ + +it should appear in language menu as Nightwatch \ No newline at end of file From dc703066c6378dc26f120cc9733e191499a5bcee Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Thu, 20 Oct 2016 23:26:39 +0200 Subject: [PATCH 09/22] Fixing (minor) issue where user adding a file system folder to the root did not get focus on the new folder. --- .../AddNewWebsiteFolderWorkflow.cs | 22 ++++++++++--- .../C1Console/Actions/DeleteTreeRefresher.cs | 1 - .../WebsiteFileElementProvider.cs | 2 +- ...bsiteFileElementProviderRootEntityToken.cs | 32 +++++++++++++++---- ...FileEntityTokenSecurityAncestorProvider.cs | 2 +- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/AddNewWebsiteFolderWorkflow.cs b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/AddNewWebsiteFolderWorkflow.cs index 5fce51e444..efc9184841 100644 --- a/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/AddNewWebsiteFolderWorkflow.cs +++ b/Composite.Workflows/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/AddNewWebsiteFolderWorkflow.cs @@ -68,13 +68,27 @@ private void finalizeCodeActivity_ExecuteCode(object sender, EventArgs e) SpecificTreeRefresher specificTreeRefresher = this.CreateSpecificTreeRefresher(); specificTreeRefresher.PostRefreshMesseges(this.EntityToken); - if (this.EntityToken is WebsiteFileElementProviderEntityToken) + string providerName; + string rootPath; + + switch (this.EntityToken.GetType().Name) { - WebsiteFileElementProviderEntityToken folderToken = (WebsiteFileElementProviderEntityToken)this.EntityToken; - var newFileToken = new WebsiteFileElementProviderEntityToken(folderToken.ProviderName, newFolderPath, folderToken.RootPath); - SelectElement(newFileToken); + case nameof(WebsiteFileElementProviderRootEntityToken): + WebsiteFileElementProviderRootEntityToken rootToken = (WebsiteFileElementProviderRootEntityToken)this.EntityToken; + providerName = rootToken.ProviderName; + rootPath = rootToken.RootPath; + break; + case nameof(WebsiteFileElementProviderEntityToken): + WebsiteFileElementProviderEntityToken folderToken = (WebsiteFileElementProviderEntityToken)this.EntityToken; + providerName = folderToken.ProviderName; + rootPath = folderToken.RootPath; + break; + default: + throw new InvalidOperationException("Unexpected EntityToken type"); } + var newFileToken = new WebsiteFileElementProviderEntityToken(providerName, newFolderPath, rootPath); + SelectElement(newFileToken); } diff --git a/Composite/C1Console/Actions/DeleteTreeRefresher.cs b/Composite/C1Console/Actions/DeleteTreeRefresher.cs index 0d715c89aa..872cfeea23 100644 --- a/Composite/C1Console/Actions/DeleteTreeRefresher.cs +++ b/Composite/C1Console/Actions/DeleteTreeRefresher.cs @@ -61,7 +61,6 @@ public void PostRefreshMessages(bool skipBeforeDeleteEntityToken = false) foreach (EntityToken entityToken in RefreshDeleteEntityTokenFinder.FindEntityTokens(_beforeGraph, skipBeforeDeleteEntityToken)) { messageService.RefreshTreeSection(entityToken); - Log.LogVerbose(this.GetType().Name, "Refreshing EntityToken: Type = {0}, Source = {1}, Id = {2}, EntityTokenType = {3}", entityToken.Type, entityToken.Source, entityToken.Id, entityToken.GetType()); } } } diff --git a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs index ff651966ee..b02babab34 100644 --- a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs +++ b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProvider.cs @@ -94,7 +94,7 @@ public ElementProviderContext Context public IEnumerable GetRoots(SearchToken seachToken) { - Element element = new Element(_context.CreateElementHandle(new WebsiteFileElementProviderRootEntityToken(_context.ProviderName))) + Element element = new Element(_context.CreateElementHandle(new WebsiteFileElementProviderRootEntityToken(_context.ProviderName, _rootPath))) { VisualData = new ElementVisualizedData() { diff --git a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProviderRootEntityToken.cs b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProviderRootEntityToken.cs index 03041eb45c..283ffcdbc9 100644 --- a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProviderRootEntityToken.cs +++ b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileElementProviderRootEntityToken.cs @@ -10,14 +10,26 @@ namespace Composite.Plugins.Elements.ElementProviders.WebsiteFileElementProvider [SecurityAncestorProvider(typeof(NoAncestorSecurityAncestorProvider))] public sealed class WebsiteFileElementProviderRootEntityToken : EntityToken { - private string _providerName; + /// + public WebsiteFileElementProviderRootEntityToken(string providerName, string rootPath) + { + ProviderName = providerName; + RootPath = rootPath; + } + /// - public WebsiteFileElementProviderRootEntityToken(string providerName) + internal string ProviderName { - _providerName = providerName; + get; + private set; } + internal string RootPath + { + get; + private set; + } /// public override string Type @@ -29,7 +41,7 @@ public override string Type /// public override string Source { - get { return _providerName; } + get { return ProviderName; } } @@ -43,14 +55,22 @@ public override string Id /// public override string Serialize() { - return _providerName; + return string.Format("{0}${1}", ProviderName, RootPath); } /// public static EntityToken Deserialize(string serializedData) { - return new WebsiteFileElementProviderRootEntityToken(serializedData); + if (serializedData.IndexOf('$')>0) + { + var parts = serializedData.Split('$'); + return new WebsiteFileElementProviderRootEntityToken(parts[0], parts[1]); + } + else + { + return new WebsiteFileElementProviderRootEntityToken(serializedData, ""); + } } } } diff --git a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileEntityTokenSecurityAncestorProvider.cs b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileEntityTokenSecurityAncestorProvider.cs index c87340fc3c..4ac891dee1 100644 --- a/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileEntityTokenSecurityAncestorProvider.cs +++ b/Composite/Plugins/Elements/ElementProviders/WebsiteFileElementProvider/WebsiteFileEntityTokenSecurityAncestorProvider.cs @@ -31,7 +31,7 @@ public IEnumerable GetParents(EntityToken entityToken) return new EntityToken[] { new WebsiteFileElementProviderEntityToken(castedEntityToken.Source, newFolderPath, castedEntityToken.RootPath) }; } - return new EntityToken[] { new WebsiteFileElementProviderRootEntityToken(castedEntityToken.Source) }; + return new EntityToken[] { new WebsiteFileElementProviderRootEntityToken(castedEntityToken.Source, castedEntityToken.RootPath) }; } } } From a34e08a644880954c7a5e14f2b4cabecfcc2d232 Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Thu, 20 Oct 2016 23:29:20 +0200 Subject: [PATCH 10/22] Adding "setFileFieldValue" command to nightwatch api (enabling test writer to upload files). Fixing minor spelling issue in Notepad++ intellisense. --- .../e2e/ApiLang/Notepad++/Nightwatch.UDL.xml | 2 +- .../test/e2e/ApiLang/Notepad++/nightwatch.xml | 16 +++++++++++----- Website/test/e2e/commands/setFileFieldValue.js | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 Website/test/e2e/commands/setFileFieldValue.js diff --git a/Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL.xml b/Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL.xml index d84c0ba2c7..f7bf81287d 100644 --- a/Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL.xml +++ b/Website/test/e2e/ApiLang/Notepad++/Nightwatch.UDL.xml @@ -24,7 +24,7 @@ - assertBrowserContainsAttribute assertBrowserContains assertFieldValue assertTreeNodeHasChild assertTreeNodeIsEmpty assertTreeNodeIsNotEmpty clickDataBySibilings clickDialogButton clickInFrame clickLabel clickSave replaceTextInCodeMirror selectEditOnContent clickText closeDocumentTab changeElementContent doubleClickSelector enterFrame leaveFrame openTreeNode replaceContent rightClickSelector selectActionFromToolbar selectContentTab selectDialog selectDocumentTab selectFrame selectFrameWithXpath selectPerspective selectTreeNodeAction setFieldValueInFieldGroup setFieldValue switchContentTab topFrame waitForFrameLoad acceptChanges acceptFunctionEdit assertTreeNodeHasNoChild submitFormData installPackage uninstallPackage + assertBrowserContainsAttribute assertBrowserContains assertFieldValue assertTreeNodeHasChild assertTreeNodeIsEmpty assertTreeNodeIsNotEmpty clickDataBySibilings clickDialogButton clickInFrame clickLabel clickSave replaceTextInCodeMirror selectEditOnContent clickText closeDocumentTab changeElementContent doubleClickSelector enterFrame leaveFrame openTreeNode replaceContent rightClickSelector selectActionFromToolbar selectContentTab selectDialog selectDocumentTab selectFrame selectFrameWithXpath selectPerspective selectTreeNodeAction setFieldValueInFieldGroup setFieldValue setFileFieldValue switchContentTab topFrame waitForFrameLoad acceptChanges acceptFunctionEdit assertTreeNodeHasNoChild submitFormData installPackage uninstallPackage browser editor2 editor beforeEach afterEach done diff --git a/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml b/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml index f11bacea84..483f9a7927 100644 --- a/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml +++ b/Website/test/e2e/ApiLang/Notepad++/nightwatch.xml @@ -39,7 +39,7 @@ - + @@ -69,7 +69,7 @@ - + @@ -94,7 +94,7 @@ - + @@ -181,17 +181,23 @@ - + - + + + + + + + diff --git a/Website/test/e2e/commands/setFileFieldValue.js b/Website/test/e2e/commands/setFileFieldValue.js new file mode 100644 index 0000000000..ca9a186d2c --- /dev/null +++ b/Website/test/e2e/commands/setFileFieldValue.js @@ -0,0 +1,18 @@ +var events = require('events'); + +function SetValueByLabel() { + events.EventEmitter.call(this); +} + +SetValueByLabel.prototype.command = function (fieldLabel,value) { + this.client.api.selectFrameWithXpath('//*[local-name() = "fielddesc"][normalize-space(text())="'+fieldLabel+'"]'); + + this.client.api + .useXpath() + .click('//*[local-name() = "fielddesc"][normalize-space(text())="'+fieldLabel+'"]/parent::*//*[local-name() = "input"]') + .useCss() + .setValue('input[type="file"]', value); + return this.client.api; +}; + +module.exports = SetValueByLabel; \ No newline at end of file From c23cf1f32993627c675376ebe8d16f95429e3777 Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Thu, 20 Oct 2016 23:46:24 +0200 Subject: [PATCH 11/22] Test validating zip upload and extraction. --- .../file-bulk-upload/ClickBundledAction.js | 29 ---------------- .../UploadAndExtractZip.js | 32 ++++++++++++++++++ .../suite/website-zip-upload-extract/test.zip | Bin 0 -> 398 bytes 3 files changed, 32 insertions(+), 29 deletions(-) delete mode 100644 Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js create mode 100644 Website/test/e2e/suite/website-zip-upload-extract/UploadAndExtractZip.js create mode 100644 Website/test/e2e/suite/website-zip-upload-extract/test.zip diff --git a/Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js b/Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js deleted file mode 100644 index 7eac1f9353..0000000000 --- a/Website/test/e2e/suite/file-bulk-upload/ClickBundledAction.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - '@tags': ['Duplicate'], - beforeEach: function (browser) { - browser.url(browser.launchUrl + '/Composite/top.aspx'); - var content = browser.page.content(); - content - .prepare("Content"); - }, - 'Click Bundled Action': function (browser) { - browser - .selectPerspective("Content") - .openTreeNode("Venus Starter Site") - .selectTreeNodeAction("Getting Started", "Add Blog", "Add Page") - .setFieldValue("Page title", "New Blog") - .clickDialogButton("Finish") - .selectDocumentTab("Content") - .closeDocumentTab("New Blog") - .assertTreeNodeHasChild("Getting Started","New Blog") - - .selectTreeNodeAction("New Blog","Delete") - .clickDialogButton("OK") - .assertTreeNodeHasNoChild("New Blog") - - }, - afterEach: function (browser, done) { - done(); - } -} - diff --git a/Website/test/e2e/suite/website-zip-upload-extract/UploadAndExtractZip.js b/Website/test/e2e/suite/website-zip-upload-extract/UploadAndExtractZip.js new file mode 100644 index 0000000000..f0340faf98 --- /dev/null +++ b/Website/test/e2e/suite/website-zip-upload-extract/UploadAndExtractZip.js @@ -0,0 +1,32 @@ +module.exports = { + '@tags': ['website-zip-upload-extract'], + beforeEach: function (browser) { + browser.url(browser.launchUrl + '/Composite/top.aspx'); + var content = browser.page.content(); + content + .prepare("Content"); + }, + 'Upload and Extract Zip': function (browser) { + browser + .selectPerspective("System") + .selectTreeNodeAction("/", "New Folder") + .setFieldValue("Folder name", "ZipTest") + .clickDialogButton("OK") + .selectPerspective("System") + .selectTreeNodeAction("ZipTest", "Upload and Extract Zip", "Upload File") + .setFileFieldValue("Zip file", require('path').resolve(__dirname + '/test.zip')) + .clickDialogButton("OK") + .openTreeNode("ZipTest") + .assertTreeNodeHasChild("ZipTest", "root.txt") + .openTreeNode("subdir1") + .openTreeNode("subdir2") + .assertTreeNodeHasChild("subdir2", "simple.txt") + + .selectTreeNodeAction("ZipTest","Delete Folder") + .clickDialogButton("OK") + }, + afterEach: function (browser, done) { + done(); + } +} + diff --git a/Website/test/e2e/suite/website-zip-upload-extract/test.zip b/Website/test/e2e/suite/website-zip-upload-extract/test.zip new file mode 100644 index 0000000000000000000000000000000000000000..335bf1f74736ef823349036771a9d21c9910a3b8 GIT binary patch literal 398 zcmWIWW@Zs#00H-&5Kn=gD<8yxY!K!E;-dWg61|d&5>NG9g{;!z5`{zskdQ)JW=^V} zo?ZZ4vmsD3P(2(709nPQNhz5{hWZfNNFSlv9H?4zVPn1|P!$MEVNqS2nOgv~1l4kg zAi{b^CJ_eQt_PaRz{sEgqJRMAmjG{sE^N+*s0Mk!7KkxDfzXZ38z9{fJF~IqMtCZ~ So0ScumKg~50BI0rU;qG5OHT;^ literal 0 HcmV?d00001 From 239d75ac86a42ca00f54699413d96bc2362272a7 Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Fri, 21 Oct 2016 15:52:30 +0300 Subject: [PATCH 12/22] Fix installing packages with dll referenced to Composite.dll and other dll in package(which not referenced to Comspoite.dll) plus installing some data after --- Composite/Data/DataMetaDataFacade.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Composite/Data/DataMetaDataFacade.cs b/Composite/Data/DataMetaDataFacade.cs index 6b21a6a065..d3b645ec26 100644 --- a/Composite/Data/DataMetaDataFacade.cs +++ b/Composite/Data/DataMetaDataFacade.cs @@ -20,7 +20,7 @@ namespace Composite.Data { - /// + /// /// /// [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] @@ -171,10 +171,10 @@ public static IEnumerable GeneratedTypeDataTypeDescriptors /// /// This method will return the data type descriptor for the given data type id. - /// If the data type descriptor has not yet been created (file not existing) and + /// If the data type descriptor has not yet been created (file not existing) and /// the is set to true, - /// this method will try getting it through the - /// that will try locating the type from the data type id using refelction + /// this method will try getting it through the + /// that will try locating the type from the data type id using refelction /// going through know assemblies. /// /// The id of the data type. @@ -211,7 +211,8 @@ public static DataTypeDescriptor GetDataTypeDescriptor(Guid dataTypeId, bool all } catch(ReflectionTypeLoadException ex) { - throw new InvalidOperationException($"Failed to get types from assembly '{assembly.FullName}'", ex); + Log.LogWarning($"Failed to get types from assembly '{assembly.FullName}'", ex); + continue; } foreach (Type type in types) From 354fbb3077b16409a241ff212f35c50cfe223d81 Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Mon, 24 Oct 2016 14:35:04 +0200 Subject: [PATCH 13/22] Updating version moniker to 5.4 (beta) --- Composite/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Composite/Properties/AssemblyInfo.cs b/Composite/Properties/AssemblyInfo.cs index 68791ba3e6..ec245877b7 100644 --- a/Composite/Properties/AssemblyInfo.cs +++ b/Composite/Properties/AssemblyInfo.cs @@ -8,9 +8,9 @@ // associated with an assembly. #if !InternalBuild -[assembly: AssemblyTitle("Orckestra CMS 5.3")] +[assembly: AssemblyTitle("Orckestra CMS 5.4 (beta)")] #else -[assembly: AssemblyTitle("Orckestra CMS 5.3 (Internal Build)")] +[assembly: AssemblyTitle("Orckestra CMS 5.4 (Internal Build)")] #endif [assembly: AssemblyDescription("Orckestra CMS Core classes")] From e7aac3428803a69741494b76b76896876220fddd Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Mon, 24 Oct 2016 16:49:52 +0200 Subject: [PATCH 14/22] Setting assembly version (5.4) --- .../Properties/AssemblyInfo.cs | 2 +- Composite/Properties/AssemblyInfo.cs | 2 +- Package.nuspec | 28 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Composite.Workflows/Properties/AssemblyInfo.cs b/Composite.Workflows/Properties/AssemblyInfo.cs index dc72a05f7b..b48c4e2e9f 100644 --- a/Composite.Workflows/Properties/AssemblyInfo.cs +++ b/Composite.Workflows/Properties/AssemblyInfo.cs @@ -32,6 +32,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("5.3.*")] +[assembly: AssemblyVersion("5.4.*")] [assembly: InternalsVisibleTo("UpgradePackage")] \ No newline at end of file diff --git a/Composite/Properties/AssemblyInfo.cs b/Composite/Properties/AssemblyInfo.cs index ec245877b7..6c3e08fdfd 100644 --- a/Composite/Properties/AssemblyInfo.cs +++ b/Composite/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("5.3.*")] +[assembly: AssemblyVersion("5.4.*")] [assembly: InternalsVisibleTo("UpgradePackage")] [assembly: InternalsVisibleTo("Composite.Workflows")] \ No newline at end of file diff --git a/Package.nuspec b/Package.nuspec index de4de6bec9..fa3f1f4160 100644 --- a/Package.nuspec +++ b/Package.nuspec @@ -2,8 +2,8 @@ OrckestraCmsFoundation.Assemblies - Orckestra CMS Foundation Assemblies - 5.3.0.0 + Orckestra CMS Foundation Assemblies + $version$ Orckestra A/S Orckestra A/S http://cms.orckestra.com/MPL11 @@ -15,20 +15,20 @@ Copyright 2016 OrckestraCms - - - - - + + + + + - - - - - - - + + + + + + + From 7d677b85bbe7b143192b78833b5f0baae9d183e4 Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Tue, 25 Oct 2016 11:46:25 +0300 Subject: [PATCH 15/22] fix #270 Function links in the C1 Page Speed view not working --- .../Commands/ConsoleCommandHandlers/ConsoleCommandHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Composite/Plugins/Commands/ConsoleCommandHandlers/ConsoleCommandHelper.cs b/Composite/Plugins/Commands/ConsoleCommandHandlers/ConsoleCommandHelper.cs index 2f91dbb16a..c978f00ef2 100644 --- a/Composite/Plugins/Commands/ConsoleCommandHandlers/ConsoleCommandHelper.cs +++ b/Composite/Plugins/Commands/ConsoleCommandHandlers/ConsoleCommandHelper.cs @@ -40,7 +40,7 @@ public static void SelectConsoleElement(string consoleId, EntityToken entityToke var selectItem = new SelectElementQueueItem { EntityToken = serializedEntityToken, - //PerspectiveElementKey = perspectiveElementKey + PerspectiveElementKey = perspectiveElementKey }; ConsoleMessageQueueFacade.Enqueue(selectItem, consoleId); From 172579dd641bbe1faffc294144999afdfeb9a9f2 Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Tue, 25 Oct 2016 12:29:42 +0300 Subject: [PATCH 16/22] Fix #266 A validation message on a required XHTML editor field (tab) shows up beyond the Console area --- .../source/top/ui/bindings/balloons/BalloonBinding.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Website/Composite/scripts/source/top/ui/bindings/balloons/BalloonBinding.js b/Website/Composite/scripts/source/top/ui/bindings/balloons/BalloonBinding.js index c0aea4f83d..c82f35b861 100644 --- a/Website/Composite/scripts/source/top/ui/bindings/balloons/BalloonBinding.js +++ b/Website/Composite/scripts/source/top/ui/bindings/balloons/BalloonBinding.js @@ -252,8 +252,13 @@ BalloonBinding.prototype._setComputedPosition = function ( tPoint, ePoint, tDim, } if ( isLeft ) { - point.x -= ( bDim.w + BalloonBinding.OFFSET_X ); - this.attachClassName ( BalloonBinding.CLASSNAME_LEFT ); + if (point.x < bDim.w + BalloonBinding.OFFSET_X) { // ballon outside app window from left + point.x += BalloonBinding.OFFSET_X * 2; + this.detachClassName(BalloonBinding.CLASSNAME_LEFT); + } else { + point.x -= (bDim.w + BalloonBinding.OFFSET_X); + this.attachClassName(BalloonBinding.CLASSNAME_LEFT); + } } else { point.x += tDim.w + BalloonBinding.OFFSET_X; this.detachClassName ( BalloonBinding.CLASSNAME_LEFT ); From f737d89323f6e3a4072c87c967adfea5d45114d7 Mon Sep 17 00:00:00 2001 From: Dmitry Dzygin Date: Tue, 25 Oct 2016 15:53:00 +0200 Subject: [PATCH 17/22] Fix for adding publishable page folder items --- .../AddAssociatedDataWorkflow.cs | 2 +- .../DataTypeDescriptorFormsHelper.cs | 45 ++++++++----------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddAssociatedDataWorkflow.cs b/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddAssociatedDataWorkflow.cs index 9ebb7981d6..8597a91e43 100644 --- a/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddAssociatedDataWorkflow.cs +++ b/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddAssociatedDataWorkflow.cs @@ -106,7 +106,7 @@ private void enterDataCodeActivity_ExecuteCode(object sender, EventArgs e) Guid pageId = GetBinding(BindingNames.PageId); - var helper = new DataTypeDescriptorFormsHelper(dataTypeDescriptor, true, null) + var helper = new DataTypeDescriptorFormsHelper(dataTypeDescriptor, true, EntityToken) { LayoutIconHandle = "associated-data-add" }; diff --git a/Composite/Data/DynamicTypes/DataTypeDescriptorFormsHelper.cs b/Composite/Data/DynamicTypes/DataTypeDescriptorFormsHelper.cs index c9d287829d..b528cb6284 100644 --- a/Composite/Data/DynamicTypes/DataTypeDescriptorFormsHelper.cs +++ b/Composite/Data/DynamicTypes/DataTypeDescriptorFormsHelper.cs @@ -58,7 +58,12 @@ static DataTypeDescriptorFormsHelper() } - /// + /// + /// Creates an instance of + /// + /// + /// + /// EntityToken is used for resolving to which publication states, current user has access to. public DataTypeDescriptorFormsHelper(DataTypeDescriptor dataTypeDescriptor, bool showPublicationStatusSelector, EntityToken entityToken) : this(dataTypeDescriptor, null, showPublicationStatusSelector, entityToken) { @@ -198,9 +203,9 @@ public string BindingNamesPrefix /// public void UpdateWithNewBindings(Dictionary bindings) { - var newBindigns = GetNewBindings(); + var newBindings = GetNewBindings(); - foreach (var kvp in newBindigns) + foreach (var kvp in newBindings) { bindings[kvp.Key] = kvp.Value; } @@ -288,9 +293,9 @@ private static Dictionary GetAvailablePublishingFlowTransitions( /// public void UpdateWithBindings(IData dataObject, Dictionary bindings) { - var newBindigns = GetBindings(dataObject); + var newBindings = GetBindings(dataObject); - foreach (var kvp in newBindigns) + foreach (var kvp in newBindings) { bindings[kvp.Key] = kvp.Value; } @@ -359,15 +364,15 @@ public Dictionary GetBindings(IData dataObject, bool allowMandat bindings[PublicationStatusBindingName] = ((IPublishControlled)dataObject).PublicationStatus; bindings.Add(PublicationStatusOptionsBindingName, GetAvailablePublishingFlowTransitions(EntityToken)); - var intefaceType = dataObject.DataSourceId.InterfaceType; + var interfaceType = dataObject.DataSourceId.InterfaceType; var stringKey = dataObject.GetUniqueKey().ToString(); var locale = dataObject.DataSourceId.LocaleScope.Name; - var existingPublishSchedule = PublishScheduleHelper.GetPublishSchedule(intefaceType, stringKey, locale); - bindings.Add("PublishDate", existingPublishSchedule != null ? existingPublishSchedule.PublishDate : (DateTime?) null); + var existingPublishSchedule = PublishScheduleHelper.GetPublishSchedule(interfaceType, stringKey, locale); + bindings.Add("PublishDate", existingPublishSchedule?.PublishDate); - var existingUnpublishSchedule = PublishScheduleHelper.GetUnpublishSchedule(intefaceType, stringKey, locale); - bindings.Add("UnpublishDate", existingUnpublishSchedule != null ? existingUnpublishSchedule.UnpublishDate : (DateTime?) null); + var existingUnpublishSchedule = PublishScheduleHelper.GetUnpublishSchedule(interfaceType, stringKey, locale); + bindings.Add("UnpublishDate", existingUnpublishSchedule?.UnpublishDate); } return bindings; @@ -530,27 +535,15 @@ public string LayoutIconHandle /// - public static XNamespace MainNamespace - { - get { return Namespaces.BindingFormsStdUiControls10; } - } - + public static XNamespace MainNamespace => Namespaces.BindingFormsStdUiControls10; /// - public static XNamespace CmsNamespace - { - get { return Namespaces.BindingForms10; } - } - + public static XNamespace CmsNamespace => Namespaces.BindingForms10; /// - public static XNamespace FunctionNamespace - { - get { return Namespaces.BindingFormsStdFuncLib10; } - } - + public static XNamespace FunctionNamespace => Namespaces.BindingFormsStdFuncLib10; /// @@ -878,7 +871,7 @@ internal bool BindingIsOptional(string bindingName) XElement bindingsXml; - if (customFormDefinition != null && customFormDefinition.Root != null) + if (customFormDefinition?.Root != null) { bindingsXml = customFormDefinition.Root; } From 361d988fb55160ca9311d1bac2591cbff27f702f Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Wed, 26 Oct 2016 13:56:20 +0300 Subject: [PATCH 18/22] Add counter to HierarchicalSelector --- .../Selectors/HierarchicalSelector.ascx | 4 +- .../Composite.Management.en-us.xml | 1 + .../selectors/HierarchicalSelectorBinding.js | 46 +++++++++++++++++++ .../styles/default/fields/selectors.less | 24 ++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/HierarchicalSelector.ascx b/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/HierarchicalSelector.ascx index fdd0b7e16c..6a238b9df8 100644 --- a/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/HierarchicalSelector.ascx +++ b/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/HierarchicalSelector.ascx @@ -94,6 +94,8 @@ " - autoselectchildren="<%= AutoSelectChildren ? "true" : "false" %>"> + autoselectchildren="<%= AutoSelectChildren ? "true" : "false" %>" + hascounter="true" + > <%= _treeXhml %> diff --git a/Website/Composite/localization/Composite.Management.en-us.xml b/Website/Composite/localization/Composite.Management.en-us.xml index 55c369e0d2..8a3cc51e7e 100644 --- a/Website/Composite/localization/Composite.Management.en-us.xml +++ b/Website/Composite/localization/Composite.Management.en-us.xml @@ -689,4 +689,5 @@ + \ No newline at end of file diff --git a/Website/Composite/scripts/source/top/ui/bindings/data/selectors/HierarchicalSelectorBinding.js b/Website/Composite/scripts/source/top/ui/bindings/data/selectors/HierarchicalSelectorBinding.js index fddb59a3c3..2f3fc28708 100644 --- a/Website/Composite/scripts/source/top/ui/bindings/data/selectors/HierarchicalSelectorBinding.js +++ b/Website/Composite/scripts/source/top/ui/bindings/data/selectors/HierarchicalSelectorBinding.js @@ -39,6 +39,11 @@ function HierarchicalSelectorBinding() { * @type {boolean} */ this.isRequired = false; + + /** + * @type {boolean} + */ + this.hasCounter = false; } /** @@ -67,6 +72,8 @@ HierarchicalSelectorBinding.prototype.onBindingAttach = function () { parent.attachClassName(DialogPageBodyBinding.FILLED_CLASSNAME); } + this.updateCounter(); + } /** @@ -95,6 +102,7 @@ HierarchicalSelectorBinding.prototype._parseDOMProperties = function () { this.autoSelectChildren = this.getProperty("autoselectchildren") === true; this.isRequired = this.getProperty("required") === true; + this.hasCounter = this.getProperty("hascounter") === true; } HierarchicalSelectorBinding.prototype._populate = function () { @@ -201,6 +209,8 @@ HierarchicalSelectorBinding.prototype.handleAction = function (action) { this.detachClassName(DataBinding.CLASSNAME_INVALID); } + this.updateCounter(); + action.consume(); break; @@ -215,6 +225,42 @@ HierarchicalSelectorBinding.prototype.handleAction = function (action) { } } + + +HierarchicalSelectorBinding.prototype.updateCounter = function () { + + if (this.hasCounter) { + var count = 0; + var selections = DOMUtil.getElementsByTagName(this.bindingElement, "selection"); + new List(selections).each(function (selection) { + var isSelectable = selection.getAttribute("selectable") === "true"; + var isSelected = selection.getAttribute("selected") === "true"; + var isReadonly = selection.getAttribute("readonly") === "true"; + if (isSelectable && !isReadonly && isSelected) { + count++; + } + }, this); + this.setCounter(count); + console.log(count); + } +} + + +HierarchicalSelectorBinding.prototype.setCounter = function (value) { + + if (this.hasCounter) { + if (this.shadowTree.countLabelBinding == null) { + this.shadowTree.countLabelBinding = LabelBinding.newInstance( + this.bindingDocument + ); + this.add(this.shadowTree.countLabelBinding); + } + var label = StringBundle.getString("ui", "Selector.Count"); + if (!label) return; + this.shadowTree.countLabelBinding.setLabel(label.replace("{0}", value)); + } +} + HierarchicalSelectorBinding.prototype.checkChildrenLazySelections = function (treenode, isChecked) { if (treenode.isContainer && !treenode.hasBeenOpened) { diff --git a/Website/Composite/styles/default/fields/selectors.less b/Website/Composite/styles/default/fields/selectors.less index 45ed75996d..990d28be2f 100644 --- a/Website/Composite/styles/default/fields/selectors.less +++ b/Website/Composite/styles/default/fields/selectors.less @@ -213,6 +213,30 @@ ui|field.fieldhelp ui|fielddata ui|urlinputdialog input { /* Hierarchical Selector */ ui|hierarchicalselector { + + &[hascounter='true'] { + + @counter-height: 30px; + + ui|box { + margin-bottom: @counter-height; + } + > ui|labelbox{ + margin-top: -@counter-height; + height: @counter-height; + width: 100%; + line-height: @counter-height; + border-top: 1px solid @base-border-color; + + ui|labelbody { + padding-right: 10px; + padding-left: 10px; + float: right; + } + } + } + + ui|treenode { ui|treenode { From a6d73e920d544d5768e18d7b0430737e48e376b5 Mon Sep 17 00:00:00 2001 From: Taras Nakonechnyi Date: Thu, 27 Oct 2016 11:25:00 +0300 Subject: [PATCH 19/22] style adjustment --- Website/Composite/styles/default/fields/selectors.less | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Website/Composite/styles/default/fields/selectors.less b/Website/Composite/styles/default/fields/selectors.less index 990d28be2f..31e6d4b6cf 100644 --- a/Website/Composite/styles/default/fields/selectors.less +++ b/Website/Composite/styles/default/fields/selectors.less @@ -229,9 +229,14 @@ ui|hierarchicalselector { border-top: 1px solid @base-border-color; ui|labelbody { - padding-right: 10px; - padding-left: 10px; + padding-right: 11px; + padding-left: 11px; float: right; + + font-family: @heading-font-family; + text-transform: uppercase; + color: @primary-color; + font-size: 13px; } } } From 691da51ca49264610d12b6e1343168aeba1e0ba4 Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Thu, 27 Oct 2016 13:42:57 +0200 Subject: [PATCH 20/22] Fix #282 - installing packages with dynamic data could lead to a deadlock --- Composite/GlobalInitializerFacade.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Composite/GlobalInitializerFacade.cs b/Composite/GlobalInitializerFacade.cs index e206e8124b..d962b088e8 100644 --- a/Composite/GlobalInitializerFacade.cs +++ b/Composite/GlobalInitializerFacade.cs @@ -393,9 +393,12 @@ private static void EnsureHookingFacade(object timeSpanToDelayStart) try { - using (ThreadDataManager.EnsureInitialize()) + using (GlobalInitializerFacade.CoreIsInitializedScope) { - HookingFacade.EnsureInitialization(); + using (ThreadDataManager.EnsureInitialize()) + { + HookingFacade.EnsureInitialization(); + } } } catch (Exception ex) From e6ad339080c42d81ff3235779efb25e35a99d2fb Mon Sep 17 00:00:00 2001 From: Dmitry Dzygin Date: Tue, 1 Nov 2016 15:25:05 +0100 Subject: [PATCH 21/22] Adding SharedAssemblyInfo.cs, removing an obsolete assembly reference --- Composite.Workflows/Composite.Workflows.csproj | 3 +++ Composite.Workflows/Properties/AssemblyInfo.cs | 17 ----------------- Composite/Composite.csproj | 5 +---- Composite/Properties/AssemblyInfo.cs | 16 ---------------- Composite/Properties/SharedAssemblyInfo.cs | 9 +++++++++ 5 files changed, 13 insertions(+), 37 deletions(-) create mode 100644 Composite/Properties/SharedAssemblyInfo.cs diff --git a/Composite.Workflows/Composite.Workflows.csproj b/Composite.Workflows/Composite.Workflows.csproj index 6abdd51e9e..c2d519c2fa 100644 --- a/Composite.Workflows/Composite.Workflows.csproj +++ b/Composite.Workflows/Composite.Workflows.csproj @@ -781,6 +781,9 @@ EditXsltFunctionWorkflow.cs + + Properties\SharedAssemblyInfo.cs + Component diff --git a/Composite.Workflows/Properties/AssemblyInfo.cs b/Composite.Workflows/Properties/AssemblyInfo.cs index b48c4e2e9f..acf7e9f7ea 100644 --- a/Composite.Workflows/Properties/AssemblyInfo.cs +++ b/Composite.Workflows/Properties/AssemblyInfo.cs @@ -8,11 +8,6 @@ [assembly: AssemblyTitle("Composite.Workflows")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Orckestra Inc")] -[assembly: AssemblyProduct("Orckestra CMS")] -[assembly: AssemblyCopyright("Copyright © Orckestra Inc 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from @@ -22,16 +17,4 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("88dc8435-878f-482a-8def-bcc6c7210f3e")] -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("5.4.*")] - [assembly: InternalsVisibleTo("UpgradePackage")] \ No newline at end of file diff --git a/Composite/Composite.csproj b/Composite/Composite.csproj index dda29f34b0..193ea68102 100644 --- a/Composite/Composite.csproj +++ b/Composite/Composite.csproj @@ -93,10 +93,6 @@ False ..\bin\Microsoft.Practices.ObjectBuilder.dll - - ..\packages\NodaTime.1.3.2\lib\net35-Client\NodaTime.dll - True - @@ -1132,6 +1128,7 @@ + diff --git a/Composite/Properties/AssemblyInfo.cs b/Composite/Properties/AssemblyInfo.cs index 6c3e08fdfd..faf637d037 100644 --- a/Composite/Properties/AssemblyInfo.cs +++ b/Composite/Properties/AssemblyInfo.cs @@ -15,11 +15,6 @@ [assembly: AssemblyDescription("Orckestra CMS Core classes")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Orckestra Inc")] -[assembly: AssemblyProduct("Orckestra CMS")] -[assembly: AssemblyCopyright("Copyright © Orckestra Inc 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from @@ -29,17 +24,6 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("c190c8d0-449f-42db-972d-0fc30f8c301d")] -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly: AssemblyVersion("5.4.*")] [assembly: InternalsVisibleTo("UpgradePackage")] [assembly: InternalsVisibleTo("Composite.Workflows")] \ No newline at end of file diff --git a/Composite/Properties/SharedAssemblyInfo.cs b/Composite/Properties/SharedAssemblyInfo.cs new file mode 100644 index 0000000000..e7e4f1f77f --- /dev/null +++ b/Composite/Properties/SharedAssemblyInfo.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +[assembly: AssemblyCompany("Orckestra Inc")] +[assembly: AssemblyProduct("Orckestra CMS")] +[assembly: AssemblyCopyright("Copyright © Orckestra Inc 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: AssemblyVersion("5.4.*")] \ No newline at end of file From 750e7f925285373d3f35494f20f0627a0225d0e9 Mon Sep 17 00:00:00 2001 From: Marcus Wendt Date: Wed, 2 Nov 2016 12:51:40 +0100 Subject: [PATCH 22/22] Updating version moniker to Orckestra CMS 5.4 --- Composite.Workflows/Properties/AssemblyInfo.cs | 5 ++--- Composite/Properties/AssemblyInfo.cs | 11 +---------- Composite/Properties/SharedAssemblyInfo.cs | 7 +++++++ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Composite.Workflows/Properties/AssemblyInfo.cs b/Composite.Workflows/Properties/AssemblyInfo.cs index acf7e9f7ea..58daa4f8f8 100644 --- a/Composite.Workflows/Properties/AssemblyInfo.cs +++ b/Composite.Workflows/Properties/AssemblyInfo.cs @@ -4,9 +4,8 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Composite.Workflows")] -[assembly: AssemblyDescription("")] +// associated with an assembly. See also Composite SharedAssemblyInfo.cs +[assembly: AssemblyDescription("Orckestra CMS Workflow Foundation classes")] [assembly: AssemblyConfiguration("")] // Setting ComVisible to false makes the types in this assembly not visible diff --git a/Composite/Properties/AssemblyInfo.cs b/Composite/Properties/AssemblyInfo.cs index faf637d037..5c45970fb0 100644 --- a/Composite/Properties/AssemblyInfo.cs +++ b/Composite/Properties/AssemblyInfo.cs @@ -2,17 +2,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -#if !InternalBuild -[assembly: AssemblyTitle("Orckestra CMS 5.4 (beta)")] -#else -[assembly: AssemblyTitle("Orckestra CMS 5.4 (Internal Build)")] -#endif - +// associated with an assembly. See also Composite SharedAssemblyInfo.cs [assembly: AssemblyDescription("Orckestra CMS Core classes")] [assembly: AssemblyConfiguration("")] @@ -24,6 +16,5 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("c190c8d0-449f-42db-972d-0fc30f8c301d")] - [assembly: InternalsVisibleTo("UpgradePackage")] [assembly: InternalsVisibleTo("Composite.Workflows")] \ No newline at end of file diff --git a/Composite/Properties/SharedAssemblyInfo.cs b/Composite/Properties/SharedAssemblyInfo.cs index e7e4f1f77f..0cf261b1b3 100644 --- a/Composite/Properties/SharedAssemblyInfo.cs +++ b/Composite/Properties/SharedAssemblyInfo.cs @@ -1,5 +1,12 @@ using System.Reflection; +// General Information about the assemblies Composite and Composite.Workflows +#if !InternalBuild +[assembly: AssemblyTitle("Orckestra CMS 5.4")] +#else +[assembly: AssemblyTitle("Orckestra CMS 5.4 (Internal Build)")] +#endif + [assembly: AssemblyCompany("Orckestra Inc")] [assembly: AssemblyProduct("Orckestra CMS")] [assembly: AssemblyCopyright("Copyright © Orckestra Inc 2016")]