aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/assets/css/admin.css4
-rw-r--r--data/assets/js/admin/dialogs/site-add.js67
-rw-r--r--data/assets/js/admin/tabs/posts.js1
-rw-r--r--data/assets/js/admin/tabs/sites.js2
-rw-r--r--src/guff/models/theme.cr15
-rw-r--r--src/guff/views/dialogs/admin/site-add.cr5
-rw-r--r--src/guff/views/dialogs/admin/site.cr21
-rw-r--r--src/guff/views/pages/admin.cr4
-rw-r--r--src/views/dialogs/admin/site-add.ecr179
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'>
+ &times;
+ </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.'
+ >
+ &times; Close
+ </button>
+ </div><!-- modal-footer -->
+ </div><!-- modal-content -->
+ </div><!-- modal-dialog -->
+</div><!-- modal -->