diff options
-rw-r--r-- | data/assets/js/admin/dialogs/user-edit.js | 63 | ||||
-rw-r--r-- | data/assets/js/admin/tabs/users.js | 7 | ||||
-rw-r--r-- | src/guff.cr | 46 | ||||
-rw-r--r-- | src/views/admin-page.ecr | 87 |
4 files changed, 171 insertions, 32 deletions
diff --git a/data/assets/js/admin/dialogs/user-edit.js b/data/assets/js/admin/dialogs/user-edit.js index 2e43d42..fed9364 100644 --- a/data/assets/js/admin/dialogs/user-edit.js +++ b/data/assets/js/admin/dialogs/user-edit.js @@ -2,14 +2,40 @@ jQuery(function($) { "use strict"; $('#user-edit-dialog').on('show.bs.modal', function() { - var row = $(this).data('row'); - - $.each({ - name: 'user_name', - email: 'email', - role: 'role_name', - }, function(id, col) { - $('#user-edit-' + id).val(row[col]); + var me = $(this); + + $(this).find('.modal-body').addClass('hidden'); + $(this).find('.modal-body.loading-text').removeClass('hidden'); + + send('user/get', { + user_id: me.data('user_id'), + }).always(function() { + $(this).find('.modal-body.loading-text').addClass('hidden'); + }).fail(function(r) { + var error = r.responseText; + + try { + // try to extract error message from json response + var data = $.parseJSON(r.responseText); + if ('error' in data) + error = data.error; + } catch (e) {} + + me.find('.modal-body.loading-error').removeClass('hidden') + .find('.error-text').text(error); + }).done(function(r) { + $.each({ + name: 'name', + email: 'email', + role: 'role', + }, function(id, col) { + $('#user-edit-' + id).val(r[col]); + }); + + $('#user-edit-password').val(''); + $('#user-edit-active').val((r.is_active == '1') ? 'active' : 'inactive'); + + me.find('.modal-body.loading-done').removeClass('hidden'); }); }); @@ -34,8 +60,7 @@ jQuery(function($) { }); $('#user-edit-confirm').click(function() { - var me = $(this), - user_id = $('#user-edit-dialog').data('row').user_id; + var me = $(this); if (me.hasClass('disabled')) return false; @@ -43,18 +68,28 @@ jQuery(function($) { // toggle loading me.toggleClass('disabled').find('.loading').toggleClass('hidden'); - send('test/edit_user', { - user_id: user_id, + send('user/set', { + user_id: $('#user-edit-dialog').data('user_id'), name: $('#user-edit-name').val(), email: $('#user-edit-email').val(), + password: $('#user-edit-password').val(), role: $('#user-edit-role').val(), + active: ($('#user-edit-active').val() == 'active') ? 't' : 'f', }).always(function() { // toggle loading me.toggleClass('disabled').find('.loading').toggleClass('hidden'); }).fail(function(r) { - alert('Error ' + r.responseText); + var error = r.responseText; + + try { + // try to extract error message from json response + var data = $.parseJSON(r.responseText); + if ('error' in data) + error = data.error; + } catch (e) {} + + alert('Error: ' + error); }).done(function(r) { - console.log(r); $('#users-reload').click(); $('#user-edit-dialog').modal('hide'); }); diff --git a/data/assets/js/admin/tabs/users.js b/data/assets/js/admin/tabs/users.js index b74b8a1..2fff893 100644 --- a/data/assets/js/admin/tabs/users.js +++ b/data/assets/js/admin/tabs/users.js @@ -10,7 +10,7 @@ jQuery(function($) { "data-user_id='%{user_id|h}' ", "data-q='%{q|h}' ", ">", - "<i class='fa fa-fw fa-user'></i>", + "<i class='fa fa-fw %{icon|h}'></i>", " ", "%{name|h} (%{email|h})", @@ -89,8 +89,11 @@ jQuery(function($) { })); }).done(function(r) { list.html($.map(r, function(row) { + var active = (row.is_active == '1'); + return TEMPLATES.run('user', $.extend({}, row, { - css: (row.is_active == '1') ? '' : 'list-group-item-danger', + icon: active ? 'fa-user' : 'fa-user-times', + css: active ? '' : 'list-group-item-danger', q: [row.user_id, row.user_name, row.email, row.role_name].join(' ').toLowerCase(), badge_css: ROLE_BADGE_CSS[row.role], })); diff --git a/src/guff.cr b/src/guff.cr index 6b842f8..5524aca 100644 --- a/src/guff.cr +++ b/src/guff.cr @@ -533,7 +533,7 @@ module Guff # add search filter filters << "a.post_id IN ( SELECT rowid - FROM posts_fts + FROM posts_fts WHERE posts_fts MATCH ? )" @@ -1051,6 +1051,21 @@ module Guff ORDER BY LOWER(a.name) ", + + get: " + SELECT a.user_id, + a.name, + a.email, + a.is_active, + b.role, + b.name AS role_name + + FROM users a + JOIN roles b + ON (b.role_id = a.role_id) + + WHERE a.user_id = ? + ", } def login( @@ -1151,6 +1166,16 @@ module Guff rows end + + def get(user_id : Int64) + row = @context.dbs.ro.row(SQL[:get], [user_id.to_s]) + raise "unknown user: #{user_id}" unless row + + row.reduce({} of String => String) do |r, k, v| + r[k] = v.to_s + r + end + end end # TODO: handle session expiration @@ -1686,12 +1711,17 @@ module Guff { "user_id": user_id } end + def do_user_get(params : HTTP::Params) + @context.models.user.get(params["user_id"].to_i64) + end + + def do_user_set(params : HTTP::Params) @context.models.user.set( user_id: params["user_id"].to_i64, name: params["name"]?, email: params["email"]?, - password: params["password"]?, + password: (params["password"]? && params["password"].size > 0) ? params["password"] : nil, active: params["active"]? ? (params["active"] == "t") : nil, role: params["role"]?, ) @@ -1747,7 +1777,7 @@ module Guff def self.icon(id : String?) if id && id.size > 0 ICON_TEMPLATE % [HTML.escape(id.not_nil!)] - else + else "" end end @@ -1795,7 +1825,7 @@ module Guff String.build do |io| @items.each do |item| io << ItemView.new( - context: @context, + context: @context, active: @default == item[:id]?, item: item ).to_s @@ -1848,7 +1878,7 @@ module Guff ) Dropdown::MenuView.new( context: @context, - id: id, + id: id, name: name, text: text, icon: icon, @@ -2016,7 +2046,7 @@ module Guff private def authors_menu_items @context.models.user.get_users.map do |row| - { + { id: row["user_id"], name: row["name"], text: "Show author \"%s\"." % [row["name"]], @@ -2026,7 +2056,7 @@ module Guff private def sites_menu_items @context.models.site.get_sites.map do |row| - { + { id: row["site_id"], name: row["name"], text: "Show site \"%s\"." % [row["name"]], @@ -2036,7 +2066,7 @@ module Guff private def states_menu_items @context.models.state.get_states.map do |row| - { + { id: row["state"], name: row["name"], icon: row["icon"], diff --git a/src/views/admin-page.ecr b/src/views/admin-page.ecr index 89a75d0..f82d06c 100644 --- a/src/views/admin-page.ecr +++ b/src/views/admin-page.ecr @@ -631,7 +631,12 @@ class='form-control' title='Enter name of user.' placeholder='John Doe' + aria-describedby='user-edit-name-help' /> + + <p id='user-edit-name-help' class='help-block'> + Name of this user. + </p> </div><!-- form-group --> <div class='form-group'> @@ -645,22 +650,88 @@ class='form-control' title='Enter user email.' placeholder='johndoe@example.com' + aria-describedby='user-edit-email-help' /> + + <p id='user-edit-email-help' class='help-block'> + Email address for this user. + </p> </div><!-- form-group --> <div class='form-group'> - <label for='user-edit-role'> - Role + <label for='user-edit-password'> + Password </label> - <select - id='user-edit-role' + <input + type='password' + id='user-edit-password' class='form-control' - title='Choose role of user.' - ><%= - role_options - %></select> + title='Enter user password.' + aria-describedby='user-edit-password-help' + /> + + <p id='user-edit-password-help' class='help-block'> + Password for this user. + </p> </div><!-- form-group --> + + <div class='row'> + <div class='col-md-6'> + <div class='form-group'> + <label for='user-edit-role'> + Role + </label> + + <select + id='user-edit-role' + class='form-control' + title='Choose role of user.' + aria-describedby='user-edit-role-help' + ><%= + role_options + %></select> + + <p id='user-edit-role-help' class='help-block'> + User role. + </p> + </div><!-- form-group --> + </div><!-- col-md-6 --> + + <div class='col-md-6'> + <div class='form-group'> + <label for='user-edit-active'> + Active + </label> + + <select + id='user-edit-active' + class='form-control' + title='Choose active state of user.' + aria-describedby='user-edit-active-help' + > + <option + value='inactive' + selected='selected' + title='Inactive: user cannot log in.' + > + Inactive + </option> + + <option + value='active' + title='Active: user can log in.' + > + Active + </option> + </select> + + <p id='user-edit-active-help' class='help-block'> + Is this user active? + </p> + </div><!-- form-group --> + </div><!-- col-md-6 --> + </div><!-- row --> </div><!-- modal-body --> <div class='modal-footer'> |