1 /** 2 * Copyright (C) 2005-2010 Alfresco Software Limited. 3 * 4 * This file is part of Alfresco 5 * 6 * Alfresco is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * Alfresco is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /** 21 * ConsoleGroups tool component. 22 * 23 * @namespace Alfresco 24 * @class Alfresco.ConsoleGroups 25 */ 26 (function() 27 { 28 /** 29 * YUI Library aliases 30 */ 31 var Dom = YAHOO.util.Dom, 32 Event = YAHOO.util.Event, 33 Element = YAHOO.util.Element; 34 35 /** 36 * Alfresco Slingshot aliases 37 */ 38 var $html = Alfresco.util.encodeHTML; 39 40 /** 41 * ConsoleGroups constructor. 42 * 43 * @param {String} htmlId The HTML id of the parent element 44 * @return {Alfresco.ConsoleGroups} The new ConsoleGroups instance 45 * @constructor 46 */ 47 Alfresco.ConsoleGroups = function(htmlId) 48 { 49 this.name = "Alfresco.ConsoleGroups"; 50 Alfresco.ConsoleGroups.superclass.constructor.call(this, htmlId); 51 52 /* Register this component */ 53 Alfresco.util.ComponentManager.register(this); 54 55 /* Load YUI Components */ 56 Alfresco.util.YUILoaderHelper.require(["button", "container", "datasource", "datatable", "json", "history", "columnbrowser"], this.onComponentsLoaded, this); 57 58 /* Decoupled event listeners */ 59 YAHOO.Bubbling.on("newGroup", this.onNewGroup, this); 60 YAHOO.Bubbling.on("updateGroup", this.onUpdateGroup, this); 61 62 /* Define panel handlers */ 63 var parent = this; 64 this.panelHandlers = {}; 65 66 // NOTE: the panel registered first is considered the "default" view and is displayed first 67 68 /* Search Panel Handler */ 69 SearchPanelHandler = function SearchPanelHandler_constructor() 70 { 71 SearchPanelHandler.superclass.constructor.call(this, "search"); 72 }; 73 74 YAHOO.extend(SearchPanelHandler, Alfresco.ConsolePanelHandler, 75 { 76 /** 77 * INSTANCE VARIABLES 78 */ 79 80 /** 81 * Keeps track if this panel is visble or not 82 * 83 * @property _visible 84 * @type Boolean 85 */ 86 _visible: false, 87 88 /** 89 * Keeps track if this panel is searching or not 90 * 91 * @property isSearching 92 * @type Boolean 93 */ 94 isSearching: false, 95 96 /** 97 * When the Add User dialog or the Add Group dialog is shown this variable keeps track 98 * of which group the selected user or group should be added to. 99 * 100 * @property _selectedParentGroupShortName 101 * @type String 102 */ 103 _selectedParentGroupShortName: null, 104 105 /** 106 * PANEL LIFECYCLE CALLBACKS 107 */ 108 109 /** 110 * Called by the ConsolePanelHandler when this panel shall be loaded 111 * 112 * @method onLoad 113 */ 114 onLoad: function ConsoleGroups_SearchPanelHandler_onLoad() 115 { 116 var me = this; 117 118 // Search Button 119 var searchButton = new YAHOO.widget.Button(parent.id + "-search-button", {}); 120 searchButton.on("click", this.onSearchClick, searchButton, this); 121 this.widgets.searchButton = searchButton; 122 123 // ColumnBrowser 124 this.widgets.columnbrowser = new YAHOO.extension.ColumnBrowser(parent.id + "-columnbrowser", 125 { 126 numVisible: 3, 127 rootUrl: Alfresco.constants.PROXY_URI + "api/rootgroups?sortBy=displayName", 128 pagination: 129 { 130 rowsPerPage: parent.options.maxPageSize, 131 rowsPerPageParam: 'maxItems', 132 recordOffsetParam: 'skipCount', 133 firstPageLinkLabel : parent._msg('tinyPagination.firstPageLinkLabel'), 134 lastPageLinkLabel : parent._msg('tinyPagination.lastPageLinkLabel'), 135 previousPageLinkLabel : parent._msg('tinyPagination.previousPageLinkLabel'), 136 nextPageLinkLabel : parent._msg('tinyPagination.nextPageLinkLabel'), 137 pageReportTemplate : parent._msg('tinyPagination.pageReportTemplate'), 138 template: parent._msg('tinyPagination.template') 139 }, 140 columnInfoBuilder: 141 { 142 fn: this.onBuildColumnInfo, 143 scope: this 144 } 145 }); 146 147 // ColumnBrowser Breadcrumb 148 this.widgets.breadcrumb = new YAHOO.extension.ColumnBrowserBreadCrumb(parent.id + "-breadcrumb", 149 { 150 columnBrowser: this.widgets.columnbrowser, 151 root: parent._msg("label.breadcrumb.root") 152 }); 153 154 // Browse button 155 var browse = new YAHOO.widget.Button(parent.id + "-browse-button", {}); 156 browse.on("click", this.onBrowseClick, browse, this); 157 158 // Show All checkbox 159 var elShowAll = Dom.get(parent.id + "-show-all"); 160 Event.addListener(elShowAll, "change", function() 161 { 162 var state = { 163 "showAll": elShowAll.checked 164 }; 165 parent.refreshUIState(state); 166 }, null, this); 167 168 // DataTable and DataSource setup 169 this.widgets.dataSource = new YAHOO.util.DataSource(Alfresco.constants.PROXY_URI + "api/groups?", 170 { 171 responseType: YAHOO.util.DataSource.TYPE_JSON, 172 responseSchema: 173 { 174 resultsList: "data", 175 metaFields: 176 { 177 recordOffset: "startIndex", 178 totalRecords: "totalRecords" 179 } 180 } 181 }); 182 183 // Work to be performed after data has been queried but before display by the DataTable 184 this.widgets.dataSource.doBeforeParseData = function ConsoleGroups_SearchPanel_doBeforeParseData(oRequest, oFullResponse) 185 { 186 var updatedResponse = oFullResponse; 187 188 if (oFullResponse) 189 { 190 var items = oFullResponse.data; 191 192 // initial sort by username field 193 items.sort(function(a, b) 194 { 195 var name1 = a.shortName ? a.shortName.toLowerCase() : "", 196 name2 = b.shortName ? b.shortName.toLowerCase() : ""; 197 return (name1 > name2) ? 1 : (name1 < name2) ? -1 : 0; 198 }); 199 200 // we need to wrap the array inside a JSON object so the DataTable gets the object it expects 201 updatedResponse = 202 { 203 "data": items 204 }; 205 } 206 207 // update Results Bar message with number of results found 208 if (items.length == 0) 209 { 210 me._setResultsMessage("message.noresults"); 211 } 212 else if (items.length < parent.options.maxSearchResults) 213 { 214 me._setResultsMessage("message.results", $html(parent.query), items.length); 215 } 216 else 217 { 218 me._setResultsMessage("message.maxresults", parent.options.maxSearchResults); 219 } 220 221 return updatedResponse; 222 }; 223 224 // Setup the main datatable 225 this._setupDataTable(); 226 227 // register the "enter" event on the search text field 228 var searchText = Dom.get(parent.id + "-search-text"); 229 new YAHOO.util.KeyListener(searchText, 230 { 231 keys: YAHOO.util.KeyListener.KEY.ENTER 232 }, 233 { 234 fn: function() 235 { 236 this.onSearchClick(); 237 }, 238 scope: this, 239 correctScope: true 240 }, "keydown").enable(); 241 242 // Load in the People Finder component from the server 243 Alfresco.util.Ajax.request( 244 { 245 url: Alfresco.constants.URL_SERVICECONTEXT + "components/people-finder/people-finder", 246 dataObj: 247 { 248 htmlid: parent.id + "-search-peoplefinder" 249 }, 250 successCallback: 251 { 252 fn: this.onPeopleFinderLoaded, 253 scope: this 254 }, 255 failureMessage: "Could not load People Finder component", 256 execScripts: true 257 }); 258 259 // Load in the Group Finder component from the server 260 Alfresco.util.Ajax.request( 261 { 262 url: Alfresco.constants.URL_SERVICECONTEXT + "components/people-finder/group-finder", 263 dataObj: 264 { 265 htmlid: parent.id + "-search-groupfinder" 266 }, 267 successCallback: 268 { 269 fn: this.onGroupFinderLoaded, 270 scope: this 271 }, 272 failureMessage: "Could not load Group Finder component", 273 execScripts: true 274 }); 275 276 // Create delete group panel 277 this.widgets.deleteGroupPanel = new Alfresco.util.createYUIPanel(parent.id + "-deletegroupdialog", 278 { 279 visible: false 280 }); 281 282 // Add event listeners to buttons 283 this.widgets.deleteGroupCancelButton = new YAHOO.widget.Button(parent.id + "-cancel-button", {}); 284 this.widgets.deleteGroupCancelButton.on("click", function() 285 { 286 this.widgets.deleteGroupPanel.hide(); 287 }, null, this); 288 289 this.widgets.deleteGroupOkButton = Alfresco.util.createYUIButton(parent, "remove-button", null); 290 }, 291 292 /** 293 * Called by the ConsolePanelHandler when this panel is shown 294 * 295 * @method onShow 296 */ 297 onShow: function ConsoleGroups_SearchPanelHandler_onShow() 298 { 299 this._visible = true; 300 301 // Set focus to the search input field 302 Dom.get(parent.id + "-search-text").focus(); 303 304 // Show All checkbox state from history 305 var elShowAll = Dom.get(parent.id + "-show-all"); 306 elShowAll.checked = parent.showAll; 307 }, 308 309 /** 310 * Called by the ConsolePanelHandler when this panel shall update its appearance 311 * 312 * @method onUpdate 313 */ 314 onUpdate: function ConsoleGroups_SearchPanelHandler_onUpdate() 315 { 316 if (parent.refresh == undefined || parent.query !== undefined) 317 { 318 /** 319 * The search panel shall only be displayed if a query exists OR when the page is initially loaded. 320 * The parent.refresh == undefined indicates that the page was reloaded when in browse view state. 321 */ 322 323 // Lets display the search list since the state indicates a query has been used 324 Dom.addClass(parent.id + "-browse-panel", "hidden"); 325 Dom.removeClass(parent.id + "-search-panel", "hidden"); 326 327 if (parent.query !== undefined) 328 { 329 // update the text field - as this event could come from bookmark, navigation or a search button click 330 var queryElem = Dom.get(parent.id + "-search-text"); 331 queryElem.value = parent.query; 332 333 // Redo the search 334 this.doSearch(); 335 } 336 } 337 else 338 { 339 // No query in the state then display the column browser 340 Dom.addClass(parent.id + "-search-panel", "hidden"); 341 Dom.removeClass(parent.id + "-browse-panel", "hidden"); 342 343 var paths = this.widgets.columnbrowser.get("urlPath"); 344 if (!paths || paths.length == 0) 345 { 346 // Load the root groups 347 this.widgets.columnbrowser.load(); 348 } 349 else if (parent.refresh) 350 { 351 // Refresh the column browser 352 this.widgets.columnbrowser.load(paths, true); 353 } 354 } 355 }, 356 357 /** 358 * Called by the ConsolePanelHandler when this panel is hidden 359 * 360 * @method onHide 361 */ 362 onHide: function ConsoleGroups_SearchPanelHandler_onHide() 363 { 364 this._visible = false; 365 }, 366 367 /** 368 * BUTTON EVENT HANDLERS 369 */ 370 371 /** 372 * Called when the user clicks the search button 373 * 374 * @method onSearchClick 375 */ 376 onSearchClick: function ConsoleGroups_SearchPanelHandler_onSearchClick() 377 { 378 var query = YAHOO.lang.trim(Dom.get(parent.id + "-search-text").value); 379 380 // inform the user if the search term entered is too small 381 if (query.replace(/\*/g, "").length < parent.options.minSearchTermLength) 382 { 383 Alfresco.util.PopupManager.displayMessage( 384 { 385 text: parent._msg("message.minimum-length", parent.options.minSearchTermLength) 386 }); 387 return; 388 } 389 390 parent.refreshUIState({"query": query}); 391 }, 392 393 /** 394 * Called when the user clicks the browse button 395 * 396 * @method onBrowseClick 397 */ 398 onBrowseClick: function ConsoleGroups_SearchPanelHandler_onBrowseClick() 399 { 400 parent.refreshUIState({"query": undefined, "refresh": "false"}); 401 }, 402 403 /** 404 * Called when the user clicks the delete button in the cofirm dialog. 405 * Deletes the group from the repository or simply removes is from a parent group. 406 * 407 * @param e The click event 408 * @param obj information about the group and its parent group 409 * shall be removed from parent group. If now present group will be deleted. 410 */ 411 onConfirmedDeleteGroupClick: function ConsoleGroups_SearchPanelHandler_onConfirmedDeleteGroupClick(e, obj) 412 { 413 // Hide the confirm dialog 414 this.widgets.deleteGroupPanel.hide(); 415 416 if (obj.multiParentMode && Dom.get(parent.id + "-remove").checked) 417 { 418 // Just remove the group from the parent group 419 this._removeGroup(obj.fullName, obj.parentShortName, obj.displayName); 420 } 421 else 422 { 423 // Delete the group form the repository 424 this._deleteGroup(obj.shortName, obj.displayName); 425 } 426 }, 427 428 /** 429 * Group selected event handler. 430 * This event is fired from Group picker - so we much ensure 431 * the event is for the current panel by checking panel visibility. 432 * 433 * @method onGroupSelected 434 * @param e DomEvent 435 * @param args Event parameters (depends on event type) 436 */ 437 onGroupSelected: function ConsoleGroups_SearchPanelHandler_onGroupSelected(e, args) 438 { 439 // This is a "global" event so we ensure the event is for the current panel by checking panel visibility. 440 if (this._visible) 441 { 442 var name = args[1].displayName; 443 this.widgets.addGroupPanel.hide(); 444 this._addToGroup( 445 args[1].itemName, 446 this._selectedParentGroupShortName, 447 parent._msg("message.addgroup-success", name), 448 parent._msg("message.addgroup-failure", name)); 449 } 450 }, 451 452 /** 453 * Called when the user has selected a person from the add user dialog. 454 * 455 * @method onPersonSelected 456 * @param e DomEvent 457 * @param args Event parameters (depends on event type) 458 */ 459 onPersonSelected: function ConsoleGroups_SearchPanelHandler_onPersonSelected(e, args) 460 { 461 // This is a "global" event so we ensure the event is for the current panel by checking panel visibility. 462 if (this._visible) 463 { 464 var name = args[1].firstName + " " + args[1].lastName; 465 this.widgets.addUserPanel.hide(); 466 this._addToGroup( 467 args[1].userName, 468 this._selectedParentGroupShortName, 469 parent._msg("message.adduser-success", name), 470 parent._msg("message.adduser-failure", name)); 471 } 472 }, 473 474 /** 475 * Called when the user clicks the new group icon in the column browser header 476 * 477 * @method onNewGroupClick 478 * @param columnInfo 479 */ 480 onNewGroupClick: function ConsoleGroups_SearchPanelHandler__onNewGroupClick(columnInfo) 481 { 482 // Send avenet so the create panel will be displayed 483 YAHOO.Bubbling.fire('newGroup', 484 { 485 group: columnInfo.parent ? columnInfo.parent.shortName : undefined, 486 groupDisplayName: columnInfo.parent ? columnInfo.parent.label : parent._msg("label.theroot") 487 }); 488 }, 489 490 /** 491 * Called when the user clicks the add gorup icon in the column browser header 492 * 493 * @method onAddGroupClick 494 * @param columnInfo 495 */ 496 onAddGroupClick: function ConsoleGroups_SearchPanelHandler__onAddGroupClick(columnInfo) 497 { 498 this._selectedParentGroupShortName = columnInfo.parent.shortName; 499 this.modules.searchGroupFinder.clearResults(); 500 this.widgets.addGroupPanel.show(); 501 }, 502 503 /** 504 * Called when the user clicks the add user icon in the column browser header 505 * 506 * @method onAddUserClick 507 * @param columnInfo 508 */ 509 onAddUserClick: function ConsoleGroups_SearchPanelHandler_onAddUserClick(columnInfo) 510 { 511 this._selectedParentGroupShortName = columnInfo.parent.shortName; 512 this.modules.searchPeopleFinder.clearResults(); 513 this.widgets.addUserPanel.show(); 514 }, 515 516 /** 517 * Called when the user clicks a groups delete icon in the column browser 518 * 519 * @method onDeleteClick 520 * @param ctx An object describing the group and its parent group 521 * ctx.columnInfo describes the clicked groups column (and its parent group) 522 * ctx.itemInfo describes the clicked group 523 */ 524 onDeleteClick: function ConsoleGroups_SearchPanelHandler_onDeleteClick(ctx) 525 { 526 this._confirmDeleteGroup( 527 ctx.itemInfo.shortName, 528 ctx.itemInfo.fullName, 529 ctx.itemInfo.label, 530 ctx.columnInfo.parent ? ctx.columnInfo.parent.shortName : null, 531 ctx.columnInfo.parent ? ctx.columnInfo.parent.label : parent._msg("label.theroot")); 532 }, 533 534 /** 535 * Called when the user clicks a users delete icon in the column browser 536 * 537 * @method onUserRemoveClick 538 * @param ctx An object describing the group and its parent group 539 * ctx.columnInfo describes the clicked groups column (and its parent group) 540 * ctx.itemInfo describes the clicked group 541 */ 542 onUserRemoveClick: function ConsoleGroups_SearchPanelHandler_onUserRemoveClick(ctx) 543 { 544 this._confirmRemoveUser(ctx.columnInfo.parent.shortName, ctx.itemInfo.shortName, ctx.itemInfo.label); 545 }, 546 547 /** 548 * Called when the user clicks a groups update icon in the column browser 549 * 550 * @method onUpdateClick 551 * @param ctx An object describing the group and its parent group 552 * ctx.columnInfo describes the clicked groups column (and its parent group) 553 * ctx.itemInfo describes the clicked group 554 */ 555 onUpdateClick: function ConsoleGroups_SearchPanelHandler_onUpdateClick(ctx) 556 { 557 YAHOO.Bubbling.fire('updateGroup', {group: ctx.itemInfo.shortName, groupDisplayName: ctx.itemInfo.label}); 558 }, 559 560 /** 561 * MODULE TEMPLATE LOAD HANDLERS 562 */ 563 564 /** 565 * Called when the people finder template has been loaded. 566 * Creates a dialog and inserts the people finder for choosing users to add. 567 * 568 * @method onPeopleFinderLoaded 569 * @param response The server response 570 */ 571 onPeopleFinderLoaded: function ConsoleGroups_SearchPanelHandler_onPeopleFinderLoaded(response) 572 { 573 // Inject the component from the XHR request into it's placeholder DIV element 574 var finderDiv = Dom.get(parent.id + "-search-peoplefinder"); 575 finderDiv.innerHTML = response.serverResponse.responseText; 576 577 // Create the Add User dialog 578 this.widgets.addUserPanel = Alfresco.util.createYUIPanel(parent.id + "-peoplepicker"); 579 580 // Find the People Finder by container ID 581 this.modules.searchPeopleFinder = Alfresco.util.ComponentManager.get(parent.id + "-search-peoplefinder"); 582 583 // Set the correct options for our use 584 this.modules.searchPeopleFinder.setOptions( 585 { 586 singleSelectMode: true 587 }); 588 589 // Make sure we listen for events when the user selects a person 590 YAHOO.Bubbling.on("personSelected", this.onPersonSelected, this); 591 }, 592 593 /** 594 * Called when the group finder template has been loaded. 595 * Creates a dialog and inserts the group finder for choosing groups to add. 596 * 597 * @method onGroupFinderLoaded 598 * @param response The server response 599 */ 600 onGroupFinderLoaded: function ConsoleGroups_SearchPanelHandler_onGroupFinderLoaded(response) 601 { 602 // Inject the component from the XHR request into it's placeholder DIV element 603 var finderDiv = Dom.get(parent.id + "-search-groupfinder"); 604 finderDiv.innerHTML = response.serverResponse.responseText; 605 606 // Create the Add Group dialog 607 this.widgets.addGroupPanel = Alfresco.util.createYUIPanel(parent.id + "-grouppicker") 608 609 // Find the Group Finder by container ID 610 this.modules.searchGroupFinder = Alfresco.util.ComponentManager.get(parent.id + "-search-groupfinder"); 611 612 // Set the correct options for our use 613 this.modules.searchGroupFinder.setOptions( 614 { 615 singleSelectMode: true 616 }); 617 618 // Make sure we listen for events when the user selects a group 619 YAHOO.Bubbling.on("itemSelected", this.onGroupSelected, this); 620 621 }, 622 623 /** 624 * COLUMN BROWSER CALLBACKS 625 */ 626 627 /** 628 * Called by the Column Browser to let this component transform the custom server reponse to a 629 * columnInfo object that the Column Browser understands 630 * 631 * @method onBuildColumnInfo 632 * @param serverResponse Response from the server containing column data OR null if a leaf was clicked 633 * @param itemInfo The parent item that was clicked to get the column data OR null if it is the root column 634 */ 635 onBuildColumnInfo: function ConsoleGroups_SearchPanelHandler_onBuildColumnInfo(serverResponse, itemInfo) 636 { 637 // Create columnInfo and its header 638 var headerButtons = []; 639 if (!itemInfo || itemInfo.cssClass == 'groups-item-group') 640 { 641 headerButtons.push({ 642 title: (itemInfo ? parent._msg("button.newsubgroup") : parent._msg("button.newgroup")), 643 cssClass: "groups-newgroup-button", 644 click: { 645 fn: this.onNewGroupClick, 646 scope: this 647 } 648 }); 649 } 650 if (itemInfo && itemInfo.cssClass == 'groups-item-group') 651 { 652 // Only add the following button for NON root columns 653 headerButtons.push({ 654 title: parent._msg("button.addgroup"), 655 cssClass: "groups-addgroup-button", 656 click: { 657 fn: this.onAddGroupClick, 658 scope: this 659 } 660 }); 661 headerButtons.push({ 662 title: parent._msg("button.adduser"), 663 cssClass: "groups-adduser-button", 664 click: { 665 fn: this.onAddUserClick, 666 scope: this 667 } 668 }); 669 } 670 671 // Create column descriptor 672 var column = { 673 parent: itemInfo, 674 header: { 675 buttons: headerButtons 676 }, 677 body: { 678 items: [] 679 } 680 }; 681 682 // Get data from request 683 var obj = {}; 684 if (serverResponse) 685 { 686 // Parse response if there was one 687 obj = YAHOO.lang.JSON.parse(serverResponse.responseText); 688 689 // Translate group paging attributes to columnbrowser pagination attributes 690 if (obj.paging) 691 { 692 column.pagination = { 693 totalRecords : obj.paging.totalItems, 694 recordOffset: obj.paging.skipCount 695 }; 696 } 697 } 698 699 // Create item buttons for users and groups 700 var groupButtons = [ 701 { 702 title: parent._msg("button.updategroup"), 703 cssClass: "groups-update-button", 704 click: { 705 fn: this.onUpdateClick, 706 scope: this 707 } 708 }, 709 { 710 title: parent._msg("button.deletegroup"), 711 cssClass: "groups-delete-button", 712 click: { 713 fn: this.onDeleteClick, 714 scope: this 715 } 716 } 717 ]; 718 var usersButtons = [ 719 { 720 title: parent._msg("button.removeuser"), 721 cssClass: "users-remove-button", 722 click: { 723 fn: this.onUserRemoveClick, 724 scope: this 725 } 726 } 727 ]; 728 729 // Transform server respons to itemInfos and add them to the columnInfo's body 730 for (var i = 0; obj.data && i < obj.data.length; i++) 731 { 732 var o = obj.data[i]; 733 var label = o.displayName; 734 if (o.displayName !== o.shortName) 735 { 736 label += " (" + o.shortName + ")"; 737 } 738 var item = { 739 shortName: o.shortName, 740 fullName: o.fullName, 741 url: o.authorityType == 'GROUP' ? Alfresco.constants.PROXY_URI + o.url + "/children?sortBy=displayName" : null, 742 hasNext: o.groupCount > 0 || o.userCount > 0, 743 label: label, 744 next : null, 745 cssClass: o.authorityType == 'GROUP' ? "groups-item-group" : "groups-item-user", 746 buttons: o.authorityType == 'GROUP' ? groupButtons : usersButtons 747 }; 748 column.body.items.push(item); 749 } 750 751 return column; 752 }, 753 754 /** 755 * PUBLIC METHODS 756 */ 757 758 /** 759 * Invoke search based on the "state", use the state-query parameter that is stored in the parent object 760 * each time a state is set. 761 * 762 * @method doSearch 763 */ 764 doSearch: function ConsoleGroups_SearchPanelHandler_doSearch() 765 { 766 // check search length again as we may have got here via history navigation 767 if (!this.isSearching && parent.query !== undefined && parent.query.length >= parent.options.minSearchTermLength) 768 { 769 this.isSearching = true; 770 771 var me = this; 772 773 // Reset the custom error messages 774 me._setDefaultDataTableErrors(me.widgets.dataTable); 775 776 // Don't display any message 777 me.widgets.dataTable.set("MSG_EMPTY", parent._msg("message.searching")); 778 779 // Empty results table 780 me.widgets.dataTable.deleteRows(0, me.widgets.dataTable.getRecordSet().getLength()); 781 782 var successHandler = function ConsoleGroups__ps_successHandler(sRequest, oResponse, oPayload) 783 { 784 me._enableSearchUI(); 785 me._setDefaultDataTableErrors(me.widgets.dataTable); 786 me.widgets.dataTable.onDataReturnInitializeTable.call(me.widgets.dataTable, sRequest, oResponse, oPayload); 787 }; 788 789 var failureHandler = function ConsoleGroups__ps_failureHandler(sRequest, oResponse) 790 { 791 me._enableSearchUI(); 792 if (oResponse.status == 401) 793 { 794 // Our session has likely timed-out, so refresh to offer the login page 795 window.location.reload(); 796 } 797 else 798 { 799 try 800 { 801 me.widgets.dataTable.set("MSG_ERROR", parent._msg("message.noresults.short")); 802 me.widgets.dataTable.showTableMessage(parent._msg("message.noresults.short"), YAHOO.widget.DataTable.CLASS_ERROR); 803 me._setResultsMessage("message.noresults"); 804 } 805 catch(e) 806 { 807 me._setDefaultDataTableErrors(me.widgets.dataTable); 808 } 809 } 810 }; 811 812 // Send the query to the server and disable search button 813 me.widgets.dataSource.sendRequest(me._buildSearchParams(parent.query), 814 { 815 success: successHandler, 816 failure: failureHandler, 817 scope: parent 818 }); 819 me._setResultsMessage("message.searchingFor", $html(parent.query)); 820 821 // Disable search button and display a wait feedback message if the groups hasn't been found yet 822 me.widgets.searchButton.set("disabled", true); 823 YAHOO.lang.later(2000, me, function(){ 824 if (me.isSearching) 825 { 826 if (!me.widgets.feedbackMessage) 827 { 828 me.widgets.feedbackMessage = Alfresco.util.PopupManager.displayMessage( 829 { 830 text: Alfresco.util.message("message.searching", parent.name), 831 spanClass: "wait", 832 displayTime: 0 833 }); 834 } 835 else if (!me.widgets.feedbackMessage.cfg.getProperty("visible")) 836 { 837 me.widgets.feedbackMessage.show(); 838 } 839 } 840 }, []); 841 } 842 }, 843 844 /** 845 * Enable search button, hide the pending wait message and set the panel as not searching. 846 * 847 * @method _enableSearchUI 848 * @private 849 */ 850 _enableSearchUI: function ConsoleGroups_SearchPanelHandler__enableSearchUI() 851 { 852 // Enable search button and close the wait feedback message if present 853 if (this.widgets.feedbackMessage && this.widgets.feedbackMessage.cfg.getProperty("visible")) 854 { 855 this.widgets.feedbackMessage.hide(); 856 } 857 this.widgets.searchButton.set("disabled", false); 858 this.isSearching = false; 859 }, 860 861 /** 862 * PRIVATE METHODS 863 */ 864 865 /** 866 * Asks the users if he is sure he wants to delete the group 867 * 868 * @param shortName shortName The id of the group to delete 869 * @param fullName The fullName of the group to delete (needed only if removing group from parent group) 870 * @param displayName The displayName of the group to delete 871 * @param parentShortName The shortName of the parent group to remove group from (needed only if removing group from parent group) 872 * @param parentDisplayName The displayName of the parent group to remove group from (needed only if removing group from parent group) 873 */ 874 _confirmDeleteGroup: function ConsoleGroups_SearchPanelHandler_confirmDeleteGroup(shortName, fullName, displayName, parentShortName, parentDisplayName) 875 { 876 var me = this; 877 parent.getParentGroups(shortName, 878 { 879 fn: function(groups) 880 { 881 // Remove previous listeners so we don't make duplicate calls and add a new one later 882 this.widgets.deleteGroupOkButton.removeListener("click", this.onConfirmedDeleteGroupClick); 883 var callbackObj = 884 { 885 shortName: shortName, 886 fullName: fullName, 887 displayName: displayName, 888 parentShortName: parentShortName, 889 parentDisplayName: parentDisplayName 890 }; 891 892 // Make sure the dialog is displayed correctly 893 if (!groups || groups.length == 0 || groups.length == 1) 894 { 895 // Group is root group or has only 1 parent 896 Dom.addClass(parent.id + "-multiparent", "hidden"); 897 Dom.removeClass(parent.id + "-singleparent", "hidden"); 898 Dom.get(parent.id + "-singleparent-message").innerHTML = parent._msg("panel.deletegroup.singleparentmessage", $html(displayName)); 899 this.widgets.deleteGroupOkButton.on("click", this.onConfirmedDeleteGroupClick, callbackObj, this); 900 } 901 else 902 { 903 // Group has multiple parents 904 Dom.addClass(parent.id + "-singleparent", "hidden"); 905 Dom.removeClass(parent.id + "-multiparent", "hidden"); 906 Dom.get(parent.id + "-multiparent-message").innerHTML = parent._msg("panel.deletegroup.multiparentmessage", $html(displayName)); 907 Dom.get(parent.id + "-remove-message").innerHTML = parent._msg("panel.deletegroup.removemessage", $html(displayName), $html(parentDisplayName)); 908 Dom.get(parent.id + "-delete-message").innerHTML = parent._msg("panel.deletegroup.deletemessage", $html(displayName)); 909 Dom.get(parent.id + "-searchdelete-message").innerHTML = parent._msg("panel.deletegroup.searchdeletemessage", $html(displayName)); 910 911 // Lets display the groups parents to the user, but only the first 10 912 var parentStr = "", displayLimit = 10; 913 for (var i = 0; i < groups.length && i < displayLimit; i++) 914 { 915 parentStr += groups[i].displayName + (i < groups.length - 1 ? ", " : ""); 916 } 917 if (i >= displayLimit) 918 { 919 parentStr += parent._msg("label.moregroups", groups.length - displayLimit); 920 } 921 Dom.get(parent.id + "-parents").innerHTML = $html(parentStr); 922 923 if (parentShortName) 924 { 925 // Display both the option to remove from parent group and delete the group 926 Dom.get(parent.id + "-remove").checked = true; 927 Dom.removeClass(parent.id + "-removerow", "hidden"); 928 Dom.removeClass(parent.id + "-deleterow", "hidden"); 929 Dom.addClass(parent.id + "-searchdeleterow", "hidden"); 930 } 931 else 932 { 933 /** 934 * The group was clicked in a context where none of the parents was displayed, 935 * in other words in the search list. There fore we can't display the option of just 936 * removing the group. 937 */ 938 Dom.get(parent.id + "-delete").checked = true; 939 Dom.addClass(parent.id + "-removerow", "hidden"); 940 Dom.addClass(parent.id + "-deleterow", "hidden"); 941 Dom.removeClass(parent.id + "-searchdeleterow", "hidden"); 942 } 943 944 // Make sure the callback knows what mode the dialog was displayed in 945 callbackObj.multiParentMode = true; 946 this.widgets.deleteGroupOkButton.on("click", this.onConfirmedDeleteGroupClick, callbackObj, this); 947 } 948 // Show the dialog 949 this.widgets.deleteGroupPanel.show(); 950 }, 951 scope: this 952 }, "message.delete-failure"); 953 }, 954 955 /** 956 * Asks the users if he is sure he wants to remove the user from the group. 957 * 958 * @param groupId The id of the group to remove the user from 959 * @param userId The id of the user to remove 960 * @param userDisplayName The displayName of the user 961 */ 962 _confirmRemoveUser: function ConsoleGroups_SearchPanelHandler__confirmRemoveUser(groupId, userId, userDisplayName) 963 { 964 var me = this; 965 Alfresco.util.PopupManager.displayPrompt( 966 { 967 title: parent._msg("message.confirm.removeuser.title"), 968 text: parent._msg("message.confirm.removeuser", userDisplayName), 969 buttons: [ 970 { 971 text: parent._msg("button.yes"), 972 handler: function ConsoleGroups__removeUser_confirmYes() 973 { 974 this.destroy(); 975 me._removeUser.call(me, groupId, userId, userDisplayName); 976 } 977 }, 978 { 979 text: parent._msg("button.no"), 980 handler: function ConsoleGroups__removeUser_confirmNo() 981 { 982 this.destroy(); 983 }, 984 isDefault: true 985 }] 986 }); 987 }, 988 989 /** 990 * Deletes the group from the repository. 991 * 992 * @param shortName The shortName of the group 993 * @param displayName The displayName of the group 994 * shall be removed from parent group. If now present group will be deleted. 995 */ 996 _deleteGroup: function ConsoleGroups_SearchPanelHandler__deleteGroup(shortName, displayName) 997 { 998 var url = Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(shortName); 999 this._doDeleteCall(url, displayName); 1000 }, 1001 1002 /** 1003 * Removes the group from a parent group 1004 * 1005 * @param fullName The full authority name of the group 1006 * @param parentShortName the shortname of the parent group 1007 * @param displayName The displayName of the group 1008 */ 1009 _removeGroup: function ConsoleGroups_SearchPanelHandler__removeGroup(fullName, parentShortName, displayName) 1010 { 1011 if (parentShortName == null) 1012 { 1013 // todo implement when webscript api supports it 1014 // This isn't supported by the webscript api yet 1015 Alfresco.util.PopupManager.displayPrompt( 1016 { 1017 title: parent._msg("message.failure"), 1018 text: parent._msg("message.noRemoveGroupFromRootSupport") 1019 }); 1020 return; 1021 } 1022 var url = Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(parentShortName) + "/children/" + encodeURIComponent(fullName); 1023 this._doDeleteCall(url, displayName); 1024 }, 1025 1026 /** 1027 * Deletes or removes a group depending on the url 1028 * 1029 * @param url Url to use to remove or delete group 1030 */ 1031 _doDeleteCall: function ConsoleGroups_SearchPanelHandler__deleteCall(url, displayName) 1032 { 1033 var groupDisplayName = displayName; 1034 Alfresco.util.Ajax.request( 1035 { 1036 method: Alfresco.util.Ajax.DELETE, 1037 url: url, 1038 successCallback: 1039 { 1040 fn: function(o) 1041 { 1042 // Refresh column browser 1043 var paths = this.widgets.columnbrowser.get("urlPath"); 1044 this.widgets.columnbrowser.load(paths, true); 1045 1046 // Refresh search table 1047 this.doSearch(); 1048 1049 // Display success message 1050 Alfresco.util.PopupManager.displayMessage( 1051 { 1052 text: parent._msg("message.delete-success", groupDisplayName) 1053 }); 1054 }, 1055 scope: this 1056 }, 1057 failureMessage: parent._msg("message.delete-failure", groupDisplayName) 1058 }); 1059 }, 1060 1061 /** 1062 * Remove the user from the group 1063 * 1064 * @param groupId The id of the group 1065 * @param userId The id of the user 1066 * @param userDisplayName The displayName of the user 1067 */ 1068 _removeUser: function ConsoleGroups_SearchPanelHandler__removeUser(groupId, userId, userDisplayName) 1069 { 1070 var name = userDisplayName; 1071 Alfresco.util.Ajax.request( 1072 { 1073 method: Alfresco.util.Ajax.DELETE, 1074 url: Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(groupId) + "/children/" + encodeURIComponent(userId), 1075 successCallback: 1076 { 1077 fn: function(o) 1078 { 1079 // Refresh column browser 1080 var paths = this.widgets.columnbrowser.get("urlPath"); 1081 this.widgets.columnbrowser.load(paths, true); 1082 1083 // Display success message 1084 Alfresco.util.PopupManager.displayMessage( 1085 { 1086 text: parent._msg("message.removeuser-success", name) 1087 }); 1088 }, 1089 scope: this 1090 }, 1091 failureMessage: parent._msg("message.removeuser-failure", name) 1092 }); 1093 }, 1094 1095 /** 1096 * Adds a user or group to a parent group. 1097 * 1098 * @param objectId The id to a user (userName) or a group (fullName) 1099 * @param parentGroupShortName The shortName of the parent group that the object shall be added under 1100 * @param successMessage Message to display if the request is successful 1101 * @param failureMessage Message to display if the request fails 1102 */ 1103 _addToGroup: function ConsoleGroups_SearchPanelHandler__addToGroup(objectId, parentGroupShortName, successMessage, failureMessage) 1104 { 1105 Alfresco.util.Ajax.jsonPost( 1106 { 1107 url: Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(parentGroupShortName) + "/children/" + encodeURIComponent(objectId), 1108 successCallback: 1109 { 1110 fn: function(o) 1111 { 1112 // Refresh column browser 1113 var paths = this.widgets.columnbrowser.get("urlPath"); 1114 this.widgets.columnbrowser.load(paths, true); 1115 1116 // Display success message 1117 Alfresco.util.PopupManager.displayMessage( 1118 { 1119 text: successMessage 1120 }); 1121 }, 1122 scope: this 1123 }, 1124 failureMessage: failureMessage 1125 }); 1126 }, 1127 1128 /** 1129 * Setup the YUI DataTable with custom renderers. 1130 * 1131 * @method _setupDataTable 1132 * @private 1133 */ 1134 _setupDataTable: function ConsoleGroups_SearchPanelHandler__setupDataTable() 1135 { 1136 var me = this; 1137 1138 /** 1139 * DataTable Cell Renderers 1140 * 1141 * Each cell has a custom renderer defined as a custom function. See YUI documentation for details. 1142 * These MUST be inline in order to have access to the parent instance (via the "parent" variable). 1143 */ 1144 1145 /** 1146 * Generic HTML-safe custom datacell formatter 1147 */ 1148 var renderCellSafeHTML = function renderCellSafeHTML(elCell, oRecord, oColumn, oData) 1149 { 1150 elCell.innerHTML = $html(oData); 1151 }; 1152 1153 /** 1154 * Group actions custom datacell formatter 1155 * 1156 * @method renderActions 1157 */ 1158 var renderActions = function renderActions(elCell, oRecord, oColumn, oData) 1159 { 1160 // fire the 'updateGroupClick' event when the group has been clicked 1161 var updateLink = document.createElement("a"); 1162 //updateLink.setAttribute("href", "#"); 1163 Dom.addClass(updateLink, "update"); 1164 updateLink.innerHTML = " "; 1165 YAHOO.util.Event.addListener(updateLink, "click", function(e) 1166 { 1167 YAHOO.Bubbling.fire('updateGroup', 1168 { 1169 group: oRecord.getData("shortName"), 1170 groupDisplayName: oRecord.getData("displayName"), 1171 query: this.query 1172 }); 1173 }, null, parent); 1174 elCell.appendChild(updateLink); 1175 1176 // 1177 var deleteLink = document.createElement("a"); 1178 //deleteLink.setAttribute("href", "#"); 1179 Dom.addClass(deleteLink, "delete"); 1180 deleteLink.innerHTML = " "; 1181 YAHOO.util.Event.addListener(deleteLink, "click", function(e) 1182 { 1183 me._confirmDeleteGroup( 1184 oRecord.getData("shortName"), 1185 null, 1186 oRecord.getData("displayName"), 1187 null, 1188 null); 1189 }); 1190 elCell.appendChild(deleteLink); 1191 }; 1192 1193 // DataTable column defintions 1194 var columnDefinitions = 1195 [ 1196 { key: "shortName", label: parent._msg("label.shortname"), sortable: true, formatter: renderCellSafeHTML }, 1197 { key: "displayName", label: parent._msg("label.displayname"), sortable: true, formatter: renderCellSafeHTML }, 1198 { key: "actions", label: parent._msg("label.actions"), sortable: false, formatter: renderActions } 1199 ]; 1200 1201 // DataTable definition 1202 this.widgets.dataTable = new YAHOO.widget.DataTable(parent.id + "-datatable", columnDefinitions, this.widgets.dataSource, 1203 { 1204 initialLoad: false, 1205 renderLoopSize: 32, 1206 sortedBy: 1207 { 1208 key: "displayName", 1209 dir: "asc" 1210 }, 1211 MSG_EMPTY: parent._msg("message.empty") 1212 }); 1213 }, 1214 1215 /** 1216 * Resets the YUI DataTable errors to our custom messages 1217 * NOTE: Scope could be YAHOO.widget.DataTable, so can't use "this" 1218 * 1219 * @method _setDefaultDataTableErrors 1220 * @param dataTable Instance of the DataTable 1221 * @private 1222 */ 1223 _setDefaultDataTableErrors: function ConsoleGroups_SearchPanelHandler__setDefaultDataTableErrors(dataTable) 1224 { 1225 dataTable.set("MSG_EMPTY", parent._msg("message.empty", "Alfresco.ConsoleGroups")); 1226 dataTable.set("MSG_ERROR", parent._msg("message.error", "Alfresco.ConsoleGroups")); 1227 }, 1228 1229 /** 1230 * Build URI parameters for People List JSON data webscript 1231 * 1232 * @method _buildSearchParams 1233 * @param query User search term 1234 * @private 1235 */ 1236 _buildSearchParams: function ConsoleGroups_SearchPanelHandler__buildSearchParams(query) 1237 { 1238 var query = "shortNameFilter=" + encodeURIComponent(query); 1239 var showAll = Dom.get(parent.id + "-show-all").checked; 1240 return showAll ? query : query + "&zone=APP.DEFAULT"; 1241 }, 1242 1243 /** 1244 * Set the message in the Results Bar area 1245 * 1246 * @method _setResultsMessage 1247 * @param messageId The messageId to display 1248 * @private 1249 */ 1250 _setResultsMessage: function ConsoleGroups_SearchPanelHandler__setResultsMessage(messageId, arg1, arg2) 1251 { 1252 var resultsDiv = Dom.get(parent.id + "-search-bar-text"); 1253 resultsDiv.innerHTML = parent._msg(messageId, arg1, arg2); 1254 } 1255 }); 1256 this.panelHandlers.searchPanelHandler = new SearchPanelHandler(); 1257 1258 /* Create Group Panel Handler */ 1259 CreatePanelHandler = function CreatePanelHandler_constructor() 1260 { 1261 CreatePanelHandler.superclass.constructor.call(this, "create"); 1262 }; 1263 1264 YAHOO.extend(CreatePanelHandler, Alfresco.ConsolePanelHandler, 1265 { 1266 /** 1267 * INSTANCE VARIABLES 1268 */ 1269 1270 /** 1271 * Keeps track if this panel is visble or not 1272 * 1273 * @property _visible 1274 * @type Boolean 1275 */ 1276 _visible: false, 1277 1278 /** 1279 * Keeps track if this panel shall request the view panel to refresh after a cancel click 1280 * 1281 * @property _refresh 1282 * @type Boolean 1283 */ 1284 _refresh: false, 1285 1286 /** 1287 * PANEL LIFECYCLE CALLBACKS 1288 */ 1289 1290 /** 1291 * Called by the ConsolePanelHandler when this panel shall be loaded 1292 * 1293 * @method onLoad 1294 */ 1295 onLoad: function ConsoleGroups_CreatePanelHandler_onLoad() 1296 { 1297 // Buttons 1298 this.widgets.creategroupOkButton = new YAHOO.widget.Button(parent.id + "-creategroup-ok-button", 1299 { 1300 type: "button" 1301 }); 1302 this.widgets.creategroupOkButton.on("click", this.onCreateGroupOKClick, null, this); 1303 this.widgets.creategroupOkButton.set("disabled", true); 1304 1305 this.widgets.creategroupAnotherButton = new YAHOO.widget.Button(parent.id + "-creategroup-another-button", 1306 { 1307 type: "button" 1308 }); 1309 this.widgets.creategroupAnotherButton.on("click", this.onCreateGroupAnotherClick, null, this); 1310 this.widgets.creategroupAnotherButton.set("disabled", true); 1311 1312 this.widgets.creategroupCancelButton = new YAHOO.widget.Button(parent.id + "-creategroup-cancel-button", 1313 { 1314 type: "button" 1315 }); 1316 this.widgets.creategroupCancelButton.on("click", this.onCreateGroupCancelClick, null, this); 1317 1318 // Form definition 1319 var form = new Alfresco.forms.Form(parent.id + "-create-form"); 1320 form.setSubmitElements([this.widgets.creategroupOkButton, this.widgets.creategroupAnotherButton]); 1321 form.setShowSubmitStateDynamically(true); 1322 1323 // Form field validation 1324 form.addValidation(parent.id + "-create-shortname", Alfresco.forms.validation.mandatory, null, "keyup"); 1325 form.addValidation(parent.id + "-create-shortname", Alfresco.forms.validation.nodeName, null, "keyup"); 1326 form.addValidation(parent.id + "-create-shortname", Alfresco.forms.validation.length, 1327 { 1328 min: 3, 1329 max: 100, 1330 crop: true, 1331 includeWhitespace: false 1332 }, "keyup"); 1333 form.addValidation(parent.id + "-create-displayname", Alfresco.forms.validation.mandatory, null, "keyup"); 1334 form.addValidation(parent.id + "-create-displayname", Alfresco.forms.validation.length, 1335 { 1336 min: 3, 1337 max: 255, 1338 crop: true, 1339 includeWhitespace: false 1340 }, "keyup"); 1341 1342 // Initialize form 1343 form.init(); 1344 this.forms.createForm = form; 1345 1346 }, 1347 1348 /** 1349 * Called by the ConsolePanelHandler when this panel shall be loaded 1350 * 1351 * @method onBeforeShow 1352 */ 1353 onBeforeShow: function ConsoleGroups_CreatePanelHandler_onBeforeShow() 1354 { 1355 // Hide the main panel area before it is displayed - so we don't show 1356 // old data to the user before the onShow() method paints the results 1357 Dom.setStyle(parent.id + "-create-main", "visibility", "hidden"); 1358 this.clear(); 1359 }, 1360 1361 /** 1362 * Clears the form fields, makes sure buttons are in correct state and sets focus 1363 * 1364 * @method clear 1365 */ 1366 clear: function clear() 1367 { 1368 Dom.get(parent.id + "-create-shortname").value = ""; 1369 Dom.get(parent.id + "-create-displayname").value = ""; 1370 if (this.forms.createForm !== null) 1371 { 1372 this.forms.createForm.init(); 1373 } 1374 }, 1375 1376 /** 1377 * Called by the ConsolePanelHandler when this panel is shown 1378 * 1379 * @method onShow 1380 */ 1381 onShow: function ConsoleGroups_CreatePanelHandler_onShow() 1382 { 1383 this._visible = true; 1384 this._refresh = false; 1385 window.scrollTo(0, 0); 1386 1387 // Make main panel area visible 1388 Dom.setStyle(parent.id + "-create-main", "visibility", "visible"); 1389 1390 Dom.get(parent.id + "-create-shortname").focus(); 1391 }, 1392 1393 /** 1394 * Called by the ConsolePanelHandler when this panel is hidden 1395 * 1396 * @method onHide 1397 */ 1398 onHide: function ConsoleGroups_CreatePanelHandler_onHide() 1399 { 1400 this._visible = false; 1401 }, 1402 1403 /** 1404 * BUTTON EVENT HANDLERS 1405 */ 1406 1407 /** 1408 * Fired when the Create Group OK button is clicked. 1409 * 1410 * @method onCreateGroupOKClick 1411 * @param e DomEvent 1412 * @param args Event parameters (depends on event type) 1413 */ 1414 onCreateGroupOKClick: function ConsoleGroups_CreatePanelHandler_onCreateGroupOKClick(e, args) 1415 { 1416 var successHandler = function(response) 1417 { 1418 window.scrollTo(0, 0); 1419 Alfresco.util.PopupManager.displayMessage( 1420 { 1421 text: parent._msg("message.create-success") 1422 }); 1423 parent.refreshUIState( 1424 { 1425 "panel": "search", 1426 "refresh": "true" 1427 }); 1428 }; 1429 this._createGroup(successHandler); 1430 }, 1431 1432 /** 1433 * Fired when the Create Group Cancel button is clicked. 1434 * 1435 * @method onCreateGroupCancelClick 1436 * @param e {object} DomEvent 1437 * @param args {array} Event parameters (depends on event type) 1438 */ 1439 onCreateGroupCancelClick: function ConsoleGroups_CreatePanelHandler_onCreateGroupCancelClick(e, args) 1440 { 1441 parent.refreshUIState( 1442 { 1443 "panel": "search", 1444 "refresh": this._refresh ? "true" : "false" 1445 }); 1446 }, 1447 1448 /** 1449 * Fired when the Create Another Group button is clicked. 1450 * 1451 * @method onCreateGroupAnotherClick 1452 * @param e DomEvent 1453 * @param args Event parameters (depends on event type) 1454 */ 1455 onCreateGroupAnotherClick: function ConsoleGroups_CreatePanelHandler_onCreateGroupAnotherClick(e, args) 1456 { 1457 var successHandler = function(response) 1458 { 1459 // Scroll to top and notify user 1460 window.scrollTo(0, 0); 1461 Alfresco.util.PopupManager.displayMessage( 1462 { 1463 text: parent._msg("message.create-success") 1464 }); 1465 1466 // Make sure we refresh view panel if cancel is clicked 1467 this._refresh = true; 1468 1469 // Clear old values so new ones can be entered 1470 this.clear(); 1471 Dom.get(parent.id + "-create-shortname").focus(); 1472 }; 1473 this._createGroup(successHandler); 1474 }, 1475 1476 /** 1477 * PRIVATE METHODS 1478 */ 1479 1480 /** 1481 * Create a group, but first check if it already exists 1482 * 1483 * @method _createGroup 1484 * @param handler Handler function to be called on successful creation 1485 * @private 1486 */ 1487 _createGroup: function ConsoleGroups_CreatePanelHandler__createGroup(successHandler) 1488 { 1489 var me = this; 1490 var shortName = YAHOO.lang.trim(Dom.get(parent.id + "-create-shortname").value); 1491 parent.getParentGroups(shortName, 1492 { 1493 fn: function(groups) 1494 { 1495 if (groups) 1496 { 1497 // The group alredy existed, now let's see if the identifer already is placed under this group 1498 var alreadyThere = false; 1499 var parentStr = ""; 1500 for (var i = 0; i < groups.length; i++) 1501 { 1502 parentStr += groups[i].displayName + (i < groups.length - 1 ? ", " : ""); 1503 } 1504 parentStr = parentStr.length > 0 ? parentStr : parent._msg("label.theroot"); 1505 Alfresco.util.PopupManager.displayPrompt( 1506 { 1507 text: parent._msg("message.confirm.add", shortName, parentStr, parent.group ? parent.group : parent._msg("label.theroot")), 1508 buttons: [ 1509 { 1510 text: parent._msg("button.ok"), 1511 handler: function ConsoleGroups__createGroup_confirmOk() 1512 { 1513 // Hide Prompt 1514 this.destroy(); 1515 if (parent.group) 1516 { 1517 me._createGroupAfterExistCheck.call(me, successHandler); 1518 } 1519 else 1520 { 1521 // todo implement when webscript api supports it 1522 // This isn't supported by the webscript api yet 1523 Alfresco.util.PopupManager.displayPrompt( 1524 { 1525 title: parent._msg("message.failure"), 1526 text: parent._msg("message.noAddGroupFromRootSupport") 1527 }); 1528 return; 1529 1530 } 1531 } 1532 }, 1533 { 1534 text: parent._msg("button.cancel"), 1535 handler: function ConsoleGroups__createGroup_confirmCancel() 1536 { 1537 // Hide prompt 1538 this.destroy(); 1539 }, 1540 isDefault: true 1541 }] 1542 }); 1543 } 1544 else 1545 { 1546 // Group didn't exist go ahead and create it 1547 me._createGroupAfterExistCheck.call(me, successHandler); 1548 } 1549 }, 1550 scope: this 1551 }, "message.create-failure"); 1552 }, 1553 1554 /** 1555 * Create the group 1556 * 1557 * @method _createGroupAfterExistCheck 1558 * @param handler {function} Handler function to be called on successful creation 1559 * @private 1560 */ 1561 _createGroupAfterExistCheck: function ConsoleGroups_CreatePanelHandler__createGroupAfterExistCheck(successHandler) 1562 { 1563 // gather up the data for our JSON PUT request 1564 var shortName = YAHOO.lang.trim(Dom.get(parent.id + "-create-shortname").value); 1565 var displayName = YAHOO.lang.trim(Dom.get(parent.id + "-create-displayname").value); 1566 displayName = displayName == "" ? undefined : displayName; 1567 var groupObj = {}; 1568 1569 var url = Alfresco.constants.PROXY_URI + "api/"; 1570 var sh = successHandler; 1571 if (parent.group && parent.group.length > 0) 1572 { 1573 url += "groups/" + encodeURIComponent(parent.group) + "/children/GROUP_" + encodeURIComponent(shortName); 1574 sh = function(response) 1575 { 1576 if (displayName && shortName != displayName) 1577 { 1578 /** 1579 * When a group is created by adding it to a parent group its not possible to 1580 * set the displayName in the same call, then another call must be made to 1581 * update the display name. 1582 */ 1583 groupObj.displayName = displayName; 1584 parent.panelHandlers.updatePanelHandler.updateGroupRequest(shortName, groupObj, 1585 { 1586 fn: successHandler, 1587 scope: this 1588 }); 1589 } 1590 else 1591 { 1592 successHandler.call(this, response); 1593 } 1594 }; 1595 } 1596 else 1597 { 1598 url += "rootgroups/" + encodeURIComponent(shortName); 1599 if (displayName) 1600 { 1601 groupObj.displayName = displayName; 1602 } 1603 } 1604 1605 Alfresco.util.Ajax.jsonPost( 1606 { 1607 url: url, 1608 dataObj: groupObj, 1609 successCallback: 1610 { 1611 fn: sh, 1612 scope: this 1613 }, 1614 failureCallback: 1615 { 1616 fn: function(o) 1617 { 1618 var obj = YAHOO.lang.JSON.parse(o.serverResponse.responseText); 1619 Alfresco.util.PopupManager.displayPrompt( 1620 { 1621 title: parent._msg("message.failure"), 1622 text: parent._msg("message.create-failure", obj.message) 1623 }); 1624 }, 1625 scope: this 1626 } 1627 }); 1628 } 1629 1630 }); 1631 this.panelHandlers.createPanelHandler = new CreatePanelHandler(); 1632 1633 1634 /* Update Group Panel Handler */ 1635 UpdatePanelHandler = function UpdatePanelHandler_constructor() 1636 { 1637 UpdatePanelHandler.superclass.constructor.call(this, "update"); 1638 }; 1639 1640 YAHOO.extend(UpdatePanelHandler, Alfresco.ConsolePanelHandler, 1641 { 1642 /** 1643 * INSTANCE VARIABLES 1644 */ 1645 1646 /** 1647 * Keeps track if this panel is visble or not 1648 * 1649 * @property _visible 1650 * @type Boolean 1651 */ 1652 _visible: false, 1653 1654 /** 1655 * PANEL LIFECYCLE CALLBACKS 1656 */ 1657 1658 /** 1659 * Called by the ConsolePanelHandler when this panel shall be loaded 1660 * 1661 * @method onLoad 1662 */ 1663 onLoad: function ConsoleGroups_UpdatePanelHandler_onLoad() 1664 { 1665 // Buttons 1666 this.widgets.updategroupSaveButton = new YAHOO.widget.Button(parent.id + "-updategroup-save-button", 1667 { 1668 type: "button" 1669 }); 1670 this.widgets.updategroupSaveButton.on("click", this.onUpdateGroupOKClick, null, this); 1671 this.widgets.updategroupCancelButton = new YAHOO.widget.Button(parent.id + "-updategroup-cancel-button", 1672 { 1673 type: "button" 1674 }); 1675 this.widgets.updategroupCancelButton.on("click", this.onUpdateGroupCancelClick, null, this); 1676 1677 // Form definition 1678 var form = new Alfresco.forms.Form(parent.id + "-update-form"); 1679 form.setSubmitElements(this.widgets.updategroupSaveButton); 1680 form.setShowSubmitStateDynamically(true); 1681 1682 // Form field validation 1683 form.addValidation(parent.id + "-update-displayname", Alfresco.forms.validation.mandatory, null, "keyup"); 1684 form.addValidation(parent.id + "-update-displayname", Alfresco.forms.validation.length, 1685 { 1686 min: 3, 1687 max: 255, 1688 crop: true, 1689 includeWhitespace: false 1690 }, "keyup"); 1691 1692 // Initialise the form 1693 form.init(); 1694 this.forms.updateForm = form; 1695 }, 1696 1697 /** 1698 * Called by the ConsolePanelHandler just before this panel is about to be shown 1699 * 1700 * @method onBeforeShow 1701 */ 1702 onBeforeShow: function ConsoleGroups_UpdatePanelHandler_onBeforeShow() 1703 { 1704 // Hide the main panel area before it is displayed - so we don't show 1705 // old data to the user before the Update() method paints the results 1706 Dom.setStyle(parent.id + "-update-main", "visibility", "hidden"); 1707 }, 1708 1709 /** 1710 * Called by the ConsolePanelHandler when this panel is shown 1711 * 1712 * @method onShow 1713 */ 1714 onShow: function ConsoleGroups_UpdatePanelHandler_onShow() 1715 { 1716 this._visible = true; 1717 }, 1718 1719 /** 1720 * Called by the ConsolePanelHandler when this panel is hidden 1721 * 1722 * @method onHide 1723 */ 1724 onHide: function ConsoleGroups_UpdatePanelHandler_onHide() 1725 { 1726 this._visible = false; 1727 }, 1728 1729 /** 1730 * Called by the ConsolePanelHandler when this panel shall update its appearance 1731 * 1732 * @method onUpdate 1733 */ 1734 onUpdate: function ConsoleGroups_UpdatePanelHandler_onUpdate() 1735 { 1736 var success = function(o) 1737 { 1738 // Properties section fields 1739 var group = o.json.data; 1740 Dom.get(parent.id + "-update-title").innerHTML = $html(group.displayName); 1741 Dom.get(parent.id + "-update-shortname").innerHTML = $html(group.shortName); 1742 Dom.get(parent.id + "-update-displayname").value = group.displayName; 1743 1744 // Make sure buttons are in the correct state 1745 if (this.forms.updateForm) 1746 { 1747 this.forms.updateForm.init(); 1748 } 1749 1750 // Make main panel area visible and focus 1751 window.scrollTo(0, 0); 1752 Dom.setStyle(parent.id + "-update-main", "visibility", "visible"); 1753 Dom.get(parent.id + "-update-displayname").focus(); 1754 }; 1755 1756 // make an ajax call to get group details 1757 Alfresco.util.Ajax.jsonGet( 1758 { 1759 url: Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(parent.group), 1760 successCallback: 1761 { 1762 fn: success, 1763 scope: this 1764 }, 1765 failureMessage: parent._msg("message.getgroup-failure", $html(parent.group)) 1766 }); 1767 }, 1768 1769 /** 1770 * BUTTON EVENT HANDLERS 1771 */ 1772 1773 /** 1774 * Fired when the Update User OK button is clicked. 1775 * 1776 * @method onUpdateGroupOKClick 1777 * @param e DomEvent 1778 * @param args Event parameters (depends on event type) 1779 */ 1780 onUpdateGroupOKClick: function ConsoleGroups_UpdatePanelHandler_onUpdateGroupOKClick(e, args) 1781 { 1782 var handler = function(res) 1783 { 1784 window.scrollTo(0, 0); 1785 Alfresco.util.PopupManager.displayMessage( 1786 { 1787 text: parent._msg("message.update-success") 1788 }); 1789 1790 var state = {"panel": "search", "refresh": "true"}; 1791 if (parent.query) 1792 { 1793 // If this panel was triggered from the search list, send back the query so the list will be displayed 1794 state.query = parent.query; 1795 } 1796 parent.refreshUIState(state); 1797 }; 1798 this._updateGroup(handler); 1799 }, 1800 1801 /** 1802 * Fired when the Update Group Cancel button is clicked. 1803 * 1804 * @method onUpdateGroupCancelClick 1805 * @param e {object} DomEvent 1806 * @param args {array} Event parameters (depends on event type) 1807 */ 1808 onUpdateGroupCancelClick: function ConsoleGroups_UpdatePanelHandler_onUpdateGroupCancelClick(e, args) 1809 { 1810 var state = {"panel": "search", "refresh": "false"}; 1811 if (parent.query) 1812 { 1813 // If this panel was triggered from the search list, send back the query so the list will be displayed 1814 state.query = parent.query; 1815 } 1816 parent.refreshUIState(state); 1817 }, 1818 1819 /** 1820 * PUBLIC METHODS 1821 */ 1822 1823 /** 1824 * Update a group - returning true on success, false on any error. 1825 * 1826 * @method updateGroupRequest 1827 * @param successCallback {function} Success callback to be called on successful update 1828 * @private 1829 */ 1830 updateGroupRequest: function ConsoleGroups_UpdatePanelHandler_updateGroupRequest(shortName, groupObj, successCallback) 1831 { 1832 Alfresco.util.Ajax.jsonPut( 1833 { 1834 url: Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(shortName), 1835 dataObj: groupObj, 1836 successCallback: successCallback, 1837 failureCallback: 1838 { 1839 fn: function(o) 1840 { 1841 Alfresco.util.PopupManager.displayPrompt( 1842 { 1843 title: parent._msg("message.failure"), 1844 text: parent._msg("message.update-failure", o.json.message) 1845 }); 1846 }, 1847 scope: this 1848 } 1849 }); 1850 }, 1851 1852 /** 1853 * PRIVATE METHODS 1854 */ 1855 1856 /** 1857 * Update a group - returning true on success, false on any error. 1858 * 1859 * @method _updateGroup 1860 * @param successHandler Handler function to be called on successful update 1861 * @private 1862 */ 1863 _updateGroup: function ConsoleGroups_UpdatePanelHandler__updateGroup(successHandler) 1864 { 1865 this.updateGroupRequest(parent.group, 1866 { 1867 displayName: YAHOO.lang.trim(Dom.get(parent.id + "-update-displayname").value) 1868 }, 1869 { 1870 fn: successHandler, 1871 scope: this 1872 }); 1873 } 1874 1875 }); 1876 this.panelHandlers.updatePanelHandler = new UpdatePanelHandler(); 1877 1878 return this; 1879 }; 1880 1881 YAHOO.extend(Alfresco.ConsoleGroups, Alfresco.ConsoleTool, 1882 { 1883 1884 /* STATES */ 1885 1886 /** 1887 * The query to use in a search in the panel 1888 * 1889 * @property query 1890 * @type string 1891 * @default null 1892 */ 1893 query: null, 1894 1895 /** 1896 * Decides if browse panels data needs to be refreshed 1897 * 1898 * @property refresh 1899 * @type boolean 1900 * @default false 1901 */ 1902 refresh: false, 1903 1904 /** 1905 * The current group 1906 * 1907 * @property group 1908 * @type string 1909 * @default null 1910 */ 1911 group: null, 1912 1913 /** 1914 * The display name for the current group 1915 * 1916 * @property groupDisplayName 1917 * @type string 1918 * @default null 1919 */ 1920 groupDisplayName: null, 1921 1922 /** 1923 * Object container for initialization options 1924 * 1925 * @property options 1926 * @type object 1927 */ 1928 options: 1929 { 1930 /** 1931 * Number of characters required for a search. 1932 * 1933 * @property minSearchTermLength 1934 * @type int 1935 * @default 1 1936 */ 1937 minSearchTermLength: 1, 1938 1939 /** 1940 * Maximum number of items to display in the results list 1941 * 1942 * @property maxSearchResults 1943 * @type int 1944 * @default 100 1945 */ 1946 maxSearchResults: 100, 1947 1948 /** 1949 * Maximum number of groups & users to rdisplay at the same time in each column 1950 * 1951 * @property maxPageSize 1952 * @type int 1953 * @default 50 1954 */ 1955 maxPageSize: 50 1956 }, 1957 1958 /** 1959 * Fired by YUI when parent element is available for scripting. 1960 * Component initialisation, including instantiation of YUI widgets and event listener binding. 1961 * 1962 * @method onReady 1963 */ 1964 onReady: function ConsoleGroups_onReady() 1965 { 1966 Alfresco.ConsoleGroups.superclass.onReady.call(this); 1967 }, 1968 1969 /** 1970 * YUI WIDGET EVENT HANDLERS 1971 * Handlers for standard events fired from YUI widgets, e.g. "click" 1972 */ 1973 1974 /** 1975 * History manager state change event handler (override base class) 1976 * 1977 * @method onStateChanged 1978 * @param e {object} DomEvent 1979 * @param args {array} Event parameters (depends on event type) 1980 */ 1981 onStateChanged: function ConsoleGroups_onStateChanged(e, args) 1982 { 1983 // Clear old states 1984 this.query = undefined; 1985 this.refresh = undefined; 1986 this.group = undefined; 1987 this.groupDisplayName = undefined; 1988 1989 var state = this.decodeHistoryState(args[1].state); 1990 if (state.query !== undefined) 1991 { 1992 this.query = state.query; 1993 } 1994 if (state.refresh) 1995 { 1996 this.refresh = state.refresh == "true" ? true : false; 1997 } 1998 if (state.group) 1999 { 2000 this.group = state.group; 2001 } 2002 if (state.groupDisplayName) 2003 { 2004 this.groupDisplayName = state.groupDisplayName; 2005 } 2006 if (state.showAll) 2007 { 2008 this.showAll = state.showAll == "true" ? true : false; 2009 // reset group browser url 2010 var rootUrl = Alfresco.constants.PROXY_URI + "api/rootgroups" + 2011 (this.showAll ? "" : "?zone=APP.DEFAULT"); 2012 this.panelHandlers.searchPanelHandler.widgets.columnbrowser.load([rootUrl] , true); 2013 } 2014 2015 // test if panel has actually changed? 2016 if (state.panel) 2017 { 2018 this.showPanel(state.panel); 2019 } 2020 2021 if (this.currentPanelId === "search") 2022 { 2023 this.updateCurrentPanel(); 2024 } 2025 else if (this.currentPanelId === "create" || 2026 (state.group && (this.currentPanelId === "view" || this.currentPanelId === "update"))) 2027 { 2028 this.updateCurrentPanel(); 2029 } 2030 }, 2031 2032 /** 2033 * New Group event handler 2034 * 2035 * @method onNewGroup 2036 * @param e {object} DomEvent 2037 * @param args {array} Event parameters (depends on event type) 2038 */ 2039 onNewGroup: function ConsoleGroups_onNewGroup(e, args) 2040 { 2041 var parentGroup = args[1].group; 2042 this.refreshUIState( 2043 { 2044 "panel": "create", 2045 "group": parentGroup 2046 }); 2047 }, 2048 2049 /** 2050 * Update Group event handler 2051 * 2052 * @method onUpdateGroup 2053 * @param e {object} DomEvent 2054 * @param args {array} Event parameters (depends on event type) 2055 */ 2056 onUpdateGroup: function ConsoleGroups_onUpdateGroup(e, args) 2057 { 2058 var group = args[1].group; 2059 var query = args[1].query; 2060 var state = { 2061 "panel": "update", 2062 "group": group 2063 }; 2064 // Remember query if cancel is clicked 2065 if (query) 2066 { 2067 state.query = query; 2068 } 2069 this.refreshUIState(state); 2070 }, 2071 2072 /** 2073 * Encode state object into a packed string for use as url history value. 2074 * Override base class. 2075 * 2076 * @method encodeHistoryState 2077 * @param obj {object} state object 2078 * @private 2079 */ 2080 encodeHistoryState: function ConsoleGroups_encodeHistoryState(obj) 2081 { 2082 // wrap up current state values 2083 var stateObj = {}; 2084 if (this.currentPanelId !== "") 2085 { 2086 stateObj.panel = this.currentPanelId; 2087 } 2088 2089 // convert to encoded url history state - overwriting with any supplied values 2090 var state = ""; 2091 if (obj.panel || stateObj.panel) 2092 { 2093 state += "panel=" + encodeURIComponent(obj.panel ? obj.panel : stateObj.panel); 2094 } 2095 if (obj.group) 2096 { 2097 state += state.length > 0 ? "&" : ""; 2098 state += "group=" + encodeURIComponent(obj.group); 2099 } 2100 if (obj.query !== undefined) 2101 { 2102 state += state.length > 0 ? "&" : ""; 2103 state += "query=" + encodeURIComponent(obj.query); 2104 } 2105 if (obj.refresh) 2106 { 2107 state += state.length > 0 ? "&" : ""; 2108 state += "refresh=" + encodeURIComponent(obj.refresh); 2109 } 2110 if (obj.showAll !== undefined) 2111 { 2112 state += state.length > 0 ? "&" : ""; 2113 state += "showAll=" + encodeURIComponent(obj.showAll); 2114 } 2115 return state; 2116 }, 2117 2118 /** 2119 * Helper method for getting the parent groups for group with identifier shortName 2120 * 2121 * @method _getParentGroups 2122 * @param shortName the group identifier 2123 * @param successCallback Callback object Called with the groups as the argument or null if group doesn't exist 2124 * @param failureMessage Displayed if an error (other than 404) occurs 2125 */ 2126 getParentGroups: function ConsoleGroups_getParentGroups(shortName, successCallback, failureMessage) 2127 { 2128 Alfresco.util.Ajax.jsonGet( 2129 { 2130 url: Alfresco.constants.PROXY_URI + "api/groups/" + encodeURIComponent(shortName) + "/parents?level=ALL&maxSize=10", 2131 successCallback: 2132 { 2133 fn: function(o) 2134 { 2135 var groups = o.json.data ? o.json.data : []; 2136 2137 // Since we do 2138 successCallback.fn.call(successCallback.scope ? successCallback.scope : this, groups); 2139 }, 2140 scope: this 2141 }, 2142 failureCallback: 2143 { 2144 fn: function(o) 2145 { 2146 if (o.serverResponse.status == 404) 2147 { 2148 // group didn't exist just continue 2149 successCallback.fn.call(successCallback.scope ? successCallback.scope : this, null); 2150 } 2151 else 2152 { 2153 // Notify the user that an error occured 2154 Alfresco.util.PopupManager.displayPrompt( 2155 { 2156 title: this._msg("message.failure"), 2157 text: this._msg(failureMessage, o.json.message) 2158 }); 2159 } 2160 }, 2161 scope: this 2162 } 2163 }); 2164 }, 2165 2166 /** 2167 * Gets a custom message 2168 * 2169 * @method _msg 2170 * @param messageId {string} The messageId to retrieve 2171 * @return {string} The custom message 2172 * @private 2173 */ 2174 _msg: function ConsoleGroups__msg(messageId) 2175 { 2176 return Alfresco.util.message.call(this, messageId, "Alfresco.ConsoleGroups", Array.prototype.slice.call(arguments).slice(1)); 2177 } 2178 }); 2179 })();