API: Subsite support for menu of cms (hide admins that don't declare support) (fixes #101 and #89 )

* Hide admins without subsite support from subsites menu
* Add subsite support to default site areas
* Enable reloading of subsites switcher dropdown when navigating the
site, and when editing subsite areas

API Fix parallel pjax menu fetching for subsites.
- thanks Mateusz!

Delint LeftAndMain_Subsites.js
This commit is contained in:
Naomi Guyer 2013-08-22 13:02:46 +12:00
parent 2d41dc62bf
commit 37843f447e
10 changed files with 237 additions and 86 deletions

View File

@ -17,3 +17,12 @@ ErrorPage::add_extension('ErrorPageSubsite');
SiteConfig::add_extension('SiteConfigSubsites');
SS_Report::add_excluded_reports('SubsiteReportWrapper');
//Display in cms menu
AssetAdmin::add_extension('SubsiteMenuExtension');
SecurityAdmin::add_extension('SubsiteMenuExtension');
CMSMain::add_extension('SubsiteMenuExtension');
CMSPagesController::add_extension('SubsiteMenuExtension');
SubsiteAdmin::add_extension('SubsiteMenuExtension');
CMSSettingsController::add_extension('SubsiteMenuExtension');

View File

@ -29,4 +29,18 @@ class SubsiteAdmin extends ModelAdmin {
return $form;
}
public function getResponseNegotiator() {
$negotiator = parent::getResponseNegotiator();
$self = $this;
// Register a new callback
$negotiator->setCallback('SubsiteList', function() use(&$self) {
return $self->SubsiteList();
});
return $negotiator;
}
public function SubsiteList() {
return $this->renderWith('SubsiteList');
}
}

View File

@ -35,7 +35,17 @@ class FileSubsites extends DataExtension {
$values[$site->ID] = $site->Title;
}
ksort($values);
if($sites)$fields->push(new DropdownField('SubsiteID', 'Subsite', $values));
if($sites){
//Dropdown needed to move folders between subsites
$fields->push($dropdown = new DropdownField('SubsiteID', 'Subsite', $values));
$fields->push(new LiteralField(
'Message',
'<p class="message notice">'.
_t('ASSETADMIN.SUBSITENOTICE', 'Folders and files created in the main site are accessible by all subsites.')
.'</p>'
));
$dropdown->addExtraClass('subsites-move-dropdown');
}
}
}

View File

@ -51,6 +51,9 @@ class LeftAndMainSubsites extends Extension {
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
}
/*
* Returns a list of the subsites accessible to the current user
*/
public function Subsites() {
// figure out what permission the controller needs
// Subsite::accessible_sites() expects something, so if there's no permission
@ -64,76 +67,74 @@ class LeftAndMainSubsites extends Extension {
}
}
switch($this->owner->class) {
case "AssetAdmin":
$subsites = Subsite::accessible_sites($permission, true, "Shared files & images");
break;
case "SecurityAdmin":
$subsites = Subsite::accessible_sites($permission, true, "Groups accessing all sites");
if($subsites->find('ID',0)) {
$subsites->push(new ArrayData(array('Title' => 'All groups', 'ID' => -1)));
}
break;
case "CMSMain":
case "CMSPagesController":
// If there's a default site then main site has no meaning
$showMainSite = !DataObject::get_one('Subsite',"\"DefaultSite\"=1");
$subsites = Subsite::accessible_sites($permission, $showMainSite);
break;
case "SubsiteAdmin":
$subsites = Subsite::accessible_sites('ADMIN', true);
break;
default:
$subsites = Subsite::accessible_sites($permission);
break;
}
return $subsites;
return Subsite::accessible_sites($permission);
}
public function SubsiteList() {
/*
* Generates a list of subsites with the data needed to
* produce a dropdown site switcher
* @return ArrayList
*/
public function ListSubsites(){
$list = $this->Subsites();
$currentSubsiteID = Subsite::currentSubsiteID();
if($list->Count() > 1) {
$output = '<div class="field dropdown">';
$output .= '<select id="SubsitesSelect">';
foreach($list as $subsite) {
$selected = $subsite->ID == $currentSubsiteID ? ' selected="selected"' : '';
$output .= "\n<option value=\"{$subsite->ID}\"$selected>". Convert::raw2xml($subsite->Title) . "</option>";
}
$output .= '</select></div>';
Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
return $output;
} elseif($list->Count() == 1) {
if($list->First()->DefaultSite==false) {
$output = '<div class="field dropdown">';
$output .= '<select id="SubsitesSelect">';
$output .= "\n<option value=\"0\">". _t('LeftAndMainSubsites.DEFAULT_SITE', 'Default site') . "</option>";
foreach($list as $subsite) {
$selected = $subsite->ID == $currentSubsiteID ? ' selected="selected"' : '';
$output .= "\n<option value=\"{$subsite->ID}\"$selected>". Convert::raw2xml($subsite->Title) . "</option>";
}
$output .= '</select></div>';
Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
return $output;
} else {
return '<span>'.$list->First()->Title.'</span>';
}
if($list == null || $list->Count() == 1 && $list->First()->DefaultSite == true){
return false;
}
}
Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
$output = new ArrayList();
foreach($list as $subsite) {
$CurrentState = $subsite->ID == $currentSubsiteID ? 'selected' : '';
$output->push(new ArrayData(array(
'CurrentState' => $CurrentState,
'ID' => $subsite->ID,
'Title' => Convert::raw2xml($subsite->Title)
)));
}
return $output;
}
/*
* Returns a subset of the main menu, filtered by admins that have
* a subsiteCMSShowInMenu method returning true
*
* @return ArrayList
*/
public function SubsiteMainMenu(){
if(Subsite::currentSubsiteID() == 0){
return $this->owner->MainMenu();
}
// loop main menu items, add all items that have subsite support
$mainMenu = $this->owner->MainMenu();
$subsitesMenu = new ArrayList();
foreach($mainMenu as $menuItem){
$controllerName = $menuItem->MenuItem->controller;
if(class_exists($controllerName)){
$controller = singleton($controllerName);
if($controller->hasMethod('subsiteCMSShowInMenu') && $controller->subsiteCMSShowInMenu()){
$subsitesMenu->push($menuItem);
}
}
if($menuItem->Code == 'Help'){
$subsitesMenu->push($menuItem);
}
}
return $subsitesMenu;
}
public function CanAddSubsites() {
return Permission::check("ADMIN", "any", null, "all");
}

View File

@ -0,0 +1,19 @@
<?php
/*
* Simple extension to show admins in the menu of subsites.
* If an admin area should be available to a subsite, you can attach
* this class to your admin in config. eg:
*
* MyAdmin::add_extension('SubsiteMenuExtension');
*
* Or you can include the subsiteCMSShowInMenu function in your admin class and have it return true
*/
class SubsiteMenuExtension extends Extension{
public function subsiteCMSShowInMenu(){
return true;
}
}

View File

@ -219,7 +219,7 @@ class Subsite extends DataObject implements PermissionProvider {
asort($pageTypeMap);
$fields = new FieldList(
new TabSet('Root',
$subsiteTabs = new TabSet('Root',
new Tab('Configuration',
new HeaderField($this->getClassName() . ' configuration', 2),
new TextField('Title', 'Name of subsite:', $this->Title),
@ -252,6 +252,8 @@ class Subsite extends DataObject implements PermissionProvider {
new HiddenField('IsSubsite', '', 1)
);
$subsiteTabs->addExtraClass('subsite-model');
$this->extend('updateCMSFields', $fields);
return $fields;
}

View File

@ -81,3 +81,11 @@ body.SubsiteAdmin .right form #URL .fieldgroup * {
.cms-add-form #PageType li .class-SubsitesVirtualPage, .class-SubsitesVirtualPage a .jstree-pageicon {
background-position: 0 -32px !important;
}
.subsites-move-dropdown{
display:none;
}
#Root_DetailsView .subsites-move-dropdown{
display:block;
}

View File

@ -1,7 +1,89 @@
/*jslint browser: true, nomen: true*/
/*global $, window, jQuery*/
(function($) {
'use strict';
$.entwine('ss', function($) {
$('#SubsitesSelect').live('change', function() {
window.location.search=$.query.set('SubsiteID', $(this).val());
$('#SubsitesSelect').entwine({
onadd:function(){
this.on('change', function(){
window.location.search=$.query.set('SubsiteID', $(this).val());
});
}
});
$('.cms-container').entwine({
SubsiteCurrentXHR: null,
/**
* LeftAndMain does not give us possibility to parallel-fetch a PJAX fragment.
* We provide our own fetcher that bypasses the history - that's because we
* don't want to load a panel, but rather just a subsite dropdown.
*/
subsiteFetchPjaxFragment: function(url, pjaxFragment) {
// Make sure only one subsite XHR request is ongoing.
if(this.getSubsiteCurrentXHR()){
this.getSubsiteCurrentXHR().abort();
}
var self = this,
xhr,
headers = {},
baseUrl = $('base').attr('href');
url = $.path.isAbsoluteUrl(url) ? url : $.path.makeUrlAbsolute(url, baseUrl);
headers['X-Pjax'] = pjaxFragment;
xhr = $.ajax({
headers: headers,
url: url,
complete: function() {
self.setSubsiteCurrentXHR(null);
},
success: function(data, status, xhr) {
self.handleAjaxResponse(data, status, xhr, null);
}
});
this.setSubsiteCurrentXHR(xhr);
}
});
/*
* Reload subsites dropdown when links are processed
*/
$('.cms-container .cms-menu-list li a').entwine({
onclick: function(e) {
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
this._super(e);
}
});
/*
* Reload subsites dropdown when the admin area reloads (for deleting sites)
*/
$('.cms-container .SubsiteAdmin .cms-edit-form fieldset.ss-gridfield').entwine({
onreload: function(e) {
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
this._super(e);
}
});
/*
* Reload subsites dropdown when subsites are added or names are modified
*/
$('.cms-container .cms-content-fields .subsite-model').entwine({
onadd: function(e) {
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
this._super(e);
}
});
// Subsite tab of Group editor
@ -72,7 +154,9 @@
onafterIframeAdjustedForPreview: function(event, doc) {
var subsiteId = $(doc).find('meta[name=x-subsite-id]').attr('content');
if (!subsiteId) return;
if (!subsiteId) {
return;
}
// Inject the SubsiteID into internal links.
$(doc).find('a').each(function() {
@ -95,11 +179,7 @@
}
});
}
});
});
})(jQuery);
}(jQuery));

View File

@ -0,0 +1,9 @@
<div class="cms-subsites" data-pjax-fragment="SubsiteList">
<div class="field dropdown">
<select id="SubsitesSelect">
<% loop $ListSubsites %>
<option value="$ID" $CurrentState>$Title</option>
<% end_loop %>
</select>
</div>
</div>

View File

@ -2,33 +2,32 @@
<div class="cms-logo-header north">
<div class="cms-logo">
<a href="$ApplicationLink" target="_blank" title="$ApplicationName (Version - $CMSVersion)">
$ApplicationName <% if CMSVersion %><abbr class="version">$CMSVersion</abbr><% end_if %>
$ApplicationName <% if $CMSVersion %><abbr class="version">$CMSVersion</abbr><% end_if %>
</a>
<span><% if SiteConfig %>$SiteConfig.Title<% else %>$ApplicationName<% end_if %></span>
<span><% if $SiteConfig %>$SiteConfig.Title<% else %>$ApplicationName<% end_if %></span>
</div>
<div class="cms-login-status">
<a href="Security/logout" class="logout-link" title="<% _t('LeftAndMain_Menu.ss.LOGOUT','Log out') %>"><% _t('LeftAndMain_Menu.ss.LOGOUT','Log out') %></a>
<% with CurrentMember %>
<% with $CurrentMember %>
<span>
<% _t('LeftAndMain_Menu.ss.Hello','Hi') %>
<a href="{$AbsoluteBaseURL}admin/myprofile" class="profile-link ss-ui-dialog-link" data-popupclass="edit-profile-popup">
<% if FirstName && Surname %>$FirstName $Surname<% else_if FirstName %>$FirstName<% else %>$Email<% end_if %>
<a href="{$AbsoluteBaseURL}admin/myprofile" class="profile-link">
<% if $FirstName && $Surname %>$FirstName $Surname<% else_if $FirstName %>$FirstName<% else %>$Email<% end_if %>
</a>
</span>
<% end_with %>
</div>
<div class="cms-subsites">
$SubsiteList
</div>
<% if $ListSubsites %>
<% include SubsiteList %>
<% end_if %>
</div>
<div class="cms-panel-content center">
<ul class="cms-menu-list">
<% loop MainMenu %>
<li class="$LinkingMode $FirstLast <% if LinkingMode == 'link' %><% else %>opened<% end_if %>" id="Menu-$Code" title="$Title.ATT">
<a href="$Link" <% if Code == 'Help' %>target="_blank"<% end_if%>>
<% loop $SubsiteMainMenu %>
<li class="$LinkingMode $FirstLast <% if $LinkingMode == 'link' %><% else %>opened<% end_if %>" id="Menu-$Code" title="$Title.ATT">
<a href="$Link" <% if $Code == 'Help' %>target="_blank"<% end_if %>>
<span class="icon icon-16 icon-{$Code.LowerCase}">&nbsp;</span>
<span class="text">$Title</span>
</a>