diff options
-rw-r--r-- | data/assets/css/admin.css | 4 | ||||
-rw-r--r-- | data/assets/js/admin/dialogs/site-add.js | 67 | ||||
-rw-r--r-- | data/assets/js/admin/tabs/posts.js | 1 | ||||
-rw-r--r-- | data/assets/js/admin/tabs/sites.js | 2 | ||||
-rw-r--r-- | src/guff/models/theme.cr | 15 | ||||
-rw-r--r-- | src/guff/views/dialogs/admin/site-add.cr | 5 | ||||
-rw-r--r-- | src/guff/views/dialogs/admin/site.cr | 21 | ||||
-rw-r--r-- | src/guff/views/pages/admin.cr | 4 | ||||
-rw-r--r-- | src/views/dialogs/admin/site-add.ecr | 179 |
9 files changed, 297 insertions, 1 deletions
diff --git a/data/assets/css/admin.css b/data/assets/css/admin.css index 60b0afd..ba65585 100644 --- a/data/assets/css/admin.css +++ b/data/assets/css/admin.css @@ -7,6 +7,10 @@ height: 20vh; } +#site-add-domains { + min-height: 100px; +} + #project-edit-releases { height: 40vh; overflow: auto; diff --git a/data/assets/js/admin/dialogs/site-add.js b/data/assets/js/admin/dialogs/site-add.js new file mode 100644 index 0000000..9a3c02f --- /dev/null +++ b/data/assets/js/admin/dialogs/site-add.js @@ -0,0 +1,67 @@ +jQuery(function($) { + "use strict"; + + var IDS = ['name', 'slug', 'body', 'lang', 'theme_id']; + var DEFAULTS = { + lang: DATA.default_lang, + theme_id: DATA.default_theme_id, + }; + + function get_domains() { + var r = $('#site-add-domains').val().replace(/^\s+|\s+$/m, ''); + return (r.length > 0) ? r.split(/\s+/m) : []; + } + + $('#site-add-dialog').on('show.bs.modal', function() { + $.each(IDS, function(_, id) { + $('#site-add-' + id).val(DEFAULTS[id] || ''); + }); + + // clear list of domains + $('#site-add-domains').val(''); + }); + + $('#site-add-dialog').on('shown.bs.modal', function() { + $('#site-add-name').focus(); + }); + + $('#site-add-dialog input[type="text"]').keydown(function(ev) { + if (ev.which == 13) { + setTimeout(function() { + $('#site-add-confirm').click(); + }, 10); + + // stop event + return false; + } + }); + + $('#site-add-confirm').click(function() { + var me = $(this); + + if (me.hasClass('disabled')) + return false; + + // toggle loading + me.toggleClass('disabled').find('.loading').toggleClass('hidden'); + + send('site/add', IDS.reduce(function(r, id) { + r[id] = $('#site-add-' + id).val(); + return r; + }, { + is_full_feed: 't', + domains: JSON.stringify(get_domains()), + })).always(function() { + // toggle loading + me.toggleClass('disabled').find('.loading').toggleClass('hidden'); + }).fail(function(r) { + gripe(r, 'add site'); + }).done(function(r) { + $('#sites-reload').click(); + $('#site-add-dialog').modal('hide'); + }); + + // stop event + return false; + }); +}); diff --git a/data/assets/js/admin/tabs/posts.js b/data/assets/js/admin/tabs/posts.js index 25f659e..38fd094 100644 --- a/data/assets/js/admin/tabs/posts.js +++ b/data/assets/js/admin/tabs/posts.js @@ -111,6 +111,7 @@ jQuery(function($) { send('post/get_posts', { type: $('#posts-filter-type li.active a').data('id'), state: $('#posts-filter-state li.active a').data('id'), + site_id: $('#posts-filter-site li.active a').data('id'), user_id: $('#posts-filter-user li.active a').data('id'), q: $('#posts-q').data('q'), page: 1, diff --git a/data/assets/js/admin/tabs/sites.js b/data/assets/js/admin/tabs/sites.js index 9ef9564..8644705 100644 --- a/data/assets/js/admin/tabs/sites.js +++ b/data/assets/js/admin/tabs/sites.js @@ -85,7 +85,7 @@ jQuery(function($) { return TEMPLATES.run('site', $.extend({}, row, { q: [row.site_id, row.slug, row.name, row.body].join(' ').toLowerCase(), - badge_css: row.is_default ? '' : 'hidden', + badge_css: +row.is_default ? '' : 'hidden', })); }).join('')); diff --git a/src/guff/models/theme.cr b/src/guff/models/theme.cr index 5b24a71..2e8730b 100644 --- a/src/guff/models/theme.cr +++ b/src/guff/models/theme.cr @@ -40,6 +40,17 @@ class Guff::Models::ThemeModel < Guff::Models::Model WHERE %s ", + get_default_id: " + SELECT theme_id + + FROM themes + + WHERE is_system + AND theme_slug = 'default' + + LIMIT 1 + ", + get_data: " SELECT a.data_key, a.data_val @@ -247,6 +258,10 @@ class Guff::Models::ThemeModel < Guff::Models::Model @context.dbs.ro.row(SQL[:get] % sql.join(" AND "), args).not_nil! end + def get_default_id : Int64 + @context.dbs.ro.one(SQL[:get_default_id]).not_nil!.to_i64 + end + def templates(theme_id : Int32) unless @cache[:templates].includes?(theme_id) # get theme diff --git a/src/guff/views/dialogs/admin/site-add.cr b/src/guff/views/dialogs/admin/site-add.cr new file mode 100644 index 0000000..894a34a --- /dev/null +++ b/src/guff/views/dialogs/admin/site-add.cr @@ -0,0 +1,5 @@ +require "./site" + +class Guff::Views::Dialogs::Admin::SiteAdd < Guff::Views::Dialogs::Admin::Site + ECR.def_to_s("src/views/dialogs/admin/site-add.ecr") +end diff --git a/src/guff/views/dialogs/admin/site.cr b/src/guff/views/dialogs/admin/site.cr new file mode 100644 index 0000000..1b6419b --- /dev/null +++ b/src/guff/views/dialogs/admin/site.cr @@ -0,0 +1,21 @@ +class Guff::Views::Dialogs::Admin::Site < Guff::Views::HTMLView + TEMPLATES = { + y: "<option value='%s' data-slug='%s' selected='selected'>%s</option>", + n: "<option value='%s' data-slug='%s'>%s</option>", + } + + private def theme_options + @context.models.theme.all.map { |row| + { + id: row["theme_id"], + slug: row["theme_slug"], + name: "%s (%s)" % %w{name version}.map { |k| + row["theme_#{k}"] + }, + } + }.map { |row| + tmpl_id = (row[:slug] == "default") ? :y : :n + TEMPLATES[tmpl_id] % %i{id slug name}.map { |k| row[k] } + }.join("") + end +end diff --git a/src/guff/views/pages/admin.cr b/src/guff/views/pages/admin.cr index 688e715..1c5f795 100644 --- a/src/guff/views/pages/admin.cr +++ b/src/guff/views/pages/admin.cr @@ -28,6 +28,7 @@ class Guff::Views::Pages::Admin < Guff::Views::HTMLView assets/js/admin/tabs/themes.js assets/js/admin/dialogs/user-add.js assets/js/admin/dialogs/user-edit.js + assets/js/admin/dialogs/site-add.js assets/js/admin/dialogs/post-edit.js assets/js/admin/dialogs/blog-edit.js assets/js/admin/dialogs/page-edit.js @@ -95,6 +96,7 @@ class Guff::Views::Pages::Admin < Guff::Views::HTMLView String.build do |io| io << Dialogs::Admin::UserAdd.new(@context) io << Dialogs::Admin::UserEdit.new(@context) + io << Dialogs::Admin::SiteAdd.new(@context) io << Dialogs::Admin::BlogEdit.new(@context) io << Dialogs::Admin::PageEdit.new(@context) io << Dialogs::Admin::ProjectEdit.new(@context) @@ -106,6 +108,8 @@ class Guff::Views::Pages::Admin < Guff::Views::HTMLView post_types: POST_TYPES, sites: @context.models.site.get_sites, default_site_id: @context.models.site.get_default_id, + default_lang: "en-US", + default_theme_id: @context.models.theme.get_default_id, }.to_json end diff --git a/src/views/dialogs/admin/site-add.ecr b/src/views/dialogs/admin/site-add.ecr new file mode 100644 index 0000000..aae2f70 --- /dev/null +++ b/src/views/dialogs/admin/site-add.ecr @@ -0,0 +1,179 @@ +<div id='site-add-dialog' class='modal fade' role='dialog'> + <div class='modal-dialog' role='document'> + <div class='modal-content'> + <div class='modal-header'> + <button + type='button' + class='close' + data-dismiss='modal' + aria-label='Close' + > + <span aria-hidden='true'> + × + </span> + </button><!-- close --> + + <h4 class='modal-title'> + <i class='fa fa-plus-circle'></i> + New Site + </h4><!-- modal-title --> + </div><!-- modal-header --> + + <div class='modal-body'> + <div class='row'> + <div class='col-md-6'> + <div class='form-group'> + <label for='site-add-name'> + Name + </label> + + <input + type='text' + id='site-add-name' + class='form-control' + title='Enter site name.' + placeholder='Some Site' + aria-describedby='site-add-name-help' + /> + + <p id='site-add-name-help' class='help-block'> + Site name. + </p> + </div><!-- form-group --> + </div><!-- col-md-6 --> + + <div class='col-md-6'> + <div class='form-group'> + <label for='site-add-slug'> + Slug + </label> + + <input + type='text' + id='site-add-slug' + class='form-control' + title='Enter site slug (lowercase).' + placeholder='some-site' + aria-describedby='site-add-slug-help' + /> + + <p id='site-add-slug-help' class='help-block'> + Name of server files directory. + </p> + </div><!-- form-group --> + </div><!-- col-md-6 --> + </div><!-- row --> + + <div class='form-group'> + <label for='site-add-body'> + Description + </label> + + <textarea + id='site-add-body' + class='form-control' + title='Enter site description.' + placeholder='A brief site description' + aria-describedby='site-add-body-help' + /></textarea> + + <p id='site-add-body-help' class='help-block'> + Brief description of site. + </p> + </div><!-- form-group --> + + <div class='row'> + <div class='col-md-6'> + <div class='form-group'> + <label for='site-add-theme_id'> + Theme + </label> + + <select + id='site-add-theme_id' + class='form-control' + title='Choose site theme.' + aria-describedby='site-add-theme-help' + ><%= + theme_options + %></select> + + <p id='site-add-theme-help' class='help-block'> + Site theme. + </p> + </div><!-- form-group --> + </div><!-- col-md-6 --> + + <div class='col-md-6'> + <div class='form-group'> + <label for='site-add-lang'> + Language + </label> + + <input + type='text' + id='site-add-lang' + class='form-control' + title='Enter site IETF language tag (BCP 47).' + aria-describedby='site-add-lang-help' + /> + + <p id='site-add-lang-help' class='help-block'> + <a + href='https://en.wikipedia.org/wiki/IETF_language_tag' + title='View IETF language tag information.' + rel='noopener nofollow' + target='_blank' + >IETF BCP 47 language tag</a> for site. + </p> + </div><!-- form-group --> + </div><!-- col-md-6 --> + </div><!-- row --> + + <div class='form-group'> + <label for='site-add-domains'> + Domains + </label> + + <textarea + id='site-add-domains' + class='form-control' + title='Newline-delimited list of site domains.' + placeholder='some.example.com' + aria-describedby='site-add-domains-help' + /></textarea> + + <p id='site-add-domains-help' class='help-block'> + Newline-deilmited list of site domains. + </p> + </div><!-- form-group --> + </div><!-- modal-body --> + + <div class='modal-footer'> + <button + id='site-add-confirm' + class='btn btn-primary' + title='Create site.' + > + <span class='hidden loading'> + <i class='fa fa-spinner fa-spin'></i> + Please Wait... + </span> + + <span class='loading'> + <i class='fa fa-plus-circle'></i> + Create Site + </span> + </button> + + <button + class='btn btn-default' + data-dismiss='modal' + title='Close dialog.' + > + × Close + </button> + </div><!-- modal-footer --> + </div><!-- modal-content --> + </div><!-- modal-dialog --> +</div><!-- modal --> |