diff options
author | Paul Duncan <pabs@pablotron.org> | 2016-08-20 14:22:44 -0400 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2016-08-20 14:22:44 -0400 |
commit | 4e065e6279e6e65344a2c5c0e9de5cd9d7ecfa13 (patch) | |
tree | 0cb32cf502546e6b9ab31b97e21a4916a87d5069 | |
parent | 743624c5c265d38df76deef2abdcbf8aef38336f (diff) | |
download | guff-4e065e6279e6e65344a2c5c0e9de5cd9d7ecfa13.tar.bz2 guff-4e065e6279e6e65344a2c5c0e9de5cd9d7ecfa13.zip |
-rw-r--r-- | data/assets/js/admin/tabs/home.js | 143 | ||||
-rw-r--r-- | src/guff/views/panel.cr | 72 | ||||
-rw-r--r-- | src/guff/views/panes/admin/home.cr | 71 |
3 files changed, 277 insertions, 9 deletions
diff --git a/data/assets/js/admin/tabs/home.js b/data/assets/js/admin/tabs/home.js new file mode 100644 index 0000000..b0f6eaf --- /dev/null +++ b/data/assets/js/admin/tabs/home.js @@ -0,0 +1,143 @@ +jQuery(function($) { + "use strict"; + + var TEMPLATES = new LuigiTemplate.Cache({ + panel: [DATA.panel_template], + }); + + function set_panel_editing(editing) { + // update panel headers + $('#home .home-editing').toggleClass('hidden', !editing); + $('#home .home-not-editing').toggleClass('hidden', editing); + + // flag panels as draggable + $('#home .panel').attr('draggable', editing); + } + + $('#admin-tab-home').on('show.bs.tab', function() { + // console.log('asdf'); + }); + + $('#home-edit-toggle').click(function() { + $(this).toggleClass('btn-default btn-primary'); + var editing = $(this).hasClass('btn-primary'), + panel = $(this).parents('.panel-heading'); + + // update buttons + panel.find('.btn-group.home-editing').toggleClass('hidden', !editing); + panel.find('.btn-group.home-not-editing').toggleClass('hidden', editing); + + set_panel_editing(editing); + + // stop event + return false; + }); + + $('#home-add').on('click', 'a', function() { + var data = $(this).data(); + + // hide dropdown + $('body').trigger('click'); + + // prepend new panel to first column + $('#home .home-col:first').prepend(TEMPLATES.run('panel', { + id: $.now(), + panel_class: 'panel-default', + config: '{}', + type: 'test', + name: data.name, + body: '<p>Sample body.</p>', + })); + + // flag panels as editable + set_panel_editing(true); + + // stop event + return false; + }); + + // cache column classes + var COL_CLASSES = $.map($('#home-cols a'), function(el) { + return $(el).data('col'); + }).join(' '); + + $('#home-cols').on('click', 'a', function() { + var data = $(this).data(), + ul = $(this).parents('.dropdown-menu'); + + // hide dropdown + $('body').trigger('click'); + + // update ui + ul.find('.active').removeClass('active'); + $(this).parent('li').addClass('active'); + ul.prev('a').find('span').text(data.name); + + var src_cols = $('#home .row .home-col'), + dst_num_cols = +data.id, + update_css = false; + + if (dst_num_cols > src_cols.length) { + for (var i = 0, l = dst_num_cols - src_cols.length; i < l; i++) + $('#home .row').append("<div class='home-col'></div>"); + + update_css = true; + } else if (dst_num_cols < src_cols.length) { + for (var i = 0, l = src_cols.length - dst_num_cols; i < l; i++) { + // append panels from deleted columns to last valid column + $.each($(src_cols[dst_num_cols + i]).find('.panel'), function(i, el) { + $(src_cols[dst_num_cols - 1]).append(el); + }); + + // remove old columns + $(src_cols.slice(dst_num_cols, src_cols.length)).remove(); + } + + update_css = true; + } else { + // do nothing, column count is fine + update_css = false; + } + + // update column classes, if necessary + if (update_css) + $('#home .row .home-col').removeClass(COL_CLASSES).addClass(data.col); + + // stop event + return false; + }); + + $('#home').on('dragstart', '.panel[draggable="true"]', function(ev) { + var oe = ev.originalEvent; + oe.dataTransfer.setData('text', oe.target.id); + + $('#home').addClass('dragging'); + }).on('dragend', '.panel[draggable="true"]', function(ev) { + $('#home').removeClass('dragging'); + }).on('dragover', '.home-col', function(ev) { + ev.preventDefault(); + }).on('drop', '.home-col', function(ev) { + ev.preventDefault(); + + var id = ev.originalEvent.dataTransfer.getData('text'); + $(this).append(document.getElementById(id)); + }).on('click', '.home-panel-edit a', function() { + var id = $(this).data('id'); + + // hide dropdown + $('body').trigger('click'); + + if (id == 'remove') { + if (confirm("Remove this panel?")) { + $($(this).parents('.panel')[0]).remove(); + } + } else if (id == 'edit') { + alert('TODO: ' + id + ' panel'); + } else { + // ignore unknown menu type + } + + // stop event + return false; + }); +}); diff --git a/src/guff/views/panel.cr b/src/guff/views/panel.cr new file mode 100644 index 0000000..025cc13 --- /dev/null +++ b/src/guff/views/panel.cr @@ -0,0 +1,72 @@ +module Guff::Views::Panel + TEMPLATE = Template.new(%{ + <div + id='home-panel-%{id|h}' + class='panel %{panel_class|h}' + data-type='%{type|h}' + data-config='%{config|h}' + > + <div class='panel-heading dropup'> + <a + href='#' + class='btn btn-default btn-xs home-editing hidden' + title='Edit panel.' + data-toggle='dropdown' + > + <i class='fa fa-cog'></i> + <i class='fa fa-caret-down'></i> + </a> + + <ul class='dropdown-menu home-panel-edit'> + <li role='presentation'> + <a + href='#' + title='Configure this panel.' + data-id='edit' + > + <i class='fa fa-list-alt'></i> + Configure... + </a> + </li> + + <li role='presentation'> + <a + href='#' + title='Remove this panel.' + data-id='remove' + > + <i class='fa fa-trash'></i> + Remove + </a> + </li> + </ul> + + <b> + %{name|h} + </b> + </div><!-- panel-heading --> + + <div class='panel-body'> + %{body} + </div><!-- panel-body --> + </div> + }.strip) + + def self.make( + type : String, + id : String, + name : String, + body : String = "", + config : Hash(String, String) = {} of String => String, + panel_class : String = "panel-default", + ) + TEMPLATE.run({ + "type" => type, + "id" => id, + "name" => name, + "body" => body, + "config" => config.to_json, + "panel_class" => panel_class, + }) + end +end diff --git a/src/guff/views/panes/admin/home.cr b/src/guff/views/panes/admin/home.cr index 6010fd4..00bffed 100644 --- a/src/guff/views/panes/admin/home.cr +++ b/src/guff/views/panes/admin/home.cr @@ -28,20 +28,73 @@ class Guff::Views::Panes::Admin::Home < Guff::Views::Panes::Admin::Pane </a> </li> }.strip, + + "add-menu-category" => %{ + <li class='dropdown-header'> + %{name|h} + </li> + }.strip, + + "divider" => %{ + <li class='divider' role='separator'></li> + }.strip, }) - ADD_MENU_ITEMS = [{ - "id" => "test-1", - "name" => "Test 1", + ADD_MENU = [{ + "type" => "label", + "name" => "Content", + }, { + "id" => "pages", + "name" => "Pages", + }, { + "id" => "projects", + "name" => "Projects", + }, { + "id" => "quick-post", + "name" => "Quick Post", + }, { + "id" => "releases", + "name" => "Releases", + }, { + "type" => "divider", }, { - "id" => "test-2", - "name" => "Test 2", - }].map { |row| - TEMPLATES["add-menu-item"].run(row) - }.join + "type" => "label", + "name" => "Logs", + }, { + "id" => "activity", + "name" => "Activity", + }, { + "id" => "logins", + "name" => "Logins", + }, { + "id" => "traffic", + "name" => "Traffic", + }, { + "type" => "divider", + }, { + "type" => "label", + "name" => "Other", + }, { + "id" => "image-viewer", + "name" => "Image Viewer", + }, { + "id" => "tutorial", + "name" => "Tutorial", + }] private def add_menu - ADD_MENU_ITEMS + ADD_MENU.map { |row| + key = case row["type"]? + when "divider" + "divider" + when "label" + "add-menu-category" + else + "add-menu-item" + end + + TEMPLATES[key].run(row) + }.join end private def cols_menu |