Merge branch 'master' into integration

Conflicts:
	templates/Includes/AssetAdmin_Content.ss
This commit is contained in:
Ingo Schommer 2012-02-24 00:31:36 +01:00
commit d09c071899
34 changed files with 513 additions and 680 deletions

View File

@ -31,6 +31,7 @@ class AssetAdmin extends LeftAndMain {
'savefile',
'deleteUnusedThumbnails' => 'ADMIN',
'SyncForm',
'filter',
);
/**
@ -41,8 +42,6 @@ class AssetAdmin extends LeftAndMain {
return $_REQUEST['ID'];
} elseif (is_numeric($this->urlParams['ID'])) {
return $this->urlParams['ID'];
} elseif(is_numeric(Session::get("{$this->class}.currentPage"))) {
return Session::get("{$this->class}.currentPage");
} else {
return "root";
}
@ -58,7 +57,8 @@ class AssetAdmin extends LeftAndMain {
if(!file_exists(ASSETS_PATH)) Filesystem::makeFolder(ASSETS_PATH);
Requirements::javascript(CMS_DIR . "/javascript/AssetAdmin.js");
Requirements::css(CMS_DIR . "/css/AssetAdmin.css");
Requirements::add_i18n_javascript(CMS_DIR . '/javascript/lang', false, true);
Requirements::css(CMS_DIR . "/css/screen.css");
Requirements::customScript(<<<JS
_TREE_ICONS = {};
@ -73,9 +73,194 @@ JS
CMSBatchActionHandler::register('delete', 'AssetAdmin_DeleteBatchAction', 'Folder');
}
public function getEditForm($id = null, $fields = null) {
$form = parent::getEditForm($id, $fields);
$folder = ($id && is_numeric($id)) ? DataObject::get_by_id('Folder', $id, false) : $this->currentPage();
$fields = $form->Fields();
$fields->push(new HiddenField('ID', false, $folder->ID));
// File listing
$gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldSortableHeader(),
new GridFieldFilter(),
new GridFieldDefaultColumns(),
new GridFieldPaginator(10),
new GridFieldAction_Delete(),
new GridFieldAction_Edit(),
$gridFieldForm = new GridFieldPopupForms(Controller::curr(), 'EditForm')
);
$gridFieldForm->setTemplate('CMSGridFieldPopupForms');
$files = DataList::create('File')
->filter('ParentID', $folder->ID)
->sort('(CASE WHEN "ClassName" = \'Folder\' THEN 0 ELSE 1 END)');
$gridField = new GridField('File','Files', $files, $gridFieldConfig);
$gridField->setDisplayFields(array(
'StripThumbnail' => '',
// 'Parent.FileName' => 'Folder',
'Title' => _t('File.Name'),
'Created' => _t('AssetAdmin.CREATED', 'Date'),
'Size' => _t('AssetAdmin.SIZE', 'Size'),
));
$gridField->setFieldCasting(array(
'Created' => 'Date->Nice'
));
$gridField->setAttribute(
'data-url-folder-template',
Controller::join_links($this->Link('show'), '%s')
);
if($folder->canCreate()) {
$uploadBtn = new LiteralField(
'UploadButton',
sprintf(
'<a class="ss-ui-button ss-ui-action-constructive cms-panel-link" data-target-panel=".cms-content" data-icon="drive-upload" href="%s">%s</a>',
Controller::join_links(singleton('CMSFileAddController')->Link(), '?ID=' . $folder->ID),
_t('Folder.UploadFilesButton', 'Upload')
)
);
} else {
$uploadBtn = null;
}
if(!$folder->hasMethod('canAddChildren') || ($folder->hasMethod('canAddChildren') && $folder->canAddChildren())) {
// TODO Will most likely be replaced by GridField logic
$addFolderBtn = new LiteralField(
'AddFolderButton',
sprintf(
'<a class="ss-ui-button ss-ui-action-constructive cms-panel-link cms-page-add-button" data-icon="add" href="%s">%s</a>',
Controller::join_links($this->Link('addfolder'), '?ParentID=' . $folder->ID),
_t('Folder.AddFolderButton', 'Add folder')
)
);
} else {
$addFolderBtn = '';
}
// Move existing fields to a "details" tab, unless they've already been tabbed out through extensions.
// Required to keep Folder->getCMSFields() simple and reuseable,
// without any dependencies into AssetAdmin (e.g. useful for "add folder" views).
if(!$fields->hasTabset()) {
$tabs = new TabSet('Root',
$tabList = new Tab('ListView', _t('AssetAdmin.ListView', 'List View')),
$tabTree = new Tab('TreeView', _t('AssetAdmin.TreeView', 'Tree View'))
);
if($fields->Count() && $folder->exists()) {
$tabs->push($tabDetails = new Tab('DetailsView', _t('AssetAdmin.DetailsView', 'Details')));
foreach($fields as $field) {
$fields->removeByName($field->Name());
$tabDetails->push($field);
}
}
$fields->push($tabs);
}
// List view
$fields->addFieldsToTab('Root.ListView', array(
$actionsComposite = Object::create('CompositeField',
Object::create('CompositeField',
$uploadBtn,
$addFolderBtn
)->addExtraClass('cms-actions-row')
)->addExtraClass('cms-content-toolbar field'),
$gridField
));
// Tree view
$fields->addFieldsToTab('Root.TreeView', array(
clone $actionsComposite,
// TODO Replace with lazy loading on client to avoid performance hit of rendering potentially unused views
new LiteralField(
'Tree',
FormField::createTag(
'div',
array(
'class' => 'cms-tree',
'data-url-tree' => $this->Link('getsubtree'),
'data-url-savetreenode' => $this->Link('savetreenode')
),
$this->SiteTreeAsUL()
)
)
));
$fields->setForm($form);
$form->addExtraClass('cms-edit-form');
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
// TODO Can't merge $FormAttributes in template at the moment
$form->addExtraClass('center ss-tabset ' . $this->BaseCSSClasses());
$form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
$this->extend('updateEditForm', $form);
return $form;
}
public function addfolder($request) {
$obj = $this->customise(array(
'EditForm' => $this->AddForm()
));
if($this->isAjax()) {
// Rendering is handled by template, which will call EditForm() eventually
$content = $obj->renderWith($this->getTemplatesWithSuffix('_Content'));
} else {
$content = $obj->renderWith($this->getViewer('show'));
}
return $content;
}
/**
* Returns a form for filtering of files and assets gridfield
*
* @return Form
* @see AssetAdmin.js
*/
public function FilterForm() {
$fields = new FieldList();
// Below is the filters that this field should filter on
$fields->push(new TextField('Title'));
$fields->push(new TextField('ClassName','Type'));
$actions = new FieldList();
$actions->push(new FormAction('doFilter', 'Filter'));
$actions->push(new ResetFormAction('doResetFilter', 'Clear Filter'));
$form = new Form($this, 'filter', $fields, $actions);
$form->addExtraClass('cms-filter-form');
// This have to match data-name attribute on the gridfield so that the javascript selectors work
$form->setAttribute('data-gridfield', 'File');
return $form;
}
/**
* If this method get's called, it means that javascript didn't hook into to the submit on
* FilterForm and we can currently not do a Filter without javascript.
*
* @param SS_HTTPRequest $data
* @throws SS_HTTPResponse_Exception
*/
public function filter(SS_HTTPRequest $data) {
throw new SS_HTTPResponse_Exception('Filterpanel doesn\'t work without javascript enabled.');
}
public function AddForm() {
$form = parent::AddForm();
$form->Actions()->fieldByName('action_doAdd')->setTitle(_t('AssetAdmin.ActionAdd', 'Add folder'));
$folder = singleton('Folder');
$form->Actions()->fieldByName('action_doAdd')
->setTitle(_t('AssetAdmin.ActionAdd', 'Add folder'))
->setAttribute('data-icon', 'accept');
$fields = $folder->getCMSFields();
$fields->replaceField('Name', new TextField("Name", _t('File.Name')));
$fields->dataFieldByName('ParentID')->setValue($this->request->getVar('ParentID'));
$form->setFields($fields);
$form->addExtraClass('cms-edit-form');
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
$form->addExtraClass('center ' . $this->BaseCSSClasses());
return $form;
}
@ -119,6 +304,7 @@ JS
$record = new Folder();
$record->ParentID = $parent;
$record->Name = $record->Title = basename($filename);
// Ensure uniqueness
$i = 2;
@ -134,10 +320,9 @@ JS
mkdir($record->FullPath);
chmod($record->FullPath, Filesystem::$file_create_mask);
// Used in TinyMCE inline folder creation
if(isset($data['returnID'])) {
return $record->ID;
} else if($this->isAjax()) {
if($this->isAjax()) {
$link = Controller::join_links($this->Link('show'), $record->ID);
$this->getResponse()->addHeader('X-ControllerURL', $link);
$form = $this->getEditForm($record->ID);
return $form->forTemplate();
} else {
@ -151,9 +336,10 @@ JS
public function currentPage() {
$id = $this->currentPageID();
if($id && is_numeric($id)) {
return DataObject::get_by_id('File', $id);
} else if($id == 'root') {
return singleton('File');
return DataObject::get_by_id('Folder', $id);
} else {
// ID is either '0' or 'root'
return singleton('Folder');
}
}
@ -183,11 +369,12 @@ JS
new FieldList(
),
new FieldList(
$btn = new FormAction('doSync', _t('FILESYSTEMSYNC','Look for new files'))
FormAction::create('doSync', _t('FILESYSTEMSYNC','Look for new files'))
->describe(_t('AssetAdmin_left.ss.FILESYSTEMSYNC_DESC', 'SilverStripe maintains its own database of the files &amp; images stored in your assets/ folder. Click this button to update that database, if files are added to the assets/ folder from outside SilverStripe, for example, if you have uploaded files via FTP.'))
->setUseButtonTag(true)
)
);
$form->setFormMethod('GET');
$btn->describe(_t('AssetAdmin_left.ss.FILESYSTEMSYNC_DESC', 'SilverStripe maintains its own database of the files &amp; images stored in your assets/ folder. Click this button to update that database, if files are added to the assets/ folder from outside SilverStripe, for example, if you have uploaded files via FTP.'));
return $form;
}

View File

@ -24,22 +24,38 @@ class CMSFileAddController extends AssetAdmin {
Requirements::javascript(SAPPHIRE_DIR . '/javascript/AssetUploadField.js');
Requirements::css(SAPPHIRE_DIR . '/css/AssetUploadField.css');
$folder = $this->currentPage();
$uploadField = Object::create('UploadField', 'AssetUploadField', '');
$uploadField->setConfig('previewMaxWidth', 40);
$uploadField->setConfig('previewMaxHeight', 30);
$uploadField->addExtraClass('ss-assetuploadfield');
$uploadField->removeExtraClass('ss-uploadfield');
$uploadField->setTemplate('AssetUploadField');
if ($this->currentPage()->exists() && $this->currentPage()->getFilename()) {
if ($folder->exists() && $folder->getFilename()) {
$uploadField->setFolderName($this->currentPage()->getFilename());
}
$form = new Form($this, 'getEditForm', new FieldList($uploadField), new FieldList());
$form->addExtraClass('cms-content center cms-edit-form ' . $this->BaseCSSClasses());
$form->addExtraClass('center cms-edit-form ' . $this->BaseCSSClasses());
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
$form->Fields()->push(
new LiteralField(
'BackLink',
sprintf(
'<a href="%s" class="backlink ss-ui-button cms-panel-link" data-icon="back">%s</a>',
Controller::join_links(singleton('AssetAdmin')->Link('show'), $folder ? $folder->ID : 0),
_t('AssetAdmin.BackToFolder', 'Back to folder')
)
)
);
return $form;
}
function Tools() {
return false;
}
}

View File

@ -58,7 +58,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
parent::init();
Requirements::css(CMS_DIR . '/css/CMSMain.css');
Requirements::css(CMS_DIR . '/css/screen.css');
Requirements::combine_files(
'cmsmain.js',
@ -205,10 +205,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$dateTo->setConfig('showcalendar', true);
$actions = new FieldList(
$resetAction = new ResetFormAction('clear', _t('CMSMain_left.ss.CLEAR', 'Clear')),
$searchAction = new FormAction('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search'))
Object::create('ResetFormAction', 'clear', _t('CMSMain_left.ss.CLEAR', 'Clear'))
->addExtraClass('ss-ui-action-minor'),
FormAction::create('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search'))
);
$resetAction->addExtraClass('ss-ui-action-minor');
// Use <button> to allow full jQuery UI styling
foreach($actions->dataFields() as $action) $action->setUseButtonTag(true);
$form = new Form($this, 'SearchForm', $fields, $actions);
$form->setFormMethod('GET');
@ -494,6 +497,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$actions = $record->getCMSActions();
}
// Use <button> to allow full jQuery UI styling
$actionsFlattened = $actions->dataFields();
if($actionsFlattened) foreach($actionsFlattened as $action) $action->setUseButtonTag(true);
if($record->hasMethod('getCMSValidator')) {
$validator = $record->getCMSValidator();
} else {
@ -534,7 +541,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$siteConfig = SiteConfig::current_site_config();
$fields = $siteConfig->getCMSFields();
$form = new Form($this, 'RootForm', $fields, $siteConfig->getCMSActions());
$actions = $siteConfig->getCMSActions();
$form = new Form($this, 'RootForm', $fields, $actions);
$form->addExtraClass('root-form');
$form->addExtraClass('cms-edit-form');
// TODO Can't merge $FormAttributes in template at the moment
@ -544,6 +552,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$form->loadDataFrom($siteConfig);
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
// Use <button> to allow full jQuery UI styling
foreach($actions->dataFields() as $action) $action->setUseButtonTag(true);
$this->extend('updateEditForm', $form);
return $form;
@ -899,7 +910,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
new HiddenField('Locale', false, $this->Locale)
),
new FieldList(
new FormAction('doShowSideReport', _t('CMSMain_left.ss.GO','Go'))
FormAction::create('doShowSideReport', _t('CMSMain_left.ss.GO','Go'))->setUseButtonTag(true)
)
);
$form->unsetValidator();
@ -1110,10 +1121,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$actions = new FieldList(
// $resetAction = new ResetFormAction('doCancel', _t('CMSMain.Cancel', 'Cancel')),
$createAction = new FormAction("doAdd", _t('CMSMain.Create',"Create"))
FormAction::create("doAdd", _t('CMSMain.Create',"Create"))
->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')
->setUseButtonTag(true)
);
// $resetAction->addExtraClass('ss-ui-action-destructive');
$createAction->addExtraClass('ss-ui-action-constructive');
$this->extend('updatePageOptions', $fields);

View File

@ -83,7 +83,7 @@ class CMSPageHistoryController extends CMSMain {
$form = parent::getEditForm($record, ($record) ? $record->getCMSFields() : null);
$form->setActions(new FieldList(
$revert = new FormAction('doRollback', _t('CMSPageHistoryController.REVERTTOTHISVERSION', 'Revert to this version'))
$revert = FormAction::create('doRollback', _t('CMSPageHistoryController.REVERTTOTHISVERSION', 'Revert to this version'))->setUseButtonTag(true)
));
$fields = $form->Fields();
@ -190,10 +190,7 @@ class CMSPageHistoryController extends CMSMain {
))->renderWith('CMSPageHistoryController_versions');
}
$form = new Form(
$this,
'VersionsForm',
new FieldList(
$fields = new FieldList(
new CheckboxField(
'ShowUnpublished',
_t('CMSPageHistoryController.SHOWUNPUBLISHED','Show unpublished versions'),
@ -206,26 +203,35 @@ class CMSPageHistoryController extends CMSMain {
),
new LiteralField('VersionsHtml', $versionsHtml),
$hiddenID = new HiddenField('ID', false, "")
),
new FieldList(
);
$actions = new FieldList(
new FormAction(
'doCompare', _t('CMSPageHistoryController.COMPAREVERSIONS','Compare Versions')
),
new FormAction(
'doShowVersion', _t('CMSPageHistoryController.SHOWVERSION','Show Version')
)
)
);
// Use <button> to allow full jQuery UI styling
foreach($actions->dataFields() as $action) $action->setUseButtonTag(true);
$form = new Form(
$this,
'VersionsForm',
$fields,
$actions
);
$form->loadDataFrom($this->request->requestVars());
$hiddenID->setValue($id);
$form->unsetValidator();
$form->addExtraClass('cms-versions-form'); // placeholder, necessary for $.metadata() to work
$form->addExtraClass(Convert::raw2json(array(
'link-tmpl-compare' => Controller::join_links($this->Link('compare'), '%s', '%s', '%s'),
'link-tmpl-show' => Controller::join_links($this->Link('show'), '%s', '%s'),
)));
$form
->addExtraClass('cms-versions-form') // placeholder, necessary for $.metadata() to work
->setAttribute('data-link-tmpl-compare', Controller::join_links($this->Link('compare'), '%s', '%s', '%s'))
->setAttribute('data-link-tmpl-show', Controller::join_links($this->Link('show'), '%s', '%s'));
return $form;
}

View File

@ -26,7 +26,7 @@ class ReportAdmin extends LeftAndMain {
public function init() {
parent::init();
Requirements::css(CMS_DIR . '/css/ReportAdmin.css');
Requirements::css(CMS_DIR . '/css/screen.css');
// Set custom options for TinyMCE specific to ReportAdmin
HtmlEditorConfig::get('cms')->setOption('ContentCSS', project() . '/css/editor.css');

View File

@ -1,363 +0,0 @@
<?php
/**
* A special kind of complex table field for manipulating assets.
*
* @package cms
* @subpackage assets
*/
class AssetTableField extends ComplexTableField {
protected $folder;
protected $template = "AssetTableField";
protected $permissions = array(
"edit",
"delete",
//"export",
);
/**
* Indicates whether a search is being executed on this object
*/
protected $searchingFor = null;
function __construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") {
parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin);
$SNG_file = singleton('File');
// If search was request, filter the results here
$SQL_search = (!empty($_REQUEST['FileSearch'])) ? Convert::raw2sql($_REQUEST['FileSearch']) : null;
if($SQL_search) {
$searchFilters = array();
foreach($SNG_file->searchableFields() as $fieldName => $fieldSpec) {
if(strpos($fieldName, '.') === false) $searchFilters[] = "\"$fieldName\" LIKE '%{$SQL_search}%'";
}
$this->sourceFilter = '(' . implode(' OR ', $searchFilters) . ')';
$this->searchingFor = $_REQUEST['FileSearch'];
// @todo Integrate search form more closely and don't rely on deprecated
// $extraLinkParams.
$this->extraLinkParams = array(
'FileSearch' => $SQL_search
);
}
$this->sourceSort = 'Title';
$this->Markable = true;
}
/**
* Creates the link to this form, including the search pattern
*
* @return string
*/
function CurrentLink() {
$link = parent::CurrentLink();
if(isset($_REQUEST['FileSearch']) ) {
if ( strpos($link, '?')!==false )
$link .= "&";
else
$link .= "/?";
$link .= "FileSearch=".urlencode($_REQUEST['FileSearch']);
}
return $link;
}
function FieldHolder() {
$ret = parent::FieldHolder();
Requirements::javascript(CMS_DIR . '/javascript/AssetTableField.js');
return $ret;
}
function FirstLink() {
$link = parent::FirstLink();
if($link && isset($_REQUEST['FileSearch'])) {
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
}
return $link;
}
function PrevLink() {
$link = parent::PrevLink();
if($link && isset($_REQUEST['FileSearch'])) {
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
}
return $link;
}
function NextLink() {
$link = parent::NextLink();
if($link && isset($_REQUEST['FileSearch'])) {
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
}
return $link;
}
function LastLink() {
$link = parent::LastLink();
if($link && isset($_REQUEST['FileSearch'])) {
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
}
return $link;
}
function setFolder($folder) {
$this->folder = $folder;
$this->sourceFilter .= ($this->sourceFilter) ? " AND " : "";
// If you are searching for files then show all those from subfolders
if($this->searchingFor) {
$folderIDs = $nextIDSet = array($folder->ID);
$folderClasses = "'" . implode("','", ClassInfo::subclassesFor("Folder")) . "'";
while($nextIDSet) {
// TO DO: In 2.4 this should be refactored to use the new data mapper.
$nextIDSet = DB::query("SELECT \"ID\" FROM \"File\" WHERE \"ParentID\" IN ("
. implode(", " , $nextIDSet) . ") AND \"ClassName\" IN ($folderClasses)")->column();
if($nextIDSet) $folderIDs = array_merge($folderIDs, $nextIDSet);
}
$this->sourceFilter .= " \"ParentID\" IN (" . implode(", ", $folderIDs) . ") AND \"ClassName\" <> 'Folder'";
// Otherwise just show the direct contents
} else {
$this->sourceFilter .= " \"ParentID\" = '" . $folder->ID . "' AND \"ClassName\" <> 'Folder'";
}
}
function Folder() {
return $this->folder;
}
function sourceID() {
if($this->folder) return $this->folder->ID;
}
/**
* Get the pop-up fields for the given record.
*/
function getCustomFieldsFor($childData) {
if(!$childData) {
user_error("AssetTableField::DetailForm No record found");
return null;
}
if(!$childData instanceof File) {
throw new InvalidArgumentException(sprintf('$childData is of class "%s", subclass of "File" expected', get_class($childData)));
}
if($childData->ParentID) {
$folder = DataObject::get_by_id('File', $childData->ParentID );
} else {
$folder = singleton('Folder');
}
$urlLink = "<div class='field readonly'>";
$urlLink .= "<label class='left'>"._t('AssetTableField.URL','URL')."</label>";
$urlLink .= "<span class='readonly'><a href='{$childData->Link()}'>{$childData->RelativeLink()}</a></span>";
$urlLink .= "</div>";
$detailFormFields = new FieldList(
new TabSet("BottomRoot",
$mainTab = new Tab('Main',
new TextField("Title", _t('AssetTableField.TITLE','Title')),
new TextField("Name", _t('AssetTableField.FILENAME','Filename')),
new LiteralField("AbsoluteURL", $urlLink),
new ReadonlyField("FileType", _t('AssetTableField.TYPE','Type')),
new ReadonlyField("Size", _t('AssetTableField.SIZE','Size'), $childData->getSize()),
new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()),
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded')),
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed'))
)
)
);
$mainTab->setTitle(_t('AssetTableField.MAIN', 'Main'));
if(is_a($childData, 'Image')) {
$tab = $detailFormFields->findOrMakeTab("BottomRoot.Image", _t('AssetTableField.IMAGE', 'Image'));
$big = $childData->URL;
$formattedImage = $childData->getFormattedImage('AssetLibraryPreview');
$thumbnail = $formattedImage ? $formattedImage->URL : '';
// Hmm this required the translated string to be appended to BottomRoot to add this to the Main tab
$detailFormFields->addFieldToTab('BottomRoot.Main',
new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions'))
);
$tab->push(
new LiteralField("ImageFull",
"<img id='thumbnailImage' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$childData->Name}' />"
)
);
}
if(!($childData instanceof Folder)) {
$mainTab->push(new CheckboxField("ShowInSearch", $childData->fieldLabel('ShowInSearch')));
}
if($childData && $childData->hasMethod('BackLinkTracking')) {
if(class_exists('Subsite')) Subsite::disable_subsite_filter(true);
$links = $childData->BackLinkTracking();
if(class_exists('Subsite')) Subsite::disable_subsite_filter(false);
$linkArray = array();
if($links && $links->exists()) {
$backlinks = array();
foreach($links as $link) {
// Avoid duplicates
if (!in_array($link->ID, $linkArray)) {
$backlinks[] = "<li><a href=\"admin/show/$link->ID\">" . $link->Breadcrumbs(null,true). "</a></li>";
$linkArray[] = $link->ID;
}
}
$backlinks = "<div style=\"clear:left\">". _t('AssetTableField.PAGESLINKING','The following pages link to this file:') ."<ul>" . implode("",$backlinks) . "</ul></div>";
}
if(!isset($backlinks)) $backlinks = "<p>". _t('AssetTableField.NOLINKS',"This file hasn't been linked to from any pages.") ."</p>";
$detailFormFields->addFieldToTab("BottomRoot.Links", new LiteralField("Backlinks", $backlinks));
}
// the ID field confuses the Controller-logic in finding the right view for ReferencedField
$detailFormFields->removeByName('ID');
if($childData) $childData->extend('updateCMSFields', $detailFormFields);
return $detailFormFields;
}
/**
* Provide some HTML for a search form, to be
* added above the AssetTable field, allowing
* a user to filter the current table's files
* by their filename.
*
* @return string HTML for search form
*/
function SearchForm() {
$fieldContainer = new FieldGroup(
new FieldGroup(
new TextField(
'FileSearch',
_t('MemberTableField.SEARCH', 'Search'),
$this->searchingFor
)
),
new FieldGroup(
$btnFilter = new InlineFormAction(
'FileFilterButton',
_t('MemberTableField.FILTER', 'Filter')
),
$btnClear = new InlineFormAction(
'FileFilterClearButton',
_t('AssetTableField.CLEAR', 'Clear')
)
)
);
$btnFilter->includeDefaultJS(false);
$btnClear->includeDefaultJS(false);
return $fieldContainer->FieldHolder();
}
/**
* @return FormField|null
*/
function DeleteMarkedButton() {
if(!$this->isReadonly() ) {
$deleteButton = new InlineFormAction(
'deletemarked',
_t('Folder.DELSELECTED','Delete selected files'),
'delete'
);
$deleteButton->includeDefaultJS(false);
return $deleteButton;
}
}
/**
* @return string HTML
*/
public function deletemarked($request) {
$fileIDs = $request->requestVar($this->getName());
$numFiles = 0;
$brokenPageList = '';
if($fileIDs && count($fileIDs)) {
$files = DataObject::get(
"File",
sprintf("\"File\".\"ID\" IN (%s)", Convert::raw2sql(implode(',', $fileIDs)))
);
if($files) {
$brokenPages = array();
foreach($files as $file) {
$brokenPages = array_merge($brokenPages, $file->BackLinkTracking()->toArray());
$file->delete();
$numFiles++;
}
if($brokenPages) {
$brokenPageList = " ". _t('AssetAdmin.NOWBROKEN', 'These pages now have broken links:') . '<ul>';
foreach($brokenPages as $brokenPage) {
$brokenPageList .= "<li style=&quot;font-size: 65%&quot;>" . $brokenPage->Breadcrumbs(3, true) . '</li>';
}
$brokenPageList .= '</ul>';
Notifications::notifyByEmail("BrokenLink", "Page_BrokenLinkEmail");
} else {
$brokenPageList = '';
}
}
}
$response = $this->form->Controller()->getResponse();
$response->addHeader(
'X-Status',
sprintf(
_t('AssetAdmin.DELETEDX',"Deleted %s file(s) %s"),
$numFiles,
$brokenPageList
)
);
}
public function movemarked($request) {
$fileIDs = $request->requestVar($this->getName());
$folderId = $request->requestVar('DestFolderID');
$numFiles = 0;
if($folderId && (is_numeric($folderId) || ($folderId) == 'root')) {
if($folderId == 'root') $folderId = 0;
if($fileIDs && count($fileIDs)) {
$files = DataObject::get(
"File",
sprintf("\"File\".\"ID\" IN (%s)", Convert::raw2sql(implode(',', $fileIDs)))
);
if($files) {
foreach($files as $file) {
$file->ParentID = $folderId;
$file->write();
$numFiles++;
}
}
}
$response = $this->form->Controller()->getResponse();
$response->addHeader(
'X-Status',
sprintf(
sprintf(_t('AssetAdmin.MOVEDX','Moved %s files'),$numFiles),
$numFiles
)
);
}
}
}

View File

@ -41,21 +41,12 @@ class Folder_UnusedAssetsField extends CompositeField {
/**
* Creates table for displaying unused files.
*
* @returns AssetTableField
* @return GridField
*/
protected function getAssetList() {
$where = $this->folder->getUnusedFilesListFilter();
$assetList = new AssetTableField(
$this->folder,
"AssetList",
"File",
array("Title" => _t('Folder.TITLE', "Title"), "LinkedURL" => _t('Folder.FILENAME', "Filename")),
"",
$where
);
$assetList->setPopupCaption(_t('Folder.VIEWASSET', "View Asset"));
$assetList->setPermissions(array("show","delete"));
$assetList->Markable = false;
return $assetList;
$files = DataList::create('File')->where($where);
$field = new GridField('AssetList', false, $files);
return $field;
}
}

View File

@ -129,13 +129,13 @@ class SiteConfig extends DataObject implements PermissionProvider {
function getCMSActions() {
if (Permission::check('ADMIN') || Permission::check('EDIT_SITECONFIG')) {
$actions = new FieldList(
$saveAction = new FormAction('save_siteconfig', _t('CMSMain.SAVE','Save'))
FormAction::create('save_siteconfig', _t('CMSMain.SAVE','Save'))
->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')
);
} else {
$actions = new FieldList();
}
$saveAction->addExtraClass('ss-ui-action-constructive');
$this->extend('updateCMSActions', $actions);
return $actions;

View File

@ -2041,13 +2041,14 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @return FieldList The available actions for this page.
*/
function getCMSActions() {
$actions = new FieldList();
$minorActions = Object::create('CompositeField')->setTag('fieldset')->addExtraClass('ss-ui-buttonset');
$actions = new FieldList($minorActions);
// "readonly"/viewing version that isn't the current version of the record
$stageOrLiveRecord = Versioned::get_one_by_stage($this->class, Versioned::current_stage(), sprintf('"SiteTree"."ID" = %d', $this->ID));
if($stageOrLiveRecord && $stageOrLiveRecord->Version != $this->Version) {
$actions->push(new FormAction('email', _t('CMSMain.EMAIL', 'Email')));
$actions->push(new FormAction('rollback', _t('CMSMain.ROLLBACK', 'Roll back to this version')));
$minorActions->push(FormAction::create('email', _t('CMSMain.EMAIL', 'Email')));
$minorActions->push(FormAction::create('rollback', _t('CMSMain.ROLLBACK', 'Roll back to this version')));
// getCMSActions() can be extended with updateCMSActions() on a extension
$this->extend('updateCMSActions', $actions);
@ -2057,22 +2058,21 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if($this->isPublished() && $this->canPublish() && !$this->IsDeletedFromStage && $this->canDeleteFromLive()) {
// "unpublish"
$unpublish = FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete');
$unpublish->describe(_t('SiteTree.BUTTONUNPUBLISHDESC', 'Remove this page from the published site'));
$unpublish->addExtraClass('unpublish');
$unpublish->addExtraClass('ss-ui-action-destructive');
$unpublish->setAttribute('buttonset', 'minoractions');
$actions->push($unpublish);
$minorActions->push(
FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete')
->describe(_t('SiteTree.BUTTONUNPUBLISHDESC', 'Remove this page from the published site'))
->addExtraClass('ss-ui-action-destructive')->setAttribute('data-icon', 'unpublish')
);
}
if($this->stagesDiffer('Stage', 'Live') && !$this->IsDeletedFromStage) {
if($this->isPublished() && $this->canEdit()) {
// "rollback"
$rollback = FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'), 'delete');
$rollback->describe(_t('SiteTree.BUTTONCANCELDRAFTDESC', 'Delete your draft and revert to the currently published page'));
$rollback->addExtraClass('delete');
$rollback->setAttribute('buttonset', 'minoractions');
$actions->push($rollback);
$minorActions->push(
FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'), 'delete')
->describe(_t('SiteTree.BUTTONCANCELDRAFTDESC', 'Delete your draft and revert to the currently published page'))
->addExtraClass('delete')->setAttribute('data-icon', 'delete')
);
}
}
@ -2080,37 +2080,41 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if($this->IsDeletedFromStage) {
if($this->ExistsOnLive) {
// "restore"
$actions->push(new FormAction('revert',_t('CMSMain.RESTORE','Restore')));
$minorActions->push(FormAction::create('revert',_t('CMSMain.RESTORE','Restore')));
if($this->canDelete() && $this->canDeleteFromLive()) {
// "delete from live"
$actions->push($deleteFromLiveAction = new FormAction('deletefromlive',_t('CMSMain.DELETEFP','Delete')));
$deleteFromLiveAction->addExtraClass('ss-ui-action-destructive');
$deleteFromLiveAction->setAttribute('buttonset', 'minoractions');
$minorActions->push(
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))->addExtraClass('ss-ui-action-destructive')
);
}
} else {
// "restore"
$actions->push(new FormAction('restore',_t('CMSMain.RESTORE','Restore')));
$minorActions->push(
FormAction::create('restore',_t('CMSMain.RESTORE','Restore'))->setAttribute('data-icon', 'decline')
);
}
} else {
if($this->canDelete()) {
// "delete"
$actions->push($deleteAction = new FormAction('delete',_t('CMSMain.DELETE','Delete draft')));
$deleteAction->addExtraClass('delete');
$deleteAction->addExtraClass('ss-ui-action-destructive');
$deleteAction->setAttribute('buttonset', 'minoractions');
$minorActions->push(
FormAction::create('delete',_t('CMSMain.DELETE','Delete draft'))->addExtraClass('delete ss-ui-action-destructive')
->setAttribute('data-icon', 'decline')
);
}
// "save"
$actions->push($saveDraftAction = new FormAction('save',_t('CMSMain.SAVEDRAFT','Save Draft')));
$saveDraftAction->addExtraClass('save-draft');
$saveDraftAction->setAttribute('buttonset', 'minoractions');
$minorActions->push(
FormAction::create('save',_t('CMSMain.SAVEDRAFT','Save Draft'))->setAttribute('data-icon', 'addpage')
);
}
}
if($this->canPublish() && !$this->IsDeletedFromStage) {
// "publish"
$actions->push($publishAction = new FormAction('publish', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & Publish')));
$publishAction->addExtraClass('ss-ui-action-constructive');
$actions->push(
FormAction::create('publish', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & Publish'))
->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')
);
}
// getCMSActions() can be extended with updateCMSActions() on a extension

35
css/screen.css Normal file
View File

@ -0,0 +1,35 @@
/** This file is the central collection of included modules, links to custom SCSS files, and any global SCSS variable definitions. DO NOT ADD stylesheet rules to this file directly! Note: By prefixing files with an underscore, they won't create individual CSS files. */
/** ----------------------------- Core Compass Libraries ------------------------------ */
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; }
body { line-height: 1; }
ol, ul { list-style: none; }
table { border-collapse: collapse; border-spacing: 0; }
caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; }
q, blockquote { quotes: none; }
q:before, q:after, blockquote:before, blockquote:after { content: ""; content: none; }
a img { border: none; }
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary { display: block; }
/** ----------------------------- CMS Components ------------------------------ */
/** Style custom to the CMSMain admin interface. CMSMain extends the built in sapphire admin section styles. As much as possible we want to use those built in styles. If anything in this file can be implemented in a generic way then it should be include in the admin scss files. @package cms */
/** ------------------------------------------------------------------ Page History Section. ----------------------------------------------------------------- */
#cms-page-history-versions tr.loading { color: #999; }
#cms-page-history-versions tr.loading td:hover { cursor: none; }
#cms-page-history-versions td:hover { cursor: pointer; }
.CMSPageHistoryController ins { background-color: #DFD; padding: 2px; text-decoration: none; }
.CMSPageHistoryController del { background-color: #FDD; padding: 2px; color: #ff4444; }
.cms .AssetAdmin #Form_EditForm_File td { padding-top: 0; padding-bottom: 0; }
.cms .AssetAdmin #Form_EditForm_File td.col-StripThumbnail { padding: 0; width: 32px; height: 32px; display: block; }
.cms .AssetAdmin #Form_EditForm_File td.col-StripThumbnail img { width: 32px; height: 32px; }
.cms .AssetAdmin #Form_EditForm_File tr[data-class=Folder] td.col-StripThumbnail { background: transparent url(../../sapphire/admin/images/sprites-32x32/blue-folder-horizontal.png) no-repeat top left; }
.cms .AssetAdmin #Form_EditForm_File tr[data-class=File] td.col-StripThumbnail { background: transparent url(../../sapphire/admin/images/sprites-32x32/blue-document.png) no-repeat top left; }
.cms .AssetAdmin #Form_EditForm_File td.col-Title { cursor: pointer; }

View File

@ -24,6 +24,31 @@
$.entwine('ss', function($){
/**
* Load folder detail view via controller methods
* rather than built-in GridField view (which is only geared towards showing files).
*/
$('#Form_EditForm_File .ss-gridfield-item').entwine({
onclick: function(e) {
// Let actions do their own thing
if($(e.target).is('.action')) return;
var grid = this.closest('.ss-gridfield');
if(this.data('class') == 'Folder') {
var url = grid.data('urlFolderTemplate').replace('%s', this.data('id'));
$('.cms-container').loadPanel(url);
e.preventDefault();
}
}
});
$('.cms-edit-form :submit[name=action_delete]').entwine({
onclick: function(e) {
if(!confirm(ss.i18n._t('AssetAdmin.ConfirmDelete'))) return false;
else this._super(e);
}
});
/**
* Class: #Form_SyncForm
*/

View File

@ -57,9 +57,8 @@
if(!id) return false;
var button, url, selected, to, from, compare, data, metadata;
var button, url, selected, to, from, compare, data;
metadata = this.metadata({type: 'class'});
compare = (this.find(":input[name=CompareMode]").is(":checked"));
selected = this.find("table input[type=checkbox]").filter(":checked");
@ -69,12 +68,12 @@
to = selected.eq(0).val();
from = selected.eq(1).val();
button = this.find(':submit[name=action_doCompare]');
url = ss.i18n.sprintf(metadata['link-tmpl-compare'], id,from,to);
url = ss.i18n.sprintf(this.data('linkTmplCompare'), id,from,to);
}
else {
to = selected.eq(0).val();
button = this.find(':submit[name=action_doShowVersion]');
url = ss.i18n.sprintf(metadata['link-tmpl-show'], id,to);
url = ss.i18n.sprintf(this.data('linkTmplShow'), id,to);
}
$('.cms-container').loadPanel(url, '', {selector: '.cms-edit-form'});

View File

@ -34,6 +34,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
'AssetTableField.MOVING': 'Moving %s file(s)',
'SecurityAdmin.BATCHACTIONSDELETECONFIRM': "Do you really want to delete %s groups?",
'CMSMAIN.AddSearchCriteria': 'Add Criteria',
'WidgetAreaEditor.TOOMANY': 'Sorry, you have reached the maximum number of widgets in this area'
'WidgetAreaEditor.TOOMANY': 'Sorry, you have reached the maximum number of widgets in this area',
'AssetAdmin.ConfirmDelete': 'Do you really want to delete this folder and all contained files?'
});
}

19
scss/AssetAdmin.scss Normal file
View File

@ -0,0 +1,19 @@
.cms .AssetAdmin {
#Form_EditForm_File {
td.col-StripThumbnail {
padding: 0;
img {
width: 32px;
height: 32px;
}
}
tr td.col-StripThumbnail {
// TODO Figure out how to share sprites and SCSS rules between sapphire/admin/scss and cms/scss
background: transparent url(../../sapphire/admin/images/sprites-32x32/blue-folder-horizontal.png) no-repeat top left;
}
td.col-Title {
cursor: pointer;
}
}
}

34
scss/_AssetAdmin.scss Normal file
View File

@ -0,0 +1,34 @@
.cms .AssetAdmin {
#Form_EditForm_File {
td {
// Taken care of by minimum image sizes
padding-top: 0;
padding-bottom: 0;
}
td.col-StripThumbnail {
padding: 0;
width: 32px;
height: 32px;
display: block;
img {
width: 32px;
height: 32px;
}
}
// TODO Figure out how to share sprites and SCSS rules between sapphire/admin/scss and cms/scss
tr[data-class=Folder] {
td.col-StripThumbnail {
background: transparent url(../../sapphire/admin/images/sprites-32x32/blue-folder-horizontal.png) no-repeat top left;
}
}
tr[data-class=File] {
td.col-StripThumbnail {
background: transparent url(../../sapphire/admin/images/sprites-32x32/blue-document.png) no-repeat top left;
}
}
td.col-Title {
cursor: pointer;
}
}
}

23
scss/screen.scss Normal file
View File

@ -0,0 +1,23 @@
/**
* This file is the central collection of included modules, links to custom SCSS files,
* and any global SCSS variable definitions.
*
* DO NOT ADD stylesheet rules to this file directly!
*
* Note: By prefixing files with an underscore, they won't create individual CSS files.
*/
/** -----------------------------
* Core Compass Libraries
* ------------------------------ */
@import "compass/reset";
@import "compass/css3";
@import "compass/utilities/sprites/sprite-img";
@import "compass/utilities/general";
/** -----------------------------
* CMS Components
* ------------------------------ */
@import "CMSMain.scss";
@import "AssetAdmin.scss";
@import "ReportAdmin.scss";

View File

@ -1,4 +1,4 @@
<div class="cms-content-tools west cms-panel cms-panel-layout" data-expandOnClick="true" data-layout="{type: 'border'}" id="cms-content-tools-CMSPageEditController">
<div class="cms-content-tools west cms-panel cms-panel-layout" data-expandOnClick="true" data-layout-type="border" id="cms-content-tools-CMSPageEditController">
<div class="cms-content-header cms-panel-header north">
<h2><% _t('CMSPageEditController.Title','Pages') %></h2>
</div>

View File

@ -1,51 +0,0 @@
<div class="cms-content center ss-tabset $BaseCSSClasses" data-layout="{type: 'border'}">
<div class="cms-content-header north">
<div>
<h2>
<% include CMSBreadcrumbs %>
</h2>
<div class="cms-content-header-tabs">
<ul>
<li>
<a href="#cms-content-listview" class="content-listview"><% _t('AssetAdmin.ListView', 'List View') %></a>
</li>
<li>
<a href="#cms-content-galleryview" class="content-galleryview"><% _t('AssetAdmin.GalleryView', 'Gallery View') %></a>
</li>
<li>
<a href="#cms-content-treeview" class="content-treeview"><% _t('AssetAdmin.TreeView', 'Tree View') %></a>
</li>
</ul>
</div>
</div>
</div>
<div class="cms-content-tools cms-panel west cms-panel-layout" data-expandOnClick="true" data-layout="{type: 'border'}">
<div class="cms-panel-content center">
<h3 class="cms-panel-header north"></h3>
<div class="cms-content-tools-actions ui-widget-content">
$AddForm
</div>
<div class="cms-tree" data-url-tree="$Link(getsubtree)" data-url-savetreenode="$Link(savetreenode)">
$SiteTreeAsUL
</div>
</div>
</div>
<div class="cms-content-fields center">
<div id="cms-content-listview">
$EditForm
</div>
<div id="cms-content-treeview">
<i>Not implemented yet</i>
</div>
<div id="cms-content-galleryview">
<i>Not implemented yet</i>
</div>
</div>
</div>

View File

@ -1 +0,0 @@
<% include Form %>

View File

@ -1,7 +1,7 @@
<div class="cms-content-tools west cms-panel cms-panel-layout collapsed" id="cms-content-tools" data-expandOnClick="true" data-layout="{type: 'border'}">
<div class="cms-content-tools west cms-panel cms-panel-layout collapsed" id="cms-content-tools" data-expandOnClick="true" data-layout-type="border">
<div class="cms-panel-content center">
<h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3>
TODO
$FilterForm
</div>
<div class="cms-panel-content-collapsed">
<h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3>

View File

@ -1,4 +1,4 @@
<div class="cms-content center ss-tabset $BaseCSSClasses" data-layout="{type: 'border'}">
<div class="cms-content center ss-tabset $BaseCSSClasses" data-layout-type="border">
<div class="cms-content-header north">
<div>

View File

@ -1,42 +0,0 @@
<div id="$id" class="$CSSClasses $extraClass field dragdrop" href="$CurrentLink">
<div class="FileFilter filterBox">
$SearchForm
</div>
<% if Markable %>
<% include TableListField_SelectOptions %>
<% end_if %>
<% include TableListField_PageControls %>
<table class="data">
<thead>
<tr>
<th width="18">&nbsp;</th>
<% if Markable %><th width="18">&nbsp;</th><% end_if %>
<% control Headings %>
<th class="$Name">$Title</th>
<% end_control %>
<th width="18">&nbsp;</th>
<% if Can(delete) %><th width="18">&nbsp;</th><% end_if %>
</tr>
</thead>
<tbody>
<% if Items %>
<% control Items %>
<% include AssetTableField_Item %>
<% end_control %>
<% else %>
<tr class="notfound">
<td></td>
<% if Markable %><th width="18">&nbsp;</th><% end_if %>
<td colspan="$Headings.Count"><i><% sprintf(_t('AssetTableField.NODATAFOUND', 'No %s found'),$NamePlural) %></i></td>
<% if Can(delete) %><td width="18">&nbsp;</td><% end_if %>
</tr>
<% end_if %>
</tbody>
</table>
<div class="utility">
$DeleteMarkedButton
<% control Utility %>
<span class="item"><a href="$Link">$Title</a></span>
<% end_control %>
</div>
</div>

View File

@ -1,23 +0,0 @@
<tr id="record-$Parent.id-$ID"<% if HighlightClasses %> class="$HighlightClasses"<% end_if %>>
<td class="dragfile" id="drag-$Parent.Name-$ID">
<img id="drag-img-$Parent.Name-$ID" alt="Drag" title="<% _t('DRAGTOFOLDER','Drag to folder on left to move file') %>" src="sapphire/images/drag.gif" />
<span class="linkCount" style="display: none;">$BackLinkTrackingCount</span>
</td>
<% if Markable %><td class="markingcheckbox">$MarkingCheckbox</td><% end_if %>
<% control Fields %>
<td class="field-$Title.HTMLATT $FirstLast $Name">$Value</td>
<% end_control %>
<% control Actions %>
<td width="16">
<% if IsAllowed %>
<a class="$Class" href="$Link">
<% if Icon %><img src="$Icon" alt="$Label" /><% else %>$Label<% end_if %>
</a>
<% else %>
<span class="disabled">
<% if IconDisabled %><img src="$IconDisabled" alt="$Label" /><% else %>$Label<% end_if %>
</span>
<% end_if %>
</td>
<% end_control %>
</tr>

View File

@ -1,37 +0,0 @@
<% with EditForm %>
<form $FormAttributes data-layout="{type: 'border'}">
<div class="cms-content-header north">
<div>
<h2><% _t('CMSAddPageController.Title','Add pages') %></h2>
</div>
</div>
<div class="cms-content-fields center cms-panel-content cms-panel-padded">
<% if Message %>
<p id="{$FormName}_error" class="message $MessageType">$Message</p>
<% else %>
<p id="{$FormName}_error" class="message $MessageType" style="display: none"></p>
<% end_if %>
<fieldset>
<% if Legend %><legend>$Legend</legend><% end_if %>
<% control Fields %>
$FieldHolder
<% end_control %>
</fieldset>
</div>
<div class="cms-content-actions south">
<% if Actions %>
<div class="Actions">
<% control Actions %>
$Field
<% end_control %>
</div>
<% end_if %>
</div>
</form>
<% end_with %>

View File

@ -1,5 +1,5 @@
<% with AddForm %>
<form $FormAttributes data-layout="{type: 'border'}">
<form $FormAttributes data-layout-type="border">
<div class="cms-content-header north">
<div>

View File

@ -1,4 +1,4 @@
<div class="cms-content-tools west cms-panel cms-panel-layout" data-expandOnClick="true" data-layout="{type: 'border'}" id="cms-content-tools-CMSPageHistoryController">
<div class="cms-content-tools west cms-panel cms-panel-layout" data-expandOnClick="true" data-layout-type="border" id="cms-content-tools-CMSPageHistoryController">
<div class="cms-content-header north">
<div>
<h2><% _t('CMSPageHistoryController.History','History') %></h2>

View File

@ -1,4 +1,4 @@
<div class="cms-content center ss-tabset $BaseCSSClasses" data-layout="{type: 'border'}">
<div class="cms-content center ss-tabset $BaseCSSClasses" data-layout-type="border">
<div class="cms-content-header north">
<div>
@ -24,7 +24,7 @@
$Tools
<div class="cms-content-fields center ui-widget-content">
<div class="cms-content-fields center ui-widget-content cms-panel-padded">
<div id="cms-content-treeview">

View File

@ -12,8 +12,8 @@
</div>
</div>
<div class="cms-content-constructive-actions">
<a class="ss-ui-button ss-ui-action-constructive cms-page-add-button" href="#cms-page-add-form"><% _t('CMSMain.AddNewButton', 'Add new') %></a>
<div class="cms-actions-row">
<a class="ss-ui-button ss-ui-action-constructive" data-icon="add" href="#cms-page-add-form"><% _t('CMSMain.AddNewButton', 'Add new') %></a>
</div>
<div class="cms-content-batchactions">

View File

@ -1,4 +1,4 @@
<div class="cms-content-tools west cms-panel cms-panel-layout collapsed" id="cms-content-tools" data-expandOnClick="true" data-layout="{type: 'border'}" id="cms-content-tools-CMSPagesController">
<div class="cms-content-tools west cms-panel cms-panel-layout collapsed" id="cms-content-tools" data-expandOnClick="true" data-layout-type="border" id="cms-content-tools-CMSPagesController">
<div class="cms-panel-content center">
<h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3>
$SearchForm

View File

@ -1,4 +1,4 @@
<div class="cms-content center $BaseCSSClasses" data-layout="{type: 'border'}">
<div class="cms-content center $BaseCSSClasses" data-layout-type="border">
<div class="cms-content-header north">
<h2><% _t('REPORTS','Reports') %></h2>

View File

@ -155,7 +155,7 @@ class CMSMainTest extends FunctionalTest {
$this->assertTrue($livePage->canDelete());
// Check that the 'restore' button exists as a simple way of checking that the correct page is returned.
$this->assertRegExp('/<input[^>]+type="submit"[^>]+name="action_(restore|revert)"/i', $response->getBody());
$this->assertRegExp('/<button[^>]+name="action_(restore|revert)"/i', $response->getBody());
}
/**

View File

@ -39,15 +39,15 @@ class SiteTreeActionsTest extends FunctionalTest {
$page->write();
$page->doPublish();
$actionsArr = $page->getCMSActions()->column('Name');
$actions = $page->getCMSActions();
$this->assertNotContains('action_save',$actionsArr);
$this->assertNotContains('action_publish',$actionsArr);
$this->assertNotContains('action_unpublish',$actionsArr);
$this->assertNotContains('action_delete',$actionsArr);
$this->assertNotContains('action_deletefromlive',$actionsArr);
$this->assertNotContains('action_rollback',$actionsArr);
$this->assertNotContains('action_revert',$actionsArr);
$this->assertNull($actions->dataFieldByName('action_save'));
$this->assertNull($actions->dataFieldByName('action_publish'));
$this->assertNull($actions->dataFieldByName('action_unpublish'));
$this->assertNull($actions->dataFieldByName('action_delete'));
$this->assertNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNull($actions->dataFieldByName('action_rollback'));
$this->assertNull($actions->dataFieldByName('action_revert'));
}
function testActionsNoDeletePublishedRecord() {
@ -70,13 +70,13 @@ class SiteTreeActionsTest extends FunctionalTest {
$editor = $this->objFromFixture('Member', 'cmsnodeleteeditor');
$this->session()->inst_set('loggedInAs', $editor->ID);
$actionsArr = $page->getCMSActions()->column('Name');
$this->assertNotContains('action_deletefromlive',$actionsArr);
$actions = $page->getCMSActions();
$this->assertNull($actions->dataFieldByName('action_deletefromlive'));
// Check that someone with the right permission can delete the page
$this->objFromFixture('Member', 'cmseditor')->logIn();
$actionsArr = $page->getCMSActions()->column('Name');
$this->assertContains('action_deletefromlive',$actionsArr);
$actions = $page->getCMSActions();
$this->assertNotNull($actions->dataFieldByName('action_deletefromlive'));
}
function testActionsPublishedRecord() {
@ -90,15 +90,15 @@ class SiteTreeActionsTest extends FunctionalTest {
$page->write();
$page->doPublish();
$actionsArr = $page->getCMSActions()->column('Name');
$actions = $page->getCMSActions();
$this->assertContains('action_save',$actionsArr);
$this->assertContains('action_publish',$actionsArr);
$this->assertContains('action_unpublish',$actionsArr);
$this->assertContains('action_delete',$actionsArr);
$this->assertNotContains('action_deletefromlive',$actionsArr);
$this->assertNotContains('action_rollback',$actionsArr);
$this->assertNotContains('action_revert',$actionsArr);
$this->assertNotNull($actions->dataFieldByName('action_save'));
$this->assertNotNull($actions->dataFieldByName('action_publish'));
$this->assertNotNull($actions->dataFieldByName('action_unpublish'));
$this->assertNotNull($actions->dataFieldByName('action_delete'));
$this->assertNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNull($actions->dataFieldByName('action_rollback'));
$this->assertNull($actions->dataFieldByName('action_revert'));
}
function testActionsDeletedFromStageRecord() {
@ -118,15 +118,15 @@ class SiteTreeActionsTest extends FunctionalTest {
$page = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = $pageID");
$this->assertType('SiteTree', $page);
$actionsArr = $page->getCMSActions()->column('Name');
$actions = $page->getCMSActions();
$this->assertNotContains('action_save',$actionsArr);
$this->assertNotContains('action_publish',$actionsArr);
$this->assertNotContains('action_unpublish',$actionsArr);
$this->assertNotContains('action_delete',$actionsArr);
$this->assertContains('action_deletefromlive',$actionsArr);
$this->assertNotContains('action_rollback',$actionsArr);
$this->assertContains('action_revert',$actionsArr);
$this->assertNull($actions->dataFieldByName('action_save'));
$this->assertNull($actions->dataFieldByName('action_publish'));
$this->assertNull($actions->dataFieldByName('action_unpublish'));
$this->assertNull($actions->dataFieldByName('action_delete'));
$this->assertNotNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNull($actions->dataFieldByName('action_rollback'));
$this->assertNotNull($actions->dataFieldByName('action_revert'));
}
function testActionsChangedOnStageRecord() {
@ -143,15 +143,14 @@ class SiteTreeActionsTest extends FunctionalTest {
$page->write();
$page->flushCache();
$actionsArr = $page->getCMSActions()->column('Name');
$this->assertContains('action_save',$actionsArr);
$this->assertContains('action_publish',$actionsArr);
$this->assertContains('action_unpublish',$actionsArr);
$this->assertContains('action_delete',$actionsArr);
$this->assertNotContains('action_deletefromlive',$actionsArr);
$this->assertContains('action_rollback',$actionsArr);
$this->assertNotContains('action_revert',$actionsArr);
$actions = $page->getCMSActions();
$this->assertNotNull($actions->dataFieldByName('action_save'));
$this->assertNotNull($actions->dataFieldByName('action_publish'));
$this->assertNotNull($actions->dataFieldByName('action_unpublish'));
$this->assertNotNull($actions->dataFieldByName('action_delete'));
$this->assertNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNotNull($actions->dataFieldByName('action_rollback'));
$this->assertNull($actions->dataFieldByName('action_revert'));
}
function testActionsViewingOldVersion() {
@ -164,13 +163,13 @@ class SiteTreeActionsTest extends FunctionalTest {
// Looking at the old version, the ability to rollback to that version is available
$version = DB::query('SELECT "Version" FROM "SiteTree_versions" WHERE "Content" = \'test page first version\'')->value();
$old = Versioned::get_version('Page', $p->ID, $version);
$actions = $old->getCMSActions()->column('Name');
$this->assertNotContains('action_save', $actions);
$this->assertNotContains('action_publish', $actions);
$this->assertNotContains('action_unpublish', $actions);
$this->assertNotContains('action_delete', $actions);
$this->assertContains('action_email', $actions);
$this->assertContains('action_rollback', $actions);
$actions = $old->getCMSActions();
$this->assertNull($actions->dataFieldByName('action_save'));
$this->assertNull($actions->dataFieldByName('action_publish'));
$this->assertNull($actions->dataFieldByName('action_unpublish'));
$this->assertNull($actions->dataFieldByName('action_delete'));
$this->assertNotNull($actions->dataFieldByName('action_email'));
$this->assertNotNull($actions->dataFieldByName('action_rollback'));
}
}