Skip to content

Commit

Permalink
ENHANCEMENT New CMSPreviewable interface class to standardize metadat…
Browse files Browse the repository at this point in the history
…a making a record previewable by the CMS.

ENHANCEMENT New "preview" and "edit" buttons to toggle between preview and cms views. Reinstated utility links to switch between draft and live preview (based on SilverStripeNavigator) (formerly called "AjaxSwitchView")
  • Loading branch information
chillu committed Aug 12, 2011
1 parent c06d52d commit 4461cae
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 270 deletions.
25 changes: 25 additions & 0 deletions admin/code/CMSPreviewable.php
@@ -0,0 +1,25 @@
<?php
/**
* Interface to provide enough information about a record to make it previewable
* through the CMS. It uses the record database ID, its "frontend" and "backend" links
* to link up the edit form with its preview.
*
* Also used by {@link SilverStripeNavigator} to generate links -
* both within the CMS preview, and as a frontend utility
* for logged-in CMS authors in custom themes (with the $SilverStripeNavigator template marker).
*/
interface CMSPreviewable {

/**
* @return String Absolute URL to the end-user view for this record.
* Example: http://mysite.com/my-record
*/
function Link();

/**
* @return String Absolute URL to the CMS-author view. Should point to a controller subclassing {@link LeftAndMain}.
* Example: http://mysite.com/admin/edit/6
*/
function CMSEditLink();

}
28 changes: 23 additions & 5 deletions admin/code/LeftAndMain.php
Expand Up @@ -421,11 +421,7 @@ public function show($request) {
} else {
$content = $this->renderWith($this->getViewer('show'));
}

if($this->ShowSwitchView()) {
$content .= '<div id="AjaxSwitchView">' . $this->SwitchView() . '</div>';
}


return $content;
}

Expand Down Expand Up @@ -844,6 +840,13 @@ public function getEditForm($id = null, $fields = null) {
) {
$fields->push(new HiddenField('ParentID'));
}

// Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load
if(in_array('CMSPreviewable', class_implements($record))) {
$navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator());
$navField->setAllowHTML(true);
$fields->push($navField);
}

if($record->hasMethod('getAllCMSActions')) {
$actions = $record->getAllCMSActions();
Expand Down Expand Up @@ -1058,6 +1061,21 @@ public function printable() {
);
}

/**
* Used for preview controls, mainly links which switch between different states of the page.
*
* @return ArrayData
*/
function getSilverStripeNavigator() {
$page = $this->currentPage();
if($page) {
$navigator = new SilverStripeNavigator($page);
return $navigator->renderWith($this->getTemplatesWithSuffix('_SilverStripeNavigator'));
} else {
return false;
}
}

/**
* Identifier for the currently shown record,
* in most cases a database ID. Inspects the following
Expand Down
4 changes: 4 additions & 0 deletions admin/code/ModelAdmin.php
Expand Up @@ -942,6 +942,10 @@ public function EditForm() {
$fields = $this->currentRecord->getCMSFields();
$fields->push(new HiddenField("ID"));

if($this->currentRecord->hasMethod('Link')) {
$fields->push(new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator()));
}

$validator = ($this->currentRecord->hasMethod('getCMSValidator')) ? $this->currentRecord->getCMSValidator() : new RequiredFields();
$validator->setJavascriptValidationHandler('none');

Expand Down
389 changes: 192 additions & 197 deletions admin/css/screen.css

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions admin/javascript/LeftAndMain.EditForm.js
Expand Up @@ -68,6 +68,14 @@
// TODO validation shouldnt need a special case
statusMessage(ss.i18n._t('ModelAdmin.VALIDATIONERROR', 'Validation Error'), 'bad');
}

// Move navigator to preview if one is available.
// If not, just leave the links in the form.
var previewEl = $('.cms-preview');
if(previewEl.length) {
// TODO Relies on DOM element order (the second .cms-navigator is the "old" one)
previewEl.find('.cms-preview-controls').html(this.find('.cms-navigator').detach());
}

this._super();
},
Expand Down
61 changes: 49 additions & 12 deletions admin/javascript/LeftAndMain.Preview.js
Expand Up @@ -11,9 +11,8 @@
* Relies on the server responses to indicate if a preview URL is available for the currently loaded
* admin interface. If no preview is available, the panel is "blocked" automatically.
*
* When a CMS user is logged in, all page views are redirected to the same view in the CMS,
* with the preview window expanded. All internal links in the preview iframe are
* automatically rewritten to point to the version without the CMS via ?cms-preview-expanded=1.
* Internal links within the preview iframe trigger a refresh of the admin panel as well,
* while all external links are disabled (via JavaScript).
*/
$('.cms-preview').entwine({

Expand All @@ -33,7 +32,6 @@
this.setSharedWidth(500);

// Create layout and controls
this.prepend('<div class="cms-preview-toggle west"><a href="#">&laquo;</a></div>');
this.find('iframe').addClass('center');
this.layout({type: 'border'});

Expand Down Expand Up @@ -82,8 +80,12 @@
loadUrl: function(url) {
this.find('iframe').attr('src', url);
},

loadCurrentPage: function() {

/**
* Loads the matching edit form for a page viewed in the preview iframe,
* based on metadata sent along with this document.
*/
loadCurrentPage: function() {
var doc = this.find('iframe')[0].contentDocument,
containerEl = this.getLayoutContainer(),
contentEl = containerEl.find('.cms-content');
Expand All @@ -92,10 +94,12 @@
if(!contentEl.hasClass('CMSMain') || contentEl.hasClass('CMSPagesController') || contentEl.hasClass('CMSSettingsController')) return;

// Load this page in the admin interface if appropriate
var id = $(doc).find('meta[name=x-page-id]').attr('content'), contentPanel = $('.cms-content');
var id = $(doc).find('meta[name=x-page-id]').attr('content'),
editLink = $(doc).find('meta[name=x-cms-edit-link]').attr('content'),
contentPanel = $('.cms-content');
// TODO Remove hardcoding
if(id && contentPanel.find(':input[name=ID]').val() != id) {
window.History.pushState({}, '', 'admin/page/edit/show/' + id);
window.History.pushState({}, '', editLink);
}
},

Expand All @@ -119,9 +123,12 @@
// this.css('overflow', 'auto');
contentEl.removeClass('center').hide();
this.find('iframe').show();
containerEl.find('.cms-menu').collapsePanel();
this.find('.cms-preview-toggle a').html('&raquo;');
containerEl.redraw();
this.find('.cms-preview-controls').show();
containerEl.find('.cms-menu').collapsePanel();

// Already triggered through panel toggle above
// containerEl.redraw();
},

collapse: function() {
Expand All @@ -130,9 +137,12 @@
// this.css('overflow', 'hidden');
contentEl.addClass('center').show();
this.find('iframe').hide();
containerEl.find('.cms-menu').expandPanel();
this.find('.cms-preview-toggle a').html('&laquo;');
containerEl.redraw();
this.find('.cms-preview-controls').hide();
containerEl.find('.cms-menu').expandPanel();

// Already triggered through panel toggle above
// containerEl.redraw();
},

block: function() {
Expand All @@ -149,6 +159,9 @@

toggle: function(bool) {
this[this.hasClass('is-collapsed') ? 'expand' : 'collapse']();
},
redraw: function() {
this.layout();
}
});

Expand Down Expand Up @@ -199,5 +212,29 @@
}
}
});

$('.cms-preview .cms-preview-states').entwine({
onmatch: function() {
this.find('a').addClass('ss-ui-button');
this.find('.active a').addClass('ui-state-highlight');
}
});
$('.cms-preview .cms-preview-states a').entwine({
onclick: function(e) {
e.preventDefault();
this.parents('.cms-preview').loadUrl(this.attr('href'));
this.addClass('ui-state-highlight');
this.parents('.cms-preview-states').find('a').not(this).removeClass('ui-state-highlight');

}
});

$('.cms-preview-toggle-link').entwine({
onclick: function(e) {
e.preventDefault();
$('.cms-preview').toggle();

}
});
});
}(jQuery));
57 changes: 5 additions & 52 deletions admin/javascript/LeftAndMain.js
Expand Up @@ -60,14 +60,17 @@

// Initialize layouts
this.redraw();

// Monitor window resizes, panel changes and edit form loads for layout changes.
// Also triggers redraw through handleStateChange()
$(window).resize(function() {self.redraw()});
$('.cms-panel').live('toggle', function() {self.redraw();});
$('.cms-edit-form').live('loadnewpage', function() {self.redraw()});

// Remove loading screen
$('.ss-loading-screen').hide();
$('body').removeClass('loading');
$(window).unbind('resize', positionLoadingSpinner);

$('.cms-edit-form').live('loadnewpage', function() {self.redraw()});

History.Adapter.bind(window,'statechange',function(){
self.handleStateChange();
Expand Down Expand Up @@ -145,15 +148,6 @@
this.setCurrentXHR(xhr);
}
});

/**
* Monitor all panels for layout changes
*/
$('.cms-panel').entwine({
ontoggle: function(e) {
this.parents('.cms-container').redraw();
}
});

/**
* Make all buttons "hoverable" with jQuery theming.
Expand Down Expand Up @@ -271,47 +265,6 @@
}
});

/**
* Class: #switchView a
*
* Updates the different stage links which are generated through
* the SilverStripeNavigator class on the serverside each time a form record
* is reloaded.
*/
$('#switchView').entwine({
onmatch: function() {
this._super();

$('.cms-edit-form').bind('loadnewpage delete', function(e) {
var updatedSwitchView = $('#AjaxSwitchView');
if(updatedSwitchView.length) {
$('#SwitchView').html(updatedSwitchView.html());
updatedSwitchView.remove();
}
});
}
});

/**
* Class: #switchView a
*
* Links for viewing the currently loaded page
* in different modes: 'live', 'stage' or 'archived'.
*
* Requires:
* jquery.metadata
*/
$('#switchView a').entwine({
/**
* Function: onclick
*/
onclick: function(e) {
// Open in popup
window.open($(e.target).attr('href'));
return false;
}
});

/**
* Duplicates functionality in DateField.js, but due to using entwine we can match
* the DOM element on creation, rather than onclick - which allows us to decorate
Expand Down
30 changes: 29 additions & 1 deletion admin/scss/_forms.scss
Expand Up @@ -168,6 +168,21 @@ form.nostyle {
* Buttons
* ---------------------------------------------------- */

.Actions {
margin-right: 80px; // Accommodate preview button
min-height: 30px;

& > div {
overflow: auto;
}
}

.cms-preview-toggle-link {
display: block;
float: right;
font-size: 11px;
}

.cms {
.ui-widget {
/* loading */
Expand All @@ -194,14 +209,14 @@ form.nostyle {
background-color: $color-button-generic;
border: 1px solid $color-button-generic-border;
@include text-shadow(lighten($color-button-generic, 20%) 0 1px 1px);

@include box-shadow(lighten($color-base, 10%) 0 1px 2px);
@include background(image-url("../images/btn_icons_sprite.png") no-repeat 999px 999px,
linear-gradient(color-stops(
lighten($color-button-generic, 10%),
darken($color-button-generic, 5%)
))
);

&.ui-state-hover {
border: 1px solid darken($color-button-generic-border, 5%);

Expand All @@ -213,6 +228,7 @@ form.nostyle {
))
);
}

&:focus,
&:active {
border: 1px solid darken($color-button-generic-border, 5%);
Expand All @@ -225,6 +241,16 @@ form.nostyle {
))
);
}

&.ss-ui-button-small {
padding: ($grid-vertical/2) ($grid-horizontal/2);
}

&.ui-state-highlight {
background-color: $color-button-highlight;
border: 1px solid $color-button-highlight-border;
}

/* constructive */
&.ss-ui-action-constructive {
padding-left: 24px;
Expand Down Expand Up @@ -355,7 +381,9 @@ form.nostyle {
cursor: pointer;
padding: 0 0 0 $grid-vertical * 2;
}

}

}

/** ----------------------------------------------------
Expand Down

0 comments on commit 4461cae

Please sign in to comment.