Merge branch '106-add-edit-records-rc'

Conflicts:
	admin/code/LeftAndMain.php
	admin/css/screen.css
	admin/scss/_style.scss
	admin/templates/Includes/LeftAndMain_EditForm.ss
	css/GridField.css
	filesystem/Folder.php
	forms/gridfield/GridField.php
	forms/gridfield/GridFieldDefaultColumns.php
	forms/gridfield/GridFieldPopupForms.php
This commit is contained in:
Ingo Schommer 2012-02-27 23:58:10 +01:00
commit bcc73de85e
25 changed files with 407 additions and 141 deletions

View File

@ -473,8 +473,7 @@ class LeftAndMain extends Controller {
/** /**
* Return a list of appropriate templates for this class, with the given suffix * Return a list of appropriate templates for this class, with the given suffix
*/ */
protected function getTemplatesWithSuffix($suffix) { public function getTemplatesWithSuffix($suffix) {
$templates = array();
$classes = array_reverse(ClassInfo::ancestry($this->class)); $classes = array_reverse(ClassInfo::ancestry($this->class));
foreach($classes as $class) { foreach($classes as $class) {
$template = $class . $suffix; $template = $class . $suffix;

View File

@ -107,7 +107,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
*/ */
function RootForm() { function RootForm() {
$config = new GridFieldConfig_Base(25); $config = new GridFieldConfig_Base(25);
$config->addComponent(new GridFieldPopupForms($this, 'RootForm')); $config->addComponent(new GridFieldPopupForms());
$config->addComponent(new GridFieldExporter()); $config->addComponent(new GridFieldExporter());
$memberList = new GridField('Members', 'All members', DataList::create('Member'), $config); $memberList = new GridField('Members', 'All members', DataList::create('Member'), $config);

View File

@ -109,8 +109,8 @@ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav,
.cms .ui-widget-header .ui-dialog-title { padding: 6px 0; text-shadow: #ced7dc 1px 1px 0; } .cms .ui-widget-header .ui-dialog-title { padding: 6px 0; text-shadow: #ced7dc 1px 1px 0; }
.cms .ui-widget-header a.ui-dialog-titlebar-close { position: absolute; top: -8px; right: -15px; width: 30px; height: 30px; z-index: 100000; } .cms .ui-widget-header a.ui-dialog-titlebar-close { position: absolute; top: -8px; right: -15px; width: 30px; height: 30px; z-index: 100000; }
.cms .ui-widget-header a.ui-state-hover { border-color: transparent; background: transparent; } .cms .ui-widget-header a.ui-state-hover { border-color: transparent; background: transparent; }
.cms .ui-widget-header a.ui-state-hover .ui-icon-closethick { background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -42px no-repeat; } .cms .ui-widget-header a.ui-state-hover .ui-icon-closethick { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -252px no-repeat; }
.cms .ui-widget-header .ui-icon-closethick { background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -82px no-repeat; width: 30px; height: 30px; } .cms .ui-widget-header .ui-icon-closethick { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -292px no-repeat; width: 30px; height: 30px; }
.cms .ui-state-hover { cursor: pointer; } .cms .ui-state-hover { cursor: pointer; }
.cms .ui-widget input, .cms .ui-widget select, .cms .ui-widget textarea, .cms .ui-widget button { color: #444444; font-size: 12px; font-family: Arial, sans-serif; } .cms .ui-widget input, .cms .ui-widget select, .cms .ui-widget textarea, .cms .ui-widget button { color: #444444; font-size: 12px; font-family: Arial, sans-serif; }
@ -383,7 +383,7 @@ form.member-profile-form #Groups .middleColumn .TreeDropdownField { width: 90%;
form.member-profile-form #Permissions .optionset li { float: none; width: auto; } form.member-profile-form #Permissions .optionset li { float: none; width: auto; }
.cms .cms-content { border-right: 1px solid rgba(201, 205, 206, 0.8); -moz-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -webkit-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -o-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; } .cms .cms-content { border-right: 1px solid rgba(201, 205, 206, 0.8); -moz-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -webkit-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -o-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; }
.cms .cms-content-fields { /* always show a y scroll bar as popups like TreeDropdowns can trigger longer pages and the extra scroll bar doesn't fire our sizing bar */ overflow-y: auto; overflow-x: auto; background: none; -moz-box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; -webkit-box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; -o-box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; box-shadow: rgba(107, 120, 123, 0.5) 0 0 4px; } .cms .cms-content-fields { /* always show a y scroll bar as popups like TreeDropdowns can trigger longer pages and the extra scroll bar doesn't fire our sizing bar */ overflow-y: auto; overflow-x: auto; background: none; width: 100%; }
/** -------------------------------------------- Panels -------------------------------------------- */ /** -------------------------------------------- Panels -------------------------------------------- */
.cms-panel { overflow: hidden; } .cms-panel { overflow: hidden; }
@ -447,9 +447,18 @@ body.cms-dialog { overflow: auto; background: url("../images/textures/bg_cms_mai
/** -------------------------------------------- Step labels -------------------------------------------- */ /** -------------------------------------------- Step labels -------------------------------------------- */
.step-label > * { display: inline-block; vertical-align: top; } .step-label > * { display: inline-block; vertical-align: top; }
.step-label .flyout { height: 18px; font-size: 14px; font-weight: bold; -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -o-border-top-left-radius: 3px; -ms-border-top-left-radius: 3px; -khtml-border-top-left-radius: 3px; border-top-left-radius: 3px; -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; -o-border-bottom-left-radius: 3px; -ms-border-bottom-left-radius: 3px; -khtml-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; background-color: #667980; padding: 4px 3px 4px 6px; text-align: center; text-shadow: none; color: #fff; } .step-label .flyout { height: 18px; font-size: 14px; font-weight: bold; -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -o-border-top-left-radius: 3px; -ms-border-top-left-radius: 3px; -khtml-border-top-left-radius: 3px; border-top-left-radius: 3px; -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; -o-border-bottom-left-radius: 3px; -ms-border-bottom-left-radius: 3px; -khtml-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; background-color: #667980; padding: 4px 3px 4px 6px; text-align: center; text-shadow: none; color: #fff; }
.step-label .arrow { height: 26px; width: 10px; background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -213px no-repeat; margin-right: 4px; } .step-label .arrow { height: 26px; width: 10px; background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -759px no-repeat; margin-right: 4px; }
.step-label .title { height: 18px; padding: 4px; } .step-label .title { height: 18px; padding: 4px; }
/** -------------------------------------------- Item Edit Form -------------------------------------------- */
#Form_ItemEditForm .field { width: 100%; }
#Form_ItemEditForm .field .fieldgroup { height: 230px; float: left; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field.first { position: relative; margin-left: 0px; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field { clear: both; width: 500px; margin-left: 420px; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field img { -moz-border-radius: 8px; -webkit-border-radius: 8px; -o-border-radius: 8px; -ms-border-radius: 8px; -khtml-border-radius: 8px; border-radius: 8px; border-width: 3px; border-style: dashed; border-color: #8c99a1; position: absolute; top: 8px; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field label { font-weight: bold; float: left; padding-top: 8px; line-height: 16px; text-shadow: white 1px 1px 0; }
#Form_ItemEditForm .field .fieldgroup .fieldgroup-field span { float: left; padding-left: 8px; font-style: italic; color: #777777; }
/** This file defines the jstree base styling (see http://jstree.com), as well as any customizations (see bottom of file). The styles are usually added through jstree.js on DOM load, but we need it earlier in order to correctly display the uninitialized tree. */ /** This file defines the jstree base styling (see http://jstree.com), as well as any customizations (see bottom of file). The styles are usually added through jstree.js on DOM load, but we need it earlier in order to correctly display the uninitialized tree. */
.cms .jstree ul { display: block; margin: 0; padding: 0; background: none; list-style-type: none; } .cms .jstree ul { display: block; margin: 0; padding: 0; background: none; list-style-type: none; }
.cms .jstree li { display: block; margin: 0; padding: 0; list-style-type: none; display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; } .cms .jstree li { display: block; margin: 0; padding: 0; list-style-type: none; display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; }
@ -564,7 +573,7 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.cms-logo span { font-weight: bold; font-size: 14px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; } .cms-logo span { font-weight: bold; font-size: 14px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; o-text-overflow: ellipsis; }
.cms-login-status { border-top: 1px solid #19435c; height: 24px; padding: 7px 4px 0 4px; overflow: hidden; line-height: 16px; font-size: 11px; } .cms-login-status { border-top: 1px solid #19435c; height: 24px; padding: 7px 4px 0 4px; overflow: hidden; line-height: 16px; font-size: 11px; }
.cms-login-status .logout-link { display: inline-block; height: 16px; width: 16px; float: left; margin: 0 8px 0 3px; background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -123px no-repeat; text-indent: -9999em; } .cms-login-status .logout-link { display: inline-block; height: 16px; width: 16px; float: left; margin: 0 8px 0 3px; background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -669px no-repeat; text-indent: -9999em; }
.cms-menu { z-index: 80; background: #c6d7df; border-right: 1px solid #8c99a1; width: 191px; /* 8x24 - 1 */ -moz-box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; -webkit-box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; -o-box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; } .cms-menu { z-index: 80; background: #c6d7df; border-right: 1px solid #8c99a1; width: 191px; /* 8x24 - 1 */ -moz-box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; -webkit-box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; -o-box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; box-shadow: rgba(107, 120, 123, 0.5) 0 0 8px; }
.cms-menu a { text-decoration: none; } .cms-menu a { text-decoration: none; }
@ -584,12 +593,12 @@ li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
.cms-menu-list li a .icon { display: inline-block; float: left; margin: 4px 10px 0 4px; filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); opacity: 0.7; } .cms-menu-list li a .icon { display: inline-block; float: left; margin: 4px 10px 0 4px; filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); opacity: 0.7; }
.cms-menu-list li a .text { display: inline-block; float: left; } .cms-menu-list li a .text { display: inline-block; float: left; }
.cms-menu-list li a .toggle-children { display: inline-block; float: right; width: 20px; height: 100%; cursor: pointer; } .cms-menu-list li a .toggle-children { display: inline-block; float: right; width: 20px; height: 100%; cursor: pointer; }
.cms-menu-list li a .toggle-children .toggle-children-icon { display: inline-block; width: 8px; height: 8px; background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -149px no-repeat; vertical-align: middle; } .cms-menu-list li a .toggle-children .toggle-children-icon { display: inline-block; width: 8px; height: 8px; background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -695px no-repeat; vertical-align: middle; }
.cms-menu-list li a .toggle-children.opened .toggle-children-icon { background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -165px no-repeat; } .cms-menu-list li a .toggle-children.opened .toggle-children-icon { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -711px no-repeat; }
.cms-menu-list li ul { display: none; } .cms-menu-list li ul { display: none; }
.cms-menu-list li.current a { color: white; text-shadow: #1e5270 0 -1px 0; border-top: 1px solid #55a4d2; border-bottom: 1px solid #1e5270; background-color: #338dc1; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #338dc1), color-stop(100%, #287099)); background-image: -webkit-linear-gradient(#338dc1, #287099); background-image: -moz-linear-gradient(#338dc1, #287099); background-image: -o-linear-gradient(#338dc1, #287099); background-image: -ms-linear-gradient(#338dc1, #287099); background-image: linear-gradient(#338dc1, #287099); } .cms-menu-list li.current a { color: white; text-shadow: #1e5270 0 -1px 0; border-top: 1px solid #55a4d2; border-bottom: 1px solid #1e5270; background-color: #338dc1; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #338dc1), color-stop(100%, #287099)); background-image: -webkit-linear-gradient(#338dc1, #287099); background-image: -moz-linear-gradient(#338dc1, #287099); background-image: -o-linear-gradient(#338dc1, #287099); background-image: -ms-linear-gradient(#338dc1, #287099); background-image: linear-gradient(#338dc1, #287099); }
.cms-menu-list li.current a .toggle-children .toggle-children-icon { background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -181px no-repeat; } .cms-menu-list li.current a .toggle-children .toggle-children-icon { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -727px no-repeat; }
.cms-menu-list li.current a .toggle-children.opened .toggle-children-icon { background: url('../images/sprites-32x32-s9a54b65fa5.png') 0 -197px no-repeat; } .cms-menu-list li.current a .toggle-children.opened .toggle-children-icon { background: url('../images/sprites-32x32-sa4e142f7f0.png') 0 -743px no-repeat; }
.cms-menu-list li.current ul { border-top: none; display: block; } .cms-menu-list li.current ul { border-top: none; display: block; }
.cms-menu-list li.current li { background-color: #287099; } .cms-menu-list li.current li { background-color: #287099; }
.cms-menu-list li.current li a { font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; color: #e2f0f7; background: none; border-top: 1px solid #338dc1; border-bottom: 1px solid #1e5270; } .cms-menu-list li.current li a { font-size: 11px; padding: 0 10px 0 40px; height: 32px; line-height: 32px; color: #e2f0f7; background: none; border-top: 1px solid #338dc1; border-bottom: 1px solid #1e5270; }

View File

@ -828,7 +828,7 @@ form.member-profile-form {
overflow-y: auto; overflow-y: auto;
overflow-x: auto; overflow-x: auto;
background: none; background: none;
@include box-shadow($color-shadow-dark 0 0 ($grid-x / 2)); width:100%;
} }
} }
@ -973,6 +973,7 @@ form.member-profile-form {
background-color: #92a5b2; background-color: #92a5b2;
padding: $grid-y/2 $grid-x/2 $grid-y/2 $grid-x*2; padding: $grid-y/2 $grid-x/2 $grid-y/2 $grid-x*2;
border-bottom: 2px solid #8399a7; border-bottom: 2px solid #8399a7;
@include background-image(linear-gradient(#ced7dc, #92a5b2)); @include background-image(linear-gradient(#ced7dc, #92a5b2));
} }
@ -1146,4 +1147,50 @@ body.cms-dialog {
padding: 4px; padding: 4px;
} }
} }
/** --------------------------------------------
* Item Edit Form
* -------------------------------------------- */
#Form_ItemEditForm {
.field {
width:100%;
.fieldgroup {
height:230px;
float:left;
.fieldgroup-field.first {
position:relative;
margin-left:0px;
}
.fieldgroup-field {
clear:both;
width:500px;
margin-left:420px;
img {
@include border-radius (8px);
border: {
width:3px;
style:dashed;
color:$color-menu-border;
}
position:absolute;
top:8px;
}
label {
font-weight:bold;
float:left;
padding-top:8px;
line-height:16px;
text-shadow: $color-text-light 1px 1px 0;
}
span {
float:left;
padding-left:8px;
font-style:italic;
color:lighten($color-text, 20%);
}
}
}
}
}

View File

@ -1,4 +0,0 @@
<div class="cms-content-fields center">
<a class="backlink ss-ui-button" href="$Backlink">Back</a>
$ItemEditForm
</div>

View File

@ -21,6 +21,13 @@
<% end_if %> <% end_if %>
<!-- <div class="cms-content-search">...</div> --> <!-- <div class="cms-content-search">...</div> -->
<% if Backlink %>
<a class="backlink ss-ui-button" href="$Backlink">
<% _t('Back', 'Back') %>
</a>
<% end_if %>
</div> </div>
</div> </div>
@ -28,7 +35,7 @@
$EditFormTools $EditFormTools
<% end_control %> <% end_control %>
<div class="cms-content-fields center cms-panel-padded"> <div class="cms-content-fields center <% if not Fields.hasTabset %>cms-panel-padded<% end_if %>">
<% if Message %> <% if Message %>
<p id="{$FormName}_error" class="message $MessageType">$Message</p> <p id="{$FormName}_error" class="message $MessageType">$Message</p>
<% else %> <% else %>

View File

@ -298,6 +298,23 @@ class Controller extends RequestHandler {
public function hasAction($action) { public function hasAction($action) {
return parent::hasAction($action) || $this->hasActionTemplate($action); return parent::hasAction($action) || $this->hasActionTemplate($action);
} }
/**
* Removes all the "action" part of the current URL and returns the result.
* If no action parameter is present, returns the full URL
* @static
* @return String
*/
public function removeAction($fullURL, $action = null) {
if (!$action) $action = $this->getAction(); //default to current action
$returnURL = $fullURL;
if (($pos = strpos($fullURL, $action)) !== false) {
$returnURL = substr($fullURL,0,$pos);
}
return $returnURL;
}
/** /**
* Returns TRUE if this controller has a template that is specifically designed to handle a specific action. * Returns TRUE if this controller has a template that is specifically designed to handle a specific action.

View File

@ -9,20 +9,22 @@
.cms table.ss-gridfield-table tbody td button { border: none; background: none; margin: 0 0 0 2px; padding: 0; width: auto; text-shadow: none; } .cms table.ss-gridfield-table tbody td button { border: none; background: none; margin: 0 0 0 2px; padding: 0; width: auto; text-shadow: none; }
.cms table.ss-gridfield-table tfoot { color: #1d2224; } .cms table.ss-gridfield-table tfoot { color: #1d2224; }
.cms table.ss-gridfield-table tfoot tr td { background: #95a5ab; padding: .7em; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } .cms table.ss-gridfield-table tfoot tr td { background: #95a5ab; padding: .7em; border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
.cms table.ss-gridfield-table tr.sortable-header th { background: #7f9198; } .cms table.ss-gridfield-table tr.title { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; }
.cms table.ss-gridfield-table tr.title th { position: relative; background: #7f9198; border-top: 1px solid rgba(0, 0, 0, 0.1); padding: 5px; min-height: 40px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; }
.cms table.ss-gridfield-table tr.title th h2 { padding: 0px; font-size: 16px; color: #fff; margin: 0; display: inline; }
.cms table.ss-gridfield-table tr.title th .new { font-size: 14px; border-color: rgba(0, 0, 0, 0.1); float: right; }
.cms table.ss-gridfield-table tr.sortable-header { background: #bac8ce; }
.cms table.ss-gridfield-table tr:hover { background: #FFFAD6 !important; } .cms table.ss-gridfield-table tr:hover { background: #FFFAD6 !important; }
.cms table.ss-gridfield-table tr:first-child { background: transparent; } .cms table.ss-gridfield-table tr:first-child { background: transparent; }
.cms table.ss-gridfield-table tr.ss-gridfield-even { background: #f0f4f7; } .cms table.ss-gridfield-table tr.ss-gridfield-even { background: #f0f4f7; }
.cms table.ss-gridfield-table tr.ss-gridfield-even.ss-gridfield-last { border-bottom: none; } .cms table.ss-gridfield-table tr.ss-gridfield-even.ss-gridfield-last { border-bottom: none; }
.cms table.ss-gridfield-table tr.even { background: #f0f4f7; } .cms table.ss-gridfield-table tr.even { background: #f0f4f7; }
.cms table.ss-gridfield-table tr th { font-weight: bold; font-size: 12px; color: #FFF; padding: 5px; border-right: 1px solid rgba(0, 0, 0, 0.1); } .cms table.ss-gridfield-table tr th { font-weight: bold; font-size: 12px; color: #FFF; padding: 5px; border-right: 1px solid rgba(0, 0, 0, 0.1); }
.cms table.ss-gridfield-table tr th.main:first-child { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; }
.cms table.ss-gridfield-table tr th.main:last-child { -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; }
.cms table.ss-gridfield-table tr th div.fieldgroup, .cms table.ss-gridfield-table tr th div.fieldgroup-field { width: auto; } .cms table.ss-gridfield-table tr th div.fieldgroup, .cms table.ss-gridfield-table tr th div.fieldgroup-field { width: auto; }
.cms table.ss-gridfield-table tr th div.fieldgroup { min-width: 200px; padding-right: 0; } .cms table.ss-gridfield-table tr th div.fieldgroup { min-width: 200px; padding-right: 0; }
.cms table.ss-gridfield-table tr th.extra, .cms table.ss-gridfield-table tr th.action { background: #7f9198; padding: 0; cursor: default; } .cms table.ss-gridfield-table tr th.extra, .cms table.ss-gridfield-table tr th.action { padding: 0; cursor: default; }
.cms table.ss-gridfield-table tr th.extra button.ss-ui-button, .cms table.ss-gridfield-table tr th.extra button:hover.ss-ui-button, .cms table.ss-gridfield-table tr th.action button.ss-ui-button, .cms table.ss-gridfield-table tr th.action button:hover.ss-ui-button { margin-left: .9em; color: #222; } .cms table.ss-gridfield-table tr th.extra button.ss-ui-button, .cms table.ss-gridfield-table tr th.extra button:hover.ss-ui-button, .cms table.ss-gridfield-table tr th.action button.ss-ui-button, .cms table.ss-gridfield-table tr th.action button:hover.ss-ui-button { margin-left: .9em; color: #222; }
.cms table.ss-gridfield-table tr th.main { border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); } .cms table.ss-gridfield-table tr th.main { border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; background: #9cb0b9; border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
.cms table.ss-gridfield-table tr th.main span { text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; } .cms table.ss-gridfield-table tr th.main span { text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; }
.cms table.ss-gridfield-table tr th.extra { background: #bac8ce; padding: 5px; border-top: rgba(0, 0, 0, 0.3); } .cms table.ss-gridfield-table tr th.extra { background: #bac8ce; padding: 5px; border-top: rgba(0, 0, 0, 0.3); }
.cms table.ss-gridfield-table tr th.extra span { width: auto; display: inline; position: static; } .cms table.ss-gridfield-table tr th.extra span { width: auto; display: inline; position: static; }

View File

@ -119,6 +119,8 @@ class File extends DataObject {
'cab','arj','tar','zip','zipx','sit','sitx','gz','tgz','bz2','ace','arc','pkg','dmg','hqx','jar', 'cab','arj','tar','zip','zipx','sit','sitx','gz','tgz','bz2','ace','arc','pkg','dmg','hqx','jar',
'xml','pdf', 'xml','pdf',
); );
protected static $labelSeparator = ':';
/** /**
* @var If this is true, then restrictions set in {@link $allowed_max_file_size} and * @var If this is true, then restrictions set in {@link $allowed_max_file_size} and
@ -255,23 +257,58 @@ class File extends DataObject {
return $this->canEdit($member); return $this->canEdit($member);
} }
/*
* Generate and return the preview image / file upload / replace field for this File
* @return FormField
*/
protected function getFilePreview() {
//file upload
$uploadField = new UploadField('UploadField','Upload Field');
$uploadField->setConfig('previewMaxWidth', 40);
$uploadField->setConfig('previewMaxHeight', 30);
//$uploadField->setTemplate('FileEditUploadField');
if ($this->ParentID) {
$parent = $this->Parent();
if ($parent) { //set the parent that the Upload field should use for uploads
$uploadField->setFolderName($parent->getFilename());
$uploadField->setRecord($parent);
//TODO: make the uploadField replace the existing file
}
}
return $uploadField;
}
/**
* Returns the fields to power the edit screen of files in the CMS
* @return FieldList
*/
function getCMSFields() { function getCMSFields() {
$urlLink = "<div class='field readonly'>"; $urlLink = "<div class='field readonly'>";
$urlLink .= "<label class='left'>"._t('AssetTableField.URL','URL')."</label>"; $urlLink .= "<label class='left'>"._t('AssetTableField.URL','URL')."</label>";
$urlLink .= "<span class='readonly'><a href='{$this->Link()}' target='_blank'>{$this->RelativeLink()}</a></span>"; $urlLink .= "<span class='readonly'><a href='{$this->Link()}' target='_blank'>{$this->RelativeLink()}</a></span>";
$urlLink .= "</div>"; $urlLink .= "</div>";
//create the file attributes in a FieldGroup
$filePreview = new FieldGroup(
$this->getFilePreview(),
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type').self::$labelSeparator),
new ReadonlyField("Filename", _t('AssetTableField.FILENAME','File name').self::$labelSeparator),
new ReadonlyField("Size", _t('AssetTableField.SIZE','File size').self::$labelSeparator, $this->getSize()),
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded').self::$labelSeparator),
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed').self::$labelSeparator)
);
$filePreview->setTitle("File preview");
$filePreview->setName("FilePreview");
return new FieldList( return new FieldList(
new TabSet('Root', new TabSet('Root',
new Tab('Main', new Tab('Main',
$filePreview,
new TextField("Title", _t('AssetTableField.TITLE','Title')), new TextField("Title", _t('AssetTableField.TITLE','Title')),
new TextField("Name", _t('AssetTableField.FILENAME','Filename')), new TextField("Name", _t('AssetTableField.FILENAME','Filename')),
new LiteralField("AbsoluteURL", $urlLink), new LiteralField("AbsoluteURL", $urlLink), //TODO: replace this is a proper preview
new ReadonlyField("FileType", _t('AssetTableField.TYPE','Type')), new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups())
new ReadonlyField("Size", _t('AssetTableField.SIZE','Size'), $this->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'))
) )
) )
); );

View File

@ -97,14 +97,21 @@ class FieldGroup extends CompositeField {
$spaceZebra = isset($this->zebra) ? " fieldgroup-$this->zebra" : ''; $spaceZebra = isset($this->zebra) ? " fieldgroup-$this->zebra" : '';
$idAtt = isset($this->id) ? " id=\"{$this->id}\"" : ''; $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : '';
$content = "<div class=\"fieldgroup$spaceZebra\"$idAtt>"; $content = "<div class=\"fieldgroup$spaceZebra\"$idAtt>";
$count = 1;
foreach($fs as $subfield) { foreach($fs as $subfield) {
$childZebra = (!isset($childZebra) || $childZebra == "odd") ? "even" : "odd"; $childZebra = (!isset($childZebra) || $childZebra == "odd") ? "even" : "odd";
if($subfield->hasMethod('setZebra')) { if($subfield->hasMethod('setZebra')) {
$subfield->setZebra($childZebra); $subfield->setZebra($childZebra);
} }
$content .= "<div class=\"fieldgroup-field\">" . $subfield->{$this->subfieldParam}() . "</div>"; //label the first and last fields of each surrounding div
if ($count == 1) $firstLast = "first";
elseif ($count == count($fs)) $firstLast = "last";
else $firstLast = '';
$content .= "<div class=\"fieldgroup-field $firstLast\">" . $subfield->{$this->subfieldParam}() . "</div>";
$count++;
} }
$content .= "</div>"; $content .= "</div>";

View File

@ -379,10 +379,9 @@ class Form extends RequestHandler {
if($field = $this->checkFieldsForAction($field->FieldList(), $funcName)) { if($field = $this->checkFieldsForAction($field->FieldList(), $funcName)) {
return $field; return $field;
} }
} elseif (!$field->hasMethod($funcName)) { } elseif ($field->hasMethod($funcName)) {
continue; return $field;
} }
return $field;
} }
} }

View File

@ -80,8 +80,6 @@ class GridField extends FormField {
*/ */
public function __construct($name, $title = null, SS_List $dataList = null, GridFieldConfig $config = null) { public function __construct($name, $title = null, SS_List $dataList = null, GridFieldConfig $config = null) {
parent::__construct($name, $title, null); parent::__construct($name, $title, null);
FormField::__construct($name);
if($dataList) { if($dataList) {
$this->setList($dataList); $this->setList($dataList);
@ -386,6 +384,7 @@ class GridField extends FormField {
$item->augmentColumns($this, $columns); $item->augmentColumns($this, $columns);
} }
} }
return $columns; return $columns;
} }
@ -404,8 +403,11 @@ class GridField extends FormField {
} }
if(!empty($this->columnDispatch[$column])) { if(!empty($this->columnDispatch[$column])) {
$handler = $this->columnDispatch[$column]; $content = "";
return $handler->getColumnContent($this, $record, $column); foreach($this->columnDispatch[$column] as $handler) {
$content .= $handler->getColumnContent($this, $record, $column);
}
return $content;
} else { } else {
throw new InvalidArgumentException("Bad column '$column'"); throw new InvalidArgumentException("Bad column '$column'");
} }
@ -427,15 +429,18 @@ class GridField extends FormField {
} }
if(!empty($this->columnDispatch[$column])) { if(!empty($this->columnDispatch[$column])) {
$handler = $this->columnDispatch[$column]; $attrs = array();
$attrs = $handler->getColumnAttributes($this, $record, $column);
if(is_array($attrs)) { foreach($this->columnDispatch[$column] as $handler) {
return $attrs; $column_attrs = $handler->getColumnAttributes($this, $record, $column);
} elseif($attrs) {
throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnAttributes()"); if(is_array($column_attrs))
} else { $attrs = array_merge($attrs, $column_attrs);
return array(); elseif($column_attrs)
throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnAttributes()");
} }
return $attrs;
} else { } else {
throw new InvalidArgumentException("Bad column '$column'"); throw new InvalidArgumentException("Bad column '$column'");
} }
@ -456,13 +461,19 @@ class GridField extends FormField {
} }
if(!empty($this->columnDispatch[$column])) { if(!empty($this->columnDispatch[$column])) {
$handler = $this->columnDispatch[$column]; $metadata = array();
$metadata = $handler->getColumnMetadata($this, $column);
if(is_array($metadata)) { foreach($this->columnDispatch[$column] as $handler) {
return $metadata; $column_metadata = $handler->getColumnMetadata($this, $column);
} elseif($metadata) {
throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnMetadata()"); if(is_array($column_metadata))
$metadata = array_merge($metadata, $column_metadata);
else
throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnMetadata()");
} }
return $metadata;
} }
throw new InvalidArgumentException("Bad column '$column'"); throw new InvalidArgumentException("Bad column '$column'");
} }
@ -489,10 +500,10 @@ class GridField extends FormField {
if($item instanceof GridField_ColumnProvider) { if($item instanceof GridField_ColumnProvider) {
$columns = $item->getColumnsHandled($this); $columns = $item->getColumnsHandled($this);
foreach($columns as $column) { foreach($columns as $column) {
$this->columnDispatch[$column] = $item; $this->columnDispatch[$column][] = $item;
} }
} }
} }
} }
/** /**
@ -729,23 +740,18 @@ class GridField_Action extends FormAction {
$actionData['StateID'] = $id; $actionData['StateID'] = $id;
// And generate field // And generate field
$attributes = array( $data = new ArrayData(array(
'class' => ($this->extraClass() ? $this->extraClass() : '') . ' action-' . $this->actionName, 'Class' => ($this->extraClass() ? $this->extraClass() : '') . ($this->isReadonly() ? ' disabled' : ''),
'id' => $this->id(), 'ID' => $this->id(),
'type' => 'submit',
// Note: This field needs to be less than 65 chars, otherwise Suhosin security patch // Note: This field needs to be less than 65 chars, otherwise Suhosin security patch
// will strip it from the requests // will strip it from the requests
'name' => 'action_gridFieldAlterAction'. '?' . http_build_query($actionData), 'Name' => 'action_gridFieldAlterAction'. '?' . http_build_query($actionData),
'tabindex' => $this->getTabIndex(), 'Disabled' => $this->isReadonly(),
'data-url' => $this->gridField->Link(), 'Label' => $this->buttonLabel,
); 'DataURL' => $this->gridField->Link(),
));
if($this->isReadonly()) { return $data->renderWith('GridField_Action');
$attributes['disabled'] = 'disabled';
$attributes['class'] = $attributes['class'] . ' disabled';
}
return $this->createTag('button', $attributes, $this->buttonLabel);
} }
/** /**

View File

@ -1,7 +1,10 @@
<?php <?php
/** /**
* This class is an GridField Component that add Delete action for Objects in the GridField * Provides the entry point to editing a single record presented by the grid.
* * Doesn't show an edit view on its own or modifies the record, but rather relies on routing conventions
* established in {@link getColumnContent()}. The default routing applies to
* the {@link GridFieldPopupForms} component, which has to be added separately
* to the grid field configuration.
*/ */
class GridFieldAction_Edit implements GridField_ColumnProvider { class GridFieldAction_Edit implements GridField_ColumnProvider {
@ -12,7 +15,8 @@ class GridFieldAction_Edit implements GridField_ColumnProvider {
* @param array $columns * @param array $columns
*/ */
public function augmentColumns($gridField, &$columns) { public function augmentColumns($gridField, &$columns) {
$columns[] = 'EditAction'; if(!in_array('Actions', $columns))
$columns[] = 'Actions';
} }
/** /**
@ -35,7 +39,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider {
* @return array * @return array
*/ */
public function getColumnMetadata($gridField, $columnName) { public function getColumnMetadata($gridField, $columnName) {
if($columnName == 'EditAction') { if($columnName == 'Actions') {
return array('title' => ''); return array('title' => '');
} }
} }
@ -47,7 +51,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider {
* @return type * @return type
*/ */
public function getColumnsHandled($gridField) { public function getColumnsHandled($gridField) {
return array('EditAction'); return array('Actions');
} }
/** /**
@ -57,7 +61,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider {
* @return array * @return array
*/ */
public function getActions($gridField) { public function getActions($gridField) {
return array('deleterecord'); return array();
} }
/** /**
@ -68,7 +72,11 @@ class GridFieldAction_Edit implements GridField_ColumnProvider {
* @return string - the HTML for the column * @return string - the HTML for the column
*/ */
public function getColumnContent($gridField, $record, $columnName) { public function getColumnContent($gridField, $record, $columnName) {
return sprintf('<a class="action-edit" href="%s">%s</a>', Controller::join_links($gridField->Link('item'), $record->ID, 'edit'), _t('GridAction.Edit', 'edit')); $data = new ArrayData(array(
'Link' => Controller::join_links($gridField->Link('item'), $record->ID, 'edit')
));
return $data->renderWith('GridFieldAction_Edit');
} }
/** /**
@ -98,7 +106,8 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti
* @param array $columns * @param array $columns
*/ */
public function augmentColumns($gridField, &$columns) { public function augmentColumns($gridField, &$columns) {
$columns[] = 'DeleteAction'; if(!in_array('Actions', $columns))
$columns[] = 'Actions';
} }
/** /**
@ -121,7 +130,7 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti
* @return array * @return array
*/ */
public function getColumnMetadata($gridField, $columnName) { public function getColumnMetadata($gridField, $columnName) {
if($columnName == 'DeleteAction') { if($columnName == 'Actions') {
return array('title' => ''); return array('title' => '');
} }
} }
@ -133,7 +142,7 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti
* @return type * @return type
*/ */
public function getColumnsHandled($gridField) { public function getColumnsHandled($gridField) {
return array('DeleteAction'); return array('Actions');
} }
/** /**
@ -175,12 +184,11 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti
* @return void * @return void
*/ */
public function handleAction(GridField $gridField, $actionName, $arguments, $data) { public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
$id = $arguments['RecordID'];
$item = $gridField->getList()->byID($id);
if(!$item) return;
if($actionName == 'deleterecord') { if($actionName == 'deleterecord') {
$item->delete(); $id = $arguments['RecordID'];
$item = $gridField->getList()->byID($id);
if(!$item) return;
$item->delete();
} }
} }
} }

View File

@ -87,15 +87,16 @@ class GridFieldConfig_Base extends GridFieldConfig {
* @param int $itemsPerPage - How many items per page should show up per page * @param int $itemsPerPage - How many items per page should show up per page
* @return GridFieldConfig_Base * @return GridFieldConfig_Base
*/ */
public static function create($itemsPerPage=25){ public static function create($itemsPerPage=15){
return new GridFieldConfig_Base($itemsPerPage=25); return new GridFieldConfig_Base($itemsPerPage=15);
} }
/** /**
* *
* @param int $itemsPerPage - How many items per page should show up * @param int $itemsPerPage - How many items per page should show up
*/ */
public function __construct($itemsPerPage=25) { public function __construct($itemsPerPage=15) {
$this->addComponent(new GridFieldTitle());
$this->addComponent(new GridFieldSortableHeader()); $this->addComponent(new GridFieldSortableHeader());
$this->addComponent(new GridFieldFilter()); $this->addComponent(new GridFieldFilter());
$this->addComponent(new GridFieldDefaultColumns()); $this->addComponent(new GridFieldDefaultColumns());
@ -142,5 +143,6 @@ class GridFieldConfig_ManyManyEditor extends GridFieldConfig {
$this->addComponent(new GridFieldAction_Edit()); $this->addComponent(new GridFieldAction_Edit());
$this->addComponent(new GridFieldRelationDelete()); $this->addComponent(new GridFieldRelationDelete());
$this->addComponent(new GridFieldPaginator($itemsPerPage)); $this->addComponent(new GridFieldPaginator($itemsPerPage));
$this->addComponent(new GridFieldPopupForms());
} }
} }

View File

@ -18,7 +18,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
* *
* @var int * @var int
*/ */
protected $itemsPerPage = 25; protected $itemsPerPage = 15;
/** /**
* Which template to use for rendering * Which template to use for rendering
@ -31,7 +31,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
* *
* @param int $itemsPerPage - How many items should be displayed per page * @param int $itemsPerPage - How many items should be displayed per page
*/ */
public function __construct($itemsPerPage=25) { public function __construct($itemsPerPage=15) {
$this->itemsPerPage = $itemsPerPage; $this->itemsPerPage = $itemsPerPage;
} }

View File

@ -1,7 +1,10 @@
<?php <?php
/** /**
* Provides view and edit forms at GridField-specific URLs. These can be placed into pop-ups by an appropriate front-end. * Provides view and edit forms at GridField-specific URLs.
* These can be placed into pop-ups by an appropriate front-end.
* Usually added to a grid field alongside of {@link GridFieldAction_Edit}
* which takes care of linking the individual rows to their edit view.
* *
* The URLs provided will be off the following form: * The URLs provided will be off the following form:
* - <FormURL>/field/<GridFieldName>/item/<RecordID> * - <FormURL>/field/<GridFieldName>/item/<RecordID>
@ -9,22 +12,18 @@
*/ */
class GridFieldPopupForms implements GridField_URLHandler { class GridFieldPopupForms implements GridField_URLHandler {
/** /**
* @var String * @var String
*/ */
protected $template = 'GridFieldItemEditView'; protected $template = 'GridFieldPopupForms';
/**
*
* @var Controller
*/
protected $popupController;
/** /**
* *
* @var string * @var string
*/ */
protected $popupFormName; protected $name;
function getURLHandlers($gridField) { function getURLHandlers($gridField) {
return array( return array(
@ -41,12 +40,10 @@ class GridFieldPopupForms implements GridField_URLHandler {
* The arguments are experimental API's to support partial content to be passed back to whatever * The arguments are experimental API's to support partial content to be passed back to whatever
* controller who wants to display the getCMSFields * controller who wants to display the getCMSFields
* *
* @param Controller $popupController The controller object that will be used to render the pop-up forms * @param string $name The name of the edit form to place into the pop-up form
* @param string $popupFormName The name of the edit form to place into the pop-up form
*/ */
public function __construct($popupController, $popupFormName) { public function __construct($name = 'DetailForm') {
$this->popupController = $popupController; $this->name = $name;
$this->popupFormName = $popupFormName;
} }
/** /**
@ -56,10 +53,22 @@ class GridFieldPopupForms implements GridField_URLHandler {
* @return GridFieldPopupForm_ItemRequest * @return GridFieldPopupForm_ItemRequest
*/ */
public function handleItem($gridField, $request) { public function handleItem($gridField, $request) {
$record = $gridField->getList()->byId($request->param("ID")); $controller = $gridField->getForm()->Controller();
$handler = new GridFieldPopupForm_ItemRequest($gridField, $this, $record, $this->popupController, $this->popupFormName);
if(is_numeric($request->param('ID'))) {
$record = $gridField->getList()->byId($request->param("ID"));
} else {
$record = Object::create($gridField->getModelClass());
}
if(!$class = ClassInfo::exists(get_class($this) . "_ItemRequest")) {
$class = 'GridFieldPopupForm_ItemRequest';
}
$handler = Object::create($class, $gridField, $this, $record, $controller, $this->name);
$handler->setTemplate($this->template); $handler->setTemplate($this->template);
return $handler;
return $handler->handleRequest($request, $gridField);
} }
/** /**
@ -75,6 +84,20 @@ class GridFieldPopupForms implements GridField_URLHandler {
function getTemplate() { function getTemplate() {
return $this->template; return $this->template;
} }
/**
* @param String
*/
function setName($name) {
$this->name = $name;
}
/**
* @return String
*/
function getName() {
return $this->name;
}
} }
class GridFieldPopupForm_ItemRequest extends RequestHandler { class GridFieldPopupForm_ItemRequest extends RequestHandler {
@ -137,15 +160,29 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler {
} }
public function Link($action = null) { public function Link($action = null) {
return Controller::join_links($this->gridField->Link('item'), $this->record->ID, $action); return Controller::join_links($this->gridField->Link('item'), $this->record->ID ? $this->record->ID : 'new', $action);
} }
function edit($request) { function edit($request) {
$controller = $this->popupController; $controller = $this->popupController;
$form = $this->ItemEditForm($this->gridField, $request);
// TODO Coupling with CMS
if($controller instanceof LeftAndMain) {
$form->addExtraClass('cms-edit-form');
$form->setTemplate($controller->getTemplatesWithSuffix('_EditForm'));
$form->addExtraClass('cms-content center ss-tabset ' . $controller->BaseCSSClasses());
if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
// TODO Link back to controller action (and edited root record) rather than index,
// which requires more URL knowledge than the current link to this field gives us.
// The current root record is held in session only,
// e.g. page/edit/show/6/ vs. page/edit/EditForm/field/MyGridField/....
$form->Backlink = $controller->Link();
}
$return = $this->customise(array( $return = $this->customise(array(
'Backlink' => $this->gridField->getForm()->Controller()->Link(), 'Backlink' => $controller->Link(),
'ItemEditForm' => $this->ItemEditForm($this->gridField, $request), 'ItemEditForm' => $form,
))->renderWith($this->template); ))->renderWith($this->template);
if($controller->isAjax()) { if($controller->isAjax()) {
@ -154,7 +191,8 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler {
// If not requested by ajax, we need to render it within the controller context+template // If not requested by ajax, we need to render it within the controller context+template
return $controller->customise(array( return $controller->customise(array(
$this->popupFormName => $return, // TODO Allow customization
'Content' => $return,
)); ));
} }
} }
@ -163,35 +201,40 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler {
* Builds an item edit form. The arguments to getCMSFields() are the popupController and * Builds an item edit form. The arguments to getCMSFields() are the popupController and
* popupFormName, however this is an experimental API and may change. * popupFormName, however this is an experimental API and may change.
* *
* In the future, we will probably need to come up with a tigher object representing a partially * @todo In the future, we will probably need to come up with a tigher object representing a partially
* complete controller with gaps for extra functionality. This, for example, would be a better way * complete controller with gaps for extra functionality. This, for example, would be a better way
* of letting Security/login put its log-in form inside a UI specified elsewhere. * of letting Security/login put its log-in form inside a UI specified elsewhere.
* *
* @return Form * @return Form
*/ */
function ItemEditForm() { function ItemEditForm() {
$request = $this->popupController->getRequest();
$form = new Form( $form = new Form(
$this, $this,
'ItemEditForm', 'ItemEditForm',
// WARNING: The arguments passed here are a little arbitrary. This API will need cleanup // WARNING: The arguments passed here are a little arbitrary. This API will need cleanup
$this->record->getCMSFields($this->popupController, $this->popupFormName), $this->record->getCMSFields($this->popupController, $this->popupFormName),
new FieldList( new FieldList(
$saveAction = new FormAction('doSave', _t('GridFieldDetailsForm.Save', 'Save')) $saveAction = new FormAction('doSave', _t('GridFieldDetailsForm.Save', 'Save')),
$deleteAction = new FormAction('doDelete', _t('GridFieldDetailsForm.Delete', 'Delete'))
) )
); );
$saveAction->addExtraClass('ss-ui-action-constructive icon-accept'); $saveAction->addExtraClass('ss-ui-action-constructive');
$deleteAction->addExtraClass('ss-ui-action-destructive');
$form->loadDataFrom($this->record); $form->loadDataFrom($this->record);
return $form; return $form;
} }
function doSave($data, $form) { function doSave($data, $form) {
$new_record = $this->record->ID == 0;
try { try {
$form->saveInto($this->record); $form->saveInto($this->record);
$this->record->write(); $this->record->write();
if($new_record)
$this->gridField->getList()->add($this->record);
} catch(ValidationException $e) { } catch(ValidationException $e) {
$form->sessionMessage($e->getResult()->message(), 'bad'); $form->sessionMessage($e->getResult()->message(), 'bad');
return Director::redirectBack(); return Controller::curr()->redirectBack();
} }
// TODO Save this item into the given relationship // TODO Save this item into the given relationship
@ -207,6 +250,34 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler {
return $this->popupController->redirectBack(); return $this->popupController->redirectBack();
} }
function doDelete($data, $form) {
try {
$toDelete = $this->record;
if (!$toDelete->canDelete()) {
throw new ValidationException(_t('GridFieldDetailsForm.DeletePermissionsFailure',"No delete permissions"),0);
}
$toDelete->delete();
} catch(ValidationException $e) {
$form->sessionMessage($e->getResult()->message(), 'bad');
return Director::redirectBack();
}
$message = sprintf(
_t('ComplexTableField.SUCCESSEDIT2', 'Deleted %s %s'),
$this->record->singular_name(),
'<a href="' . $this->Link('edit') . '">"' . htmlspecialchars($this->record->Title, ENT_QUOTES) . '"</a>'
);
$form->sessionMessage($message, 'good');
//when an item is deleted, redirect to the revelant admin section without the action parameter
$controller = Controller::curr();
$noActionURL = $controller->removeAction($data['url']);
return Director::redirect($noActionURL, 302); //redirect back to admin section
}
/** /**
* @param String * @param String
*/ */

View File

@ -0,0 +1,13 @@
<?php
class GridFieldTitle implements GridField_HTMLProvider {
function getHTMLFragments($gridField) {
return array(
'header' => $gridField->customise(array(
'NewLink' => Controller::join_links($gridField->Link('item'), 'new')
))->renderWith('GridFieldTitle')
);
}
}
?>

View File

@ -112,7 +112,21 @@
).css({'position':'relative','margin':'0 auto','width':'65%'}).appendTo(eleInput.closest('th')); ).css({'position':'relative','margin':'0 auto','width':'65%'}).appendTo(eleInput.closest('th'));
} }
} }
}); });
$('fieldset.ss-gridfield .new-link').entwine({
onclick: function(e) {
$(this).trigger('opennewview', $(this).prop('href'));
return false;
}
});
$('fieldset.ss-gridfield .edit-link').entwine({
onclick: function(e) {
$(this).trigger('openeditview', $(this).prop('href'));
return false;
}
});
/** /**
* Allows selection of one or more rows in the grid field. * Allows selection of one or more rows in the grid field.
@ -146,4 +160,4 @@
}); });
}(jQuery)); }(jQuery));

View File

@ -63,7 +63,7 @@ class HasManyList extends RelationList {
* @param $itemID The ID of the item to be removed * @param $itemID The ID of the item to be removed
*/ */
function removeByID($itemID) { function removeByID($itemID) {
$item = $this->byID($item); $item = $this->byID($itemID);
return $this->remove($item); return $this->remove($item);
} }

View File

@ -72,6 +72,21 @@ class Image extends File {
parent::defineMethods(); parent::defineMethods();
} }
/*
* Generate and return the preview image / file upload / replace field for this File
* @return FormField
*/
protected function getFilePreview() {
$formattedImage = $this->getFormattedImage('AssetLibraryPreview');
$thumbnail = $formattedImage ? $formattedImage->URL : '';
$previewField = new LiteralField("ImageFull",
"<img id='thumbnailImage' class='thumbnail-preview' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$this->Name}' />\n"
);
return $previewField;
}
function getCMSFields() { function getCMSFields() {
$fields = parent::getCMSFields(); $fields = parent::getCMSFields();
@ -81,19 +96,9 @@ class Image extends File {
$urlLink .= "<span class='readonly'><a href='{$this->Link()}'>{$this->RelativeLink()}</a></span>"; $urlLink .= "<span class='readonly'><a href='{$this->Link()}'>{$this->RelativeLink()}</a></span>";
$urlLink .= "</div>"; $urlLink .= "</div>";
$big = $this->URL; //attach the addition file information for an image to the existing FieldGroup create in the parent class
$formattedImage = $this->getFormattedImage('AssetLibraryPreview'); $fileAttributes = $fields->FieldByName('Root.Main.FilePreview');
$thumbnail = $formattedImage ? $formattedImage->URL : ''; $fileAttributes->push(new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions').self::$labelSeparator));
// Hmm this required the translated string to be appended to BottomRoot to add this to the Main tab
$fields->addFieldToTab('Root.Main',
new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions'))
);
$fields->addFieldToTab('Root.Main',
new LiteralField("ImageFull",
"<img id='thumbnailImage' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$this->Name}' />"
)
);
return $fields; return $fields;
} }

View File

@ -86,11 +86,34 @@ $gf_border_radius: 7px;
} }
} }
tr { tr {
&.sortable-header { &.title {
@include border-top-radius($gf_border_radius);
th { th {
position: relative;
background: $gf_colour_gradient_dark; background: $gf_colour_gradient_dark;
border-top: 1px solid $gf_colour_border;
padding: 5px;
min-height: 40px;
@include background-image(linear-gradient($gf_colour_gradient_light, $gf_colour_gradient_dark));
@include border-top-radius($gf_border_radius);
@include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0);
h2{
padding: 0px;
font-size: 16px;
color:#fff;
margin:0;
display:inline;
}
.new{
font-size: 14px;
border-color: $gf_colour_border;
float: right;
}
} }
}
&.sortable-header {
background: $gf_colour_subheader;
} }
&:hover { &:hover {
background: #FFFAD6 !important; background: #FFFAD6 !important;
@ -116,10 +139,10 @@ $gf_border_radius: 7px;
padding: 5px; padding: 5px;
border-right: 1px solid $gf_colour_border; border-right: 1px solid $gf_colour_border;
&.main:first-child{ &.main:first-child{
@include border-top-left-radius($gf_border_radius); //@include border-top-left-radius($gf_border_radius);
} }
&.main:last-child{ &.main:last-child{
@include border-top-right-radius($gf_border_radius); //@include border-top-right-radius($gf_border_radius);
} }
div { div {
&.fieldgroup,&.fieldgroup-field { &.fieldgroup,&.fieldgroup-field {
@ -131,7 +154,6 @@ $gf_border_radius: 7px;
} }
} }
&.extra,&.action { &.extra,&.action {
background: $gf_colour_gradient_dark;
padding: 0; padding: 0;
cursor: default; cursor: default;
button,button:hover { button,button:hover {
@ -144,7 +166,8 @@ $gf_border_radius: 7px;
&.main{ &.main{
border-top: 1px solid $gf_colour_border; border-top: 1px solid $gf_colour_border;
color:#fff; color:#fff;
@include background-image(linear-gradient($gf_colour_gradient_light, $gf_colour_gradient_dark)); background: darken($gf_colour_subheader,10%);
border-bottom: 1px solid $gf_colour_border;
span{ span{
@include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0); @include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0);
} }

View File

@ -63,7 +63,6 @@ class Group extends DataObject {
Requirements::javascript(SAPPHIRE_DIR . '/javascript/PermissionCheckboxSetField.js'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/PermissionCheckboxSetField.js');
$config = new GridFieldConfig_ManyManyEditor('FirstName', true, 20); $config = new GridFieldConfig_ManyManyEditor('FirstName', true, 20);
$config->addComponent(new GridFieldPopupForms(Controller::curr(), 'EditForm'));
$config->addComponent(new GridFieldExporter()); $config->addComponent(new GridFieldExporter());
$memberList = new GridField('Members','Members', $this->Members(), $config); $memberList = new GridField('Members','Members', $this->Members(), $config);

View File

@ -0,0 +1 @@
<a class="edit-link" href="$Link">edit</a>

View File

@ -0,0 +1,3 @@
<tr class="title">
<th colspan="$ColumnCount"><h2>$Title</h2> <a href="$NewLink" class="action ss-ui-action-constructive ss-ui-button ui-button ui-widget ui-state-default ui-corner-all new new-link">Add new</a></th>
</tr>

View File

@ -0,0 +1 @@
<button id="$ID" class="$Class" name="$Name" type="submit" data-url="$DataURL"<% if Disabled %> disabled="disabled"<% end_if %>>$Label</button>