');
+ }
+
+ // Initialize drag-and-drop.
+ var regions = $('div.region');
+ regions.sortable({
+ connectWith: regions,
+ cursor: 'move',
+ dropOnEmpty: true,
+ items: '>div.block, div.disabled-block',
+ opacity: 0.8,
+ update: Drupal.behaviors.dashboard.update
+ });
+ },
+
+ update: function (event, ui) {
+ var item = $(ui.item);
+
+ // If the user dragged a disabled block, load the block contents.
+ if (item.hasClass('disabled-block')) {
+ var module, delta, itemClass;
+ itemClass = item.attr('class');
+ // Determine the block module and delta.
+ module = itemClass.match(/\bmodule-(\S+)\b/)[1];
+ delta = itemClass.match(/\bdelta-(\S+)\b/)[1];
+
+ // Load the newly enabled block's content.
+ $("div.content", item).load(Drupal.settings.dashboard.blockContent + '/' + module + '/' + delta);
+ console.log(Drupal.settings.dashboard.blockContent + '/' + module + '/' + delta);
+ // Remove "disabled-block" from the item's class, so we don't reload its
+ // content the next time it's dragged.
+ item.attr('class', itemClass.replace(/\bdisabled-block\b/, ''));
+ }
+
+ // Let the server know what the new block order is.
+ $.post(Drupal.settings.dashboard.updatePath, {
+ 'form_token': Drupal.settings.dashboard.formToken,
+ 'regions': Drupal.behaviors.dashboard.getOrder
+ }
+ );
+ },
+
+ /**
+ * Return the current order of the blocks in each of the sortable regions,
+ * in query string format.
+ */
+ getOrder: function () {
+ var order = [];
+ $('div.region').each(function () {
+ var region = $(this).parent().attr('id').replace(/-/g, '_');
+ var blocks = $(this).sortable('toArray');
+ var i;
+ for (i = 0; i < blocks.length; i++) {
+ order.push(region + '[]=' + blocks[i]);
+ }
+ });
+ order = order.join('&');
+ return order;
+ }
+};
+
+})(jQuery);
diff --git modules/dashboard/dashboard.module modules/dashboard/dashboard.module
new file mode 100644
index 0000000..16e1d34
--- /dev/null
+++ modules/dashboard/dashboard.module
@@ -0,0 +1,153 @@
+ 'Dashboard',
+ 'page callback' => 'dashboard_admin',
+ 'access arguments' => array('access toolbar'),
+ 'type' => MENU_CALLBACK,
+ );
+ $items['admin/dashboard/customize'] = array(
+ 'page callback' => 'dashboard_show_disabled',
+ 'access arguments' => array('access toolbar'),
+ 'type' => MENU_CALLBACK,
+ );
+ $items['admin/dashboard/block-content'] = array(
+ 'page callback' => 'dashboard_show_block_content',
+ 'page arguments' => array(3, 4),
+ 'access arguments' => array('access toolbar'),
+ 'type' => MENU_CALLBACK,
+ );
+ $items['admin/dashboard/update'] = array(
+ 'page callback' => 'dashboard_update',
+ 'access arguments' => array('access toolbar'),
+ 'type' => MENU_CALLBACK,
+ );
+ return $items;
+}
+
+/**
+ * Implement hook_help().
+ */
+function dashboard_help($path, $arg) {
+ switch ($path) {
+ case 'admin/dashboard':
+ return '
' . t('Drag and drop dashboard widgets to their place.') . '
';
+ }
+}
+
+/**
+ * Dashboard page callback.
+ */
+function dashboard_admin() {
+ drupal_add_js(drupal_get_path('module', 'dashboard') . '/dashboard.js');
+ drupal_add_js(array(
+ 'dashboard' => array(
+ 'customize' => url('admin/dashboard/customize'),
+ 'blockContent' => url('admin/dashboard/block-content'),
+ 'updatePath' => url('admin/dashboard/update'),
+ 'formToken' => drupal_get_token('dashboard-update'),
+ ),
+ ), array('type' => 'setting'));
+ drupal_add_library('system', 'ui.sortable');
+ drupal_add_library('system', 'ui.draggable');
+ drupal_add_library('system', 'ui.droppable');
+ return '';
+}
+
+/**
+ * Implement hook_block_list_alter().
+ *
+ * Skip rendering dashboard blocks when not on the dashboard page itself.
+ */
+function dashboard_block_list_alter(&$blocks) {
+ if ($_GET['q'] != 'admin/dashboard') {
+ foreach ($blocks as $key => $block) {
+ if (strpos($block->region, 'dashboard') === 0) {
+ unset($blocks[$key]);
+ }
+ }
+ }
+}
+
+function dashboard_show_disabled() {
+ global $theme_key;
+
+ // Theme system not initialized at this point.
+ drupal_theme_initialize();
+
+ // Blocks are not necessarily initialized either.
+ $blocks = _block_rehash();
+
+ $output = '
';
+ $output .= '
Disabled blocks
';
+
+ foreach ($blocks as $block) {
+ if ($block['theme'] == $theme_key && ($block['status'] == 0 || empty($block['region']))) {
+ $output .= '
'
+ . '
'.(!empty($block['title']) ? $block['title'] : $block['info']).'
'
+ . '
'
+ . '
';
+ }
+ }
+ $output .= '
';
+
+ print $output;
+ exit();
+
+}
+
+function dashboard_show_block_content($module, $delta) {
+ $block = module_invoke($module, 'block_view', $delta);
+ // TODO: Render the content portion of the block.
+ $rendered_block = '';
+ print $rendered_block;
+ exit;
+}
+
+/**
+ * Set the new weight of each region according to the drag-and-drop order.
+ */
+function dashboard_update() {
+ drupal_theme_initialize();
+ global $theme_key;
+ // Check the form token to make sure we have a valid request.
+ if (!empty($_REQUEST['form_token']) && drupal_valid_token($_REQUEST['form_token'], 'dashboard-update')) {
+ parse_str($_REQUEST['regions'], $regions);
+ foreach ($regions as $region_name => $blocks) {
+ if ($region_name == 'disabled_blocks') {
+ $region_name = '';
+ }
+ foreach ($blocks as $weight => $block_string) {
+ // Parse the query string to determine the block's module and delta.
+ preg_match('/block-([^-]+)-(.+)/', $block_string, $matches);
+ $block = new stdClass;
+ $block->module = $matches[1];
+ $block->delta = $matches[2];
+
+ $block->region = $region_name;
+ $block->weight = $weight;
+ $block->status = 1;
+
+ db_merge('block')
+ ->key(array(
+ 'module' => $block->module,
+ 'delta' => $block->delta,
+ 'theme' => $theme_key,
+ ))
+ ->fields(array(
+ 'status' => $block->status,
+ 'weight' => $block->weight,
+ 'region' => $block->region,
+ 'pages' => '',
+ ))
+ ->execute();
+ }
+ }
+ }
+ exit;
+}
\ No newline at end of file
diff --git modules/toolbar/toolbar.install modules/toolbar/toolbar.install
index 42dadd2..edcf485 100644
--- modules/toolbar/toolbar.install
+++ modules/toolbar/toolbar.install
@@ -27,7 +27,7 @@ function toolbar_install() {
$items = array(
'node/add' => 'Add',
'admin/content' => 'Find content',
- 'admin' => 'Dashboard',
+ 'admin/dashboard' => 'Dashboard',
);
$weight = -20;
foreach ($items as $path => $title) {
diff --git profiles/default/default.info profiles/default/default.info
index 9ebf79a..f0fecf0 100644
--- profiles/default/default.info
+++ profiles/default/default.info
@@ -6,6 +6,7 @@ core = 7.x
dependencies[] = block
dependencies[] = color
dependencies[] = comment
+dependencies[] = dashboard
dependencies[] = help
dependencies[] = image
dependencies[] = menu
diff --git themes/seven/page-admin-dashboard.tpl.php themes/seven/page-admin-dashboard.tpl.php
new file mode 100644
index 0000000..161c5fa
--- /dev/null
+++ themes/seven/page-admin-dashboard.tpl.php
@@ -0,0 +1,62 @@
+
+>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git themes/seven/seven.info themes/seven/seven.info
index da9e494..f42ec45 100644
--- themes/seven/seven.info
+++ themes/seven/seven.info
@@ -11,3 +11,7 @@ regions[content] = Content
regions[help] = Help
regions[page_top] = Page top
regions[page_bottom] = Page bottom
+regions[dashboard_thick] = Dashboard thick
+regions[dashboard_thin] = Dashboard thin
+;hidden_regions[] = dashboard_thick
+;hidden_regions[] = dashboard_thin
diff --git themes/seven/style.css themes/seven/style.css
index c402743..5e15a5e 100644
--- themes/seven/style.css
+++ themes/seven/style.css
@@ -728,3 +728,76 @@ body.overlay #page {
body.overlay #block-system-main {
padding: 20px;
}
+
+/* Dashboard */
+
+body.page-admin-dashboard div#page {
+ padding-top:20px;
+}
+
+body.page-admin-dashboard div#dashboard-thick {
+ width: 65%;
+ float: left;
+ min-height: 1px;
+ margin: 5px;
+}
+
+body.page-admin-dashboard div#dashboard-thin {
+ width: 30%;
+ float: left;
+ min-height: 1px;
+ margin: 5px;
+}
+
+body.page-admin-dashboard div.block {
+ border: 1px solid #e2e1dc;
+ margin-bottom: 20px;
+}
+
+body.page-admin-dashboard div.block h2 {
+ background-color:#e2e1dc;
+ padding: 3px 5px;
+}
+
+body.page-admin-dashboard div.block div.content {
+ padding: 10px 5px 5px 5px;
+}
+
+body.page-admin-dashboard div.block div.content ul.menu {
+ margin-left:20px;
+}
+
+body.page-admin-dashboard.one-sidebar div#content div.block {
+ margin-right:20px;
+}
+
+body.page-admin-dashboard #disabled-blocks {
+ margin: 5px;
+}
+body.page-admin-dashboard #disabled-blocks .block {
+ background: #e2e1dc;
+ padding: 4px;
+ margin: 3px;
+ display: inline;
+ -moz-border-radius: 4px;
+}
+body.page-admin-dashboard .ui-sortable {
+ border: 3px dashed #ccc;
+ padding: 10px;
+}
+body.page-admin-dashboard div.dragging {
+ width: 30% !important;
+}
+body.page-admin-dashboard #disabled-blocks h2 {
+ display: inline;
+ font-weight: normal;
+}
+body.page-admin-dashboard #disabled-blocks .block .content {
+ display: none;
+}
+body.page-admin-dashboard .ui-sortable .block {
+ cursor: move;
+}
+body.page-admin-dashboard #help {
+ display: none;
+}
\ No newline at end of file