diff options
author | Petr Vobornik <pvoborni@redhat.com> | 2012-08-27 10:57:47 +0200 |
---|---|---|
committer | Petr Vobornik <pvoborni@redhat.com> | 2012-08-29 12:00:06 +0200 |
commit | 81007ff38578588906737df3082b42fb7f2ee011 (patch) | |
tree | 367340e56e48f2288671eccc647c52405838b1b4 | |
parent | 7d3aa96103b03ef50ec1f6d94e2f578d800163fc (diff) | |
download | freeipa.git-81007ff38578588906737df3082b42fb7f2ee011.tar.gz freeipa.git-81007ff38578588906737df3082b42fb7f2ee011.tar.xz freeipa.git-81007ff38578588906737df3082b42fb7f2ee011.zip |
Successful action notification
User was not notified about success of actions executed from action list, action panel or facet cotrol bar.
This patch adds IPA.notify_success(message) call. It creates a yellow notification area with supplied message in Web UI header in the middle of the green area (empty space of first level navigation).
This area is displayed for 3s and then it fades out (800ms). It also fades out when it is clicked.
This call is used(directly or indirectly) in:
* search facets: delete, disable, enable actions
* details facets: delete action
* user details facet: reset password action
* host details facet: unprovision, set OTP actions
* service details facet: unprovision action
* host and service details facet: request, revoke, restore certificates actions
* group details facet: change to POSIX/external actions
* dns zone details facet: add/remove permission actions
https://fedorahosted.org/freeipa/ticket/2977
-rwxr-xr-x | install/ui/certificate.js | 3 | ||||
-rw-r--r-- | install/ui/details.js | 4 | ||||
-rw-r--r-- | install/ui/dns.js | 22 | ||||
-rw-r--r-- | install/ui/hbac.js | 16 | ||||
-rw-r--r-- | install/ui/host.js | 2 | ||||
-rw-r--r-- | install/ui/ipa.css | 15 | ||||
-rw-r--r-- | install/ui/ipa.js | 35 | ||||
-rw-r--r-- | install/ui/search.js | 44 | ||||
-rw-r--r-- | install/ui/selinux.js | 16 | ||||
-rw-r--r-- | install/ui/serverconfig.js | 6 | ||||
-rw-r--r-- | install/ui/service.js | 1 | ||||
-rw-r--r-- | install/ui/sudo.js | 16 | ||||
-rw-r--r-- | install/ui/test/data/ipa_init.json | 10 | ||||
-rw-r--r-- | install/ui/user.js | 18 | ||||
-rw-r--r-- | ipalib/plugins/internal.py | 8 |
15 files changed, 135 insertions, 81 deletions
diff --git a/install/ui/certificate.js b/install/ui/certificate.js index e94c81a0..6a6509e7 100755 --- a/install/ui/certificate.js +++ b/install/ui/certificate.js @@ -696,6 +696,7 @@ IPA.cert.request_action = function(spec) { }, on_success: function(data, text_status, xhr) { facet.refresh(); + IPA.notify_success(IPA.messages.objects.cert.requested); } }).execute(); } @@ -746,6 +747,7 @@ IPA.cert.revoke_action = function(spec) { }, on_success: function(data, text_status, xhr) { facet.refresh(); + IPA.notify_success(IPA.messages.objects.cert.revoked); } }).execute(); } @@ -792,6 +794,7 @@ IPA.cert.restore_action = function(spec) { args: [certificate.serial_number], on_success: function(data, text_status, xhr) { facet.refresh(); + IPA.notify_success(IPA.messages.objects.cert.restored); } }).execute(); } diff --git a/install/ui/details.js b/install/ui/details.js index 0530592d..883bb06b 100644 --- a/install/ui/details.js +++ b/install/ui/details.js @@ -1123,6 +1123,8 @@ IPA.object_action = function(spec) { }; that.on_success = function(facet, data, text_status, xhr) { + + IPA.notify_success(data.result.summary); facet.on_update.notify(); }; @@ -1190,6 +1192,8 @@ IPA.delete_action = function(spec) { var that = IPA.object_action(spec); that.on_success = function(facet, data, text_status, xhr) { + + IPA.notify_success(data.result.summary); facet.on_update.notify(); facet.redirect(); }; diff --git a/install/ui/dns.js b/install/ui/dns.js index cd8cb8e1..0803fdd3 100644 --- a/install/ui/dns.js +++ b/install/ui/dns.js @@ -113,20 +113,8 @@ IPA.dns.zone_entity = function(spec) { } ], actions: [ - { - name: 'disable', - factory: IPA.batch_items_action, - method: 'disable', - needs_confirm: true, - enable_cond: ['item-selected'] - }, - { - name: 'enable', - factory: IPA.batch_items_action, - method: 'enable', - needs_confirm: true, - enable_cond: ['item-selected'] - } + IPA.batch_disable_action, + IPA.batch_enable_action ], control_buttons: [ { @@ -616,8 +604,9 @@ IPA.dns.add_permission_action = function(spec) { method: 'add_permission', args: [pkey], options: {}, - on_success: function() { + on_success: function(data, text_status, xhr) { facet.refresh(); + IPA.notify_success(data.result.summary); } }); @@ -645,8 +634,9 @@ IPA.dns.remove_permission_action = function(spec) { method: 'remove_permission', args: [pkey], options: {}, - on_success: function() { + on_success: function(data, text_status, xhr) { facet.refresh(); + IPA.notify_success(data.result.summary); } }); diff --git a/install/ui/hbac.js b/install/ui/hbac.js index cb324942..a3683e7b 100644 --- a/install/ui/hbac.js +++ b/install/ui/hbac.js @@ -48,20 +48,8 @@ IPA.hbac.rule_entity = function(spec) { 'description' ], actions: [ - { - name: 'disable', - factory: IPA.batch_items_action, - method: 'disable', - needs_confirm: true, - enable_cond: ['item-selected'] - }, - { - name: 'enable', - factory: IPA.batch_items_action, - method: 'enable', - needs_confirm: true, - enable_cond: ['item-selected'] - } + IPA.batch_disable_action, + IPA.batch_enable_action ], control_buttons: [ { diff --git a/install/ui/host.js b/install/ui/host.js index cea2019b..a2b91b6b 100644 --- a/install/ui/host.js +++ b/install/ui/host.js @@ -622,6 +622,7 @@ IPA.host_unprovision_dialog = function(spec) { function(data, text_status, xhr) { that.facet.refresh(); that.close(); + IPA.notify_success(IPA.messages.objects.host.unprovisioned); }, function(xhr, text_status, error_thrown) { that.close(); @@ -853,6 +854,7 @@ IPA.host.set_otp_dialog = function(spec) { on_success: function(data) { that.facet.load(data); that.close(); + IPA.notify_success(IPA.messages.objects.host.password_set_success); }, on_error: function() { that.close(); diff --git a/install/ui/ipa.css b/install/ui/ipa.css index ddbe71c1..c8a220e7 100644 --- a/install/ui/ipa.css +++ b/install/ui/ipa.css @@ -263,6 +263,21 @@ body { font-weight: bold; } +/* ---- Notification area ---- */ + +.notification-area { + position: absolute; + top: 40px; + left: 380px; + right: 380px; + line-height: 1.5em; + z-index: 20; + padding: 4px; + + font-weight: bold; + text-align: center; +} + /* ---- Navigation ---- */ #navigation { position: absolute; diff --git a/install/ui/ipa.js b/install/ui/ipa.js index 0c25863d..7df4deed 100644 --- a/install/ui/ipa.js +++ b/install/ui/ipa.js @@ -2040,6 +2040,39 @@ IPA.confirm = function(msg) { return window.confirm(msg); }; +IPA.notify_success = function(message) { + + function destroy_timeout() { + if (IPA.notify_success.timeout) window.clearTimeout(IPA.notify_success.timeout); + } + + var notification_area = $('.notification-area'); + + if (notification_area.length === 0) { + notification_area = $('<div/>', { + 'class': 'notification-area ui-corner-all ui-state-highlight', + click: function() { + destroy_timeout(); + notification_area.fadeOut(100); + } + }); + + notification_area.appendTo('#container'); + } + + notification_area.text(message); + + destroy_timeout(); + notification_area.fadeIn(IPA.config.message_fadein_time); + + IPA.notify_success.timeout = window.setTimeout(function() { + notification_area.fadeOut(IPA.config.message_fadeout_time); + }, IPA.config.message_timeout); +}; + IPA.config = { - default_priority: 500 + default_priority: 500, + message_timeout: 3000, // [ms] + message_fadeout_time: 800, // [ms] + message_fadein_time: 400 // [ms] }; diff --git a/install/ui/search.js b/install/ui/search.js index 2c30b5b7..154d7ffa 100644 --- a/install/ui/search.js +++ b/install/ui/search.js @@ -308,10 +308,11 @@ IPA.search_deleter_dialog = function(spec) { var batch = that.create_command(); - batch.on_success = function() { + batch.on_success = function(data, text_status, xhr) { that.facet.refresh(); that.facet.on_update.notify([],that.facet); that.close(); + IPA.notify_success(IPA.messages.search.deleted); }; batch.on_error = function() { @@ -414,13 +415,14 @@ IPA.batch_items_action = function(spec) { var that = IPA.action(spec); that.method = spec.method || 'disable'; + that.success_msg = spec.success_msg; - that.execute = function(facet, on_success, on_error) { + that.execute_action = function(facet, on_success, on_error) { var entity = facet.managed_entity; var pkeys = facet.get_selected_values(); - var batch = IPA.batch_command({ + that.batch = IPA.batch_command({ name: entity.name + '_batch_'+ that.method, on_success: that.get_on_success(facet, on_success) }); @@ -434,15 +436,21 @@ IPA.batch_items_action = function(spec) { args: [pkey] }); - batch.add_command(command); + that.batch.add_command(command); } - batch.execute(); + that.batch.execute(); }; that.on_success = function(facet, data, text_status, xhr) { facet.on_update.notify(); facet.refresh(); + + if (that.success_msg) { + var succeeded = that.batch.commands.length - that.batch.errors.errors.length; + var msg = that.success_msg.replace('${count}', succeeded); + IPA.notify_success(msg); + } }; that.get_on_success = function(facet, on_success) { @@ -455,3 +463,29 @@ IPA.batch_items_action = function(spec) { return that; }; + +IPA.batch_disable_action = function(spec) { + + spec = spec || {}; + + spec.name = spec.name || 'disable'; + spec.method = spec.method || 'disable'; + spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm; + spec.enable_cond = spec.enable_cond || ['item-selected']; + spec.success_msg = spec.success_msg || IPA.messages.search.disabled; + + return IPA.batch_items_action(spec); +}; + +IPA.batch_enable_action = function(spec) { + + spec = spec || {}; + + spec.name = spec.name || 'enable'; + spec.method = spec.method || 'enable'; + spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm; + spec.enable_cond = spec.enable_cond || ['item-selected']; + spec.success_msg = spec.success_msg || IPA.messages.search.enabled; + + return IPA.batch_items_action(spec); +};
\ No newline at end of file diff --git a/install/ui/selinux.js b/install/ui/selinux.js index 6c6d240c..c754fabf 100644 --- a/install/ui/selinux.js +++ b/install/ui/selinux.js @@ -47,20 +47,8 @@ IPA.selinux.selinuxusermap_entity = function(spec) { 'description' ], actions: [ - { - name: 'disable', - factory: IPA.batch_items_action, - method: 'disable', - needs_confirm: true, - enable_cond: ['item-selected'] - }, - { - name: 'enable', - factory: IPA.batch_items_action, - method: 'enable', - needs_confirm: true, - enable_cond: ['item-selected'] - } + IPA.batch_disable_action, + IPA.batch_enable_action ], control_buttons: [ { diff --git a/install/ui/serverconfig.js b/install/ui/serverconfig.js index 950b9898..517aa780 100644 --- a/install/ui/serverconfig.js +++ b/install/ui/serverconfig.js @@ -23,9 +23,9 @@ /* REQUIRES: ipa.js, details.js, search.js, add.js, facet.js, entity.js */ -IPA.config = {}; +IPA.serverconfig = {}; -IPA.config.entity = function(spec) { +IPA.serverconfig.entity = function(spec) { var that = IPA.entity(spec); @@ -115,4 +115,4 @@ IPA.config.entity = function(spec) { return that; }; -IPA.register('config', IPA.config.entity); +IPA.register('config', IPA.serverconfig.entity); diff --git a/install/ui/service.js b/install/ui/service.js index be3d9047..04e294bf 100644 --- a/install/ui/service.js +++ b/install/ui/service.js @@ -379,6 +379,7 @@ IPA.service.unprovision_dialog = function(spec) { on_success: function(data, text_status, xhr) { that.facet.refresh(); that.close(); + IPA.notify_success(IPA.messages.objects.service.unprovisioned); }, on_error: function(xhr, text_status, error_thrown) { that.close(); diff --git a/install/ui/sudo.js b/install/ui/sudo.js index 0dcf4322..d18415ff 100644 --- a/install/ui/sudo.js +++ b/install/ui/sudo.js @@ -46,20 +46,8 @@ IPA.sudo.rule_entity = function(spec) { 'description' ], actions: [ - { - name: 'disable', - factory: IPA.batch_items_action, - method: 'disable', - needs_confirm: true, - enable_cond: ['item-selected'] - }, - { - name: 'enable', - factory: IPA.batch_items_action, - method: 'enable', - needs_confirm: true, - enable_cond: ['item-selected'] - } + IPA.batch_disable_action, + IPA.batch_enable_action ], control_buttons: [ { diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json index 32ce1c1e..ff4c7489 100644 --- a/install/ui/test/data/ipa_init.json +++ b/install/ui/test/data/ipa_init.json @@ -193,8 +193,10 @@ "reason": "Reason for Revocation", "remove_from_crl": "Remove from CRL", "request_message": "<ol><li>Examples uses NSS database located in current directory. Replace \"-d .\" in example with \"-d /path/to/database\" if NSS database is located elsewhere. If you don't have a NSS database you can create one in current directory by \"certutil -N -d .\" </li><li>Create a CSR with \"CN=${hostname},O=${realm}\", for example:<br/># certutil -R -d . -a <em title=\"key size in bits\">-g 2048</em> -s 'CN=${hostname},O=${realm}'</li><li>Copy and paste the CSR (the text block which starts with \"-----BEGIN NEW CERTIFICATE REQUEST-----\" and ends with \"-----END NEW CERTIFICATE REQUEST-----\") below:</li></ol>", + "requested": "Certificate requested", "restore_certificate": "Restore Certificate for ${entity} ${primary_key}", "restore_confirmation": "To confirm your intention to restore this certificate, click the \"Restore\" button.", + "restored": "Certificate restored", "revoke_certificate": "Revoke Certificate for ${entity} ${primary_key}", "revoke_confirmation": "To confirm your intention to revoke this certificate, select a reason from the pull-down list, and click the \"Revoke\" button.", "revoked": "Certificate Revoked", @@ -323,11 +325,13 @@ "password_reset_button": "Reset OTP", "password_reset_title": "Reset One-Time-Password", "password_set_button": "Set OTP", + "password_set_success": "OTP set", "password_set_title": "Set One-Time-Password", "status": "Status", "unprovision": "Unprovision", "unprovision_confirmation": "Are you sure you want to unprovision this host?", - "unprovision_title": "Unprovisioning ${entity}" + "unprovision_title": "Unprovisioning ${entity}", + "unprovisioned": "Host unprovisioned" }, "hostgroup": { "identity": "Host Group Settings" @@ -396,6 +400,7 @@ "unprovision": "Unprovision", "unprovision_confirmation": "Are you sure you want to unprovision this service?", "unprovision_title": "Unprovisioning ${entity}", + "unprovisioned": "Service unprovisioned", "valid": "Kerberos Key Present, Service Provisioned" }, "sshkeystore": { @@ -476,6 +481,9 @@ }, "search": { "delete_confirm": "Are you sure you want to delete selected entries?", + "deleted": "Selected entries were deleted.", + "disabled": "${count} items were disabled", + "enabled": "${count} items were enabled", "partial_delete": "Some entries were not deleted", "quick_links": "Quick Links", "select_all": "Select All", diff --git a/install/ui/user.js b/install/ui/user.js index 7bb5a570..d0f1f5af 100644 --- a/install/ui/user.js +++ b/install/ui/user.js @@ -57,20 +57,12 @@ IPA.user.entity = function(spec) { ], actions: [ { - name: 'disable', - factory: IPA.batch_items_action, - method: 'disable', - needs_confirm: true, - hide_cond: ['self-service'], - enable_cond: ['item-selected'] + factory: IPA.batch_disable_action, + hide_cond: ['self-service'] }, { - name: 'enable', - factory: IPA.batch_items_action, - method: 'enable', - needs_confirm: true, - hide_cond: ['self-service'], - enable_cond: ['item-selected'] + factory: IPA.batch_enable_action, + hide_cond: ['self-service'] } ], control_buttons: [ @@ -614,7 +606,7 @@ IPA.user_password_dialog = function(spec) { if (that.success_handler) { that.success_handler.call(this, data, text_status, xhr); } else { - alert(IPA.messages.password.password_change_complete); + IPA.notify_success(IPA.messages.password.password_change_complete); that.close(); // refresh password expiration field diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py index 88402fb5..890ebb45 100644 --- a/ipalib/plugins/internal.py +++ b/ipalib/plugins/internal.py @@ -329,8 +329,10 @@ class i18n_messages(Command): "reason": _("Reason for Revocation"), "remove_from_crl": _("Remove from CRL"), "request_message": _("<ol><li>Examples uses NSS database located in current directory. Replace \"-d .\" in example with \"-d /path/to/database\" if NSS database is located elsewhere. If you don't have a NSS database you can create one in current directory by \"certutil -N -d .\" </li><li>Create a CSR with \"CN=${hostname},O=${realm}\", for example:<br/># certutil -R -d . -a <em title=\"key size in bits\">-g 2048</em> -s 'CN=${hostname},O=${realm}'</li><li>Copy and paste the CSR (the text block which starts with \"-----BEGIN NEW CERTIFICATE REQUEST-----\" and ends with \"-----END NEW CERTIFICATE REQUEST-----\") below:</li></ol>"), + "requested": _("Certificate requested"), "restore_certificate": _("Restore Certificate for ${entity} ${primary_key}"), "restore_confirmation": _("To confirm your intention to restore this certificate, click the \"Restore\" button."), + "restored": _("Certificate restored"), "revoke_certificate": _("Revoke Certificate for ${entity} ${primary_key}"), "revoke_confirmation": _("To confirm your intention to revoke this certificate, select a reason from the pull-down list, and click the \"Revoke\" button."), "revoked": _("Certificate Revoked"), @@ -461,11 +463,13 @@ class i18n_messages(Command): "password_reset_button": _("Reset OTP"), "password_reset_title": _("Reset One-Time-Password"), "password_set_button": _("Set OTP"), + "password_set_success": _("OTP set"), "password_set_title": _("Set One-Time-Password"), "status": _("Status"), "unprovision": _("Unprovision"), "unprovision_confirmation": _("Are you sure you want to unprovision this host?"), "unprovision_title": _("Unprovisioning ${entity}"), + "unprovisioned": _("Host unprovisioned"), }, "hostgroup": { "identity": _("Host Group Settings"), @@ -535,6 +539,7 @@ class i18n_messages(Command): "unprovision": _("Unprovision"), "unprovision_confirmation": _("Are you sure you want to unprovision this service?"), "unprovision_title": _("Unprovisioning ${entity}"), + "unprovisioned": _("Service unprovisioned"), "valid": _("Kerberos Key Present, Service Provisioned"), }, "sshkeystore": { @@ -615,6 +620,9 @@ class i18n_messages(Command): }, "search": { "delete_confirm": _("Are you sure you want to delete selected entries?"), + "deleted": _("Selected entries were deleted."), + "disabled": _("${count} items were disabled"), + "enabled": _("${count} items were enabled"), "partial_delete": _("Some entries were not deleted"), "quick_links": _("Quick Links"), "select_all": _("Select All"), |