diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3fa3d5e..1d70ea6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,6 +15,18 @@ class ApplicationController < ActionController::Base devise_parameter_sanitizer.permit(:account_update, keys: [:notifications_enabled, :locale]) end + def after_sign_in_path_for(_resource) + checks_path + end + + def after_sign_up_path_for(_resource) + checks_path + end + + def after_sign_out_path_for(_resource) + root_path + end + def user_not_authorized flash[:alert] = I18n.t("user_not_authorized", scope: :flashes) redirect_to(request.referrer || root_path) diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb index 3913cd7..9449b56 100644 --- a/app/controllers/checks_controller.rb +++ b/app/controllers/checks_controller.rb @@ -1,7 +1,7 @@ # Copyright (C) 2018 Colin Darie , 2018 Jeremy Lecour , 2018 Evolix # License: GNU AGPL-3+ (see full text in LICENSE file) -class ChecksController < ApplicationController +class ChecksController < ApplicationController # rubocop:disable Metrics/ClassLength before_action :authenticate_user! before_action :set_check, except: [:index, :new, :create, :supports] after_action :verify_authorized, except: :index @@ -29,16 +29,17 @@ class ChecksController < ApplicationController build_empty_notification end - def create - @check = Check.new(new_check_params) - @check.user = current_user + def create # rubocop:disable Metrics/AbcSize + @check = Check.new(new_check_params.merge(user: current_user)) authorize @check if @check.save - flash[:notice] = t(".saved") + flash[:notice] = t("checks.created", scope: :flashes) redirect_to checks_path else - flash.now[:alert] = t(".invalid") + flash.now[:alert] = t("checks.invalid", scope: :flashes) + + fill_or_build_new_notification render :new end end @@ -49,11 +50,12 @@ class ChecksController < ApplicationController def update if @check.update(update_check_params) - flash[:notice] = "Your check has been updated." + flash[:notice] = t("checks.updated", scope: :flashes) redirect_to checks_path else - flash.now[:alert] = "An error occured." - build_empty_notification + flash.now[:alert] = t("checks.invalid", scope: :flashes) + + fill_or_build_new_notification render :edit end end @@ -61,7 +63,7 @@ class ChecksController < ApplicationController def destroy @check.destroy! - flash[:notice] = "Your check has been destroyed." + flash[:notice] = t("checks.destroyed", scope: :flashes) redirect_to checks_path end @@ -86,13 +88,39 @@ class ChecksController < ApplicationController end def check_params(*others) - params.require(:check) - .permit(:domain, :domain_expires_at, :comment, :vendor, :round_robin, *others, - notifications_attributes: [:id, :channel, :recipient, :interval]) + permitted = params.require(:check) + .permit(:domain, :domain_expires_at, :comment, :vendor, + :round_robin, *others, + notification_ids: [], + notifications_attributes: [:channel, :label, :recipient, :interval]) + + merge_current_user!(permitted) + + permitted + end + + def merge_current_user!(permitted) + return unless permitted[:notifications_attributes].present? + + permitted[:notifications_attributes].each_pair do |_key, attributes| + attributes.merge!(user: current_user) + end end def build_empty_notification - @check.notifications.build + @new_notification = @check.notifications.build + @new_notification.recipient = current_user.email + end + + def fill_or_build_new_notification + last_notification = @check.notifications.last + + # user has filled a new notification: we use it for the form + if last_notification.new_record? + @new_notification = last_notification + else # otherwise, set a new empty notification + build_empty_notification + end end def current_sort diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 8fc3103..25aaa38 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -3,45 +3,61 @@ class NotificationsController < ApplicationController before_action :authenticate_user! - before_action :set_notification, except: [:create] + before_action :set_notification, except: [:index, :new, :create] + after_action :verify_authorized, except: :index + after_action :verify_policy_scoped, only: :index + + def index + @notifications = policy_scope(Notification).order(checks_count: :desc) + end + + def new + @notification = Notification.new + authorize @notification + @notification.recipient = current_user.email + end def create - check = Check.find(params[:check_id]) - @notification = check.notifications.build(notification_params) + @notification = Notification.new(notification_params) + @notification.user = current_user authorize @notification if @notification.save - flash[:notice] = "Your notification has been saved." - redirect_to check_path + flash[:notice] = t("notifications.created", scope: :flashes) + redirect_to notifications_path else - flash.now[:alert] = "An error occured." - render "checks/edit" + flash.now[:alert] = t("notifications.invalid", scope: :flashes) + render :new + end + end + + def edit; end + + def update + if @notification.update(notification_params) + flash[:notice] = t("notifications.updated", scope: :flashes) + redirect_to notifications_path + else + flash.now[:alert] = t("notifications.error", scope: :flashes) + render :edit end end def destroy @notification.destroy! - respond_to do |format| - format.js - end + flash[:notice] = t("notifications.destroyed", scope: :flashes) + redirect_to notifications_path end private def set_notification - # joins the check because policy use the check relation - @notification = Notification - .joins(:check) - .find_by!(id: params[:id], check_id: params[:check_id]) + @notification = Notification.find(params[:id]) authorize @notification end def notification_params - params.require(:notification).permit(:channel, :recipient, :interval) - end - - def check_path - edit_check_path(check_id: params[:check_id]) + params.require(:notification).permit(:label, :recipient, :interval) end end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index d0c1067..8c5d170 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -2,5 +2,7 @@ # License: GNU AGPL-3+ (see full text in LICENSE file) class PagesController < ApplicationController - def home; end + def home + redirect_to checks_path if user_signed_in? + end end diff --git a/app/frontend/scss/components/callouts.scss b/app/frontend/scss/components/callouts.scss new file mode 100644 index 0000000..75f4bb4 --- /dev/null +++ b/app/frontend/scss/components/callouts.scss @@ -0,0 +1,51 @@ +// Taken from Bootstrap 4 documentation + +.bd-callout { + padding: 1.25rem; + margin-top: 1.25rem; + margin-bottom: 1.25rem; + border: 1px solid #eee; + border-left-width: .25rem; + border-radius: .25rem +} + +.bd-callout h4 { + margin-top: 0; + margin-bottom: .25rem +} + +.bd-callout p:last-child { + margin-bottom: 0 +} + +.bd-callout code { + border-radius: .25rem +} + +.bd-callout+.bd-callout { + margin-top: -.25rem +} + +.bd-callout-info { + border-left-color: #5bc0de +} + +.bd-callout-info h4 { + color: #5bc0de +} + +.bd-callout-warning { + border-left-color: #f0ad4e +} + +.bd-callout-warning h4 { + color: #f0ad4e +} + +.bd-callout-danger { + border-left-color: #d9534f +} + +.bd-callout-danger h4 { + color: #d9534f +} diff --git a/app/frontend/scss/components/notifications.scss b/app/frontend/scss/components/notifications.scss new file mode 100644 index 0000000..aef4306 --- /dev/null +++ b/app/frontend/scss/components/notifications.scss @@ -0,0 +1,8 @@ +// Copyright (C) 2018 Colin Darie , 2018 Evolix +// License: GNU AGPL-3+ (see full text in LICENSE file) + +.notifications-table { + .action a { + color: black; + } +} diff --git a/app/frontend/scss/index.scss b/app/frontend/scss/index.scss index 2b38b06..20ea0ae 100644 --- a/app/frontend/scss/index.scss +++ b/app/frontend/scss/index.scss @@ -5,5 +5,7 @@ @import '~bootstrap/scss/bootstrap'; @import 'layout'; @import 'icons'; +@import 'components/callouts'; @import 'components/users'; @import 'components/checks'; +@import 'components/notifications'; diff --git a/app/helpers/check_notifications_helper.rb b/app/helpers/check_notifications_helper.rb new file mode 100644 index 0000000..28deb6c --- /dev/null +++ b/app/helpers/check_notifications_helper.rb @@ -0,0 +1,5 @@ +# Copyright (C) 2018 Colin Darie , 2018 Evolix +# License: GNU AGPL-3+ (see full text in LICENSE file) + +module CheckNotificationsHelper +end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 0e9b90d..73fd45a 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -1,12 +1,9 @@ -# Copyright (C) 2018 Colin Darie , 2018 Evolix -# License: GNU AGPL-3+ (see full text in LICENSE file) - module NotificationsHelper def many_channels_available? Notification.channels.many? end - def recipient_col_class - many_channels_available? ? "col-md-7" : "col-md-9" + def notification_variable_col_class + many_channels_available? ? "col-md-4" : "col-md-5" end end diff --git a/app/mailers/notifications_mailer.rb b/app/mailers/notifications_mailer.rb index b8cdc01..b57de6c 100644 --- a/app/mailers/notifications_mailer.rb +++ b/app/mailers/notifications_mailer.rb @@ -5,8 +5,9 @@ class NotificationsMailer < ApplicationMailer helper :application before_action except: :recurrent_failures do - @notification = params.fetch(:notification) - @check = @notification.check + @check_notification = params.fetch(:check_notification) + @check = @check_notification.check + @notification = @check_notification.notification end def domain_expires_soon diff --git a/app/models/check.rb b/app/models/check.rb index 292283f..bd76fe7 100644 --- a/app/models/check.rb +++ b/app/models/check.rb @@ -34,10 +34,12 @@ class Check < ApplicationRecord belongs_to :user has_many :logs, class_name: "CheckLog", dependent: :destroy - has_many :notifications, validate: true, dependent: :destroy + has_many :check_notifications, dependent: :destroy + has_many :notifications, -> { order(checks_count: :desc) }, + through: :check_notifications, validate: true + accepts_nested_attributes_for :notifications, - allow_destroy: true, - reject_if: lambda { |at| at["recipient"].blank? && at["interval"].blank? } + reject_if: lambda { |att| att["interval"].blank? } enum kind: [:domain, :ssl] enum mode: [:auto, :manual] @@ -58,7 +60,7 @@ class Check < ApplicationRecord before_save :reset_consecutive_failures before_save :set_mode - after_update :reset_notifications + after_update :reset_check_notifications after_save :enqueue_sync scope :active, -> { where(active: true) } @@ -119,10 +121,10 @@ class Check < ApplicationRecord ResyncJob.perform_later(id) end - def reset_notifications + def reset_check_notifications return unless (saved_changes.keys & %w[domain domain_expires_at]).present? - notifications.each(&:reset!) + check_notifications.each(&:reset!) end def reset_consecutive_failures diff --git a/app/models/check_notification.rb b/app/models/check_notification.rb new file mode 100644 index 0000000..789280b --- /dev/null +++ b/app/models/check_notification.rb @@ -0,0 +1,46 @@ +# == Schema Information +# +# Table name: check_notifications +# +# id :bigint(8) not null, primary key +# sent_at :datetime +# status :integer default("pending"), not null +# created_at :datetime not null +# updated_at :datetime not null +# check_id :bigint(8) +# notification_id :bigint(8) +# +# Indexes +# +# index_check_notifications_on_check_id (check_id) +# index_check_notifications_on_notification_id (notification_id) +# +# Foreign Keys +# +# fk_rails_... (check_id => checks.id) +# fk_rails_... (notification_id => notifications.id) +# + +# Copyright (C) 2018 Colin Darie , 2018 Evolix +# License: GNU AGPL-3+ (see full text in LICENSE file) + +class CheckNotification < ApplicationRecord + belongs_to :check + belongs_to :notification, counter_cache: :checks_count + + enum status: [:pending, :ongoing, :succeed, :failed] + + scope :active_check, -> { Check.active } + scope :check_last_run_failed, -> { Check.last_run_failed } + + def pending! + self.sent_at = nil + super + end + alias reset! pending! + + def ongoing! + self.sent_at = Time.now + super + end +end diff --git a/app/models/notification.rb b/app/models/notification.rb index 860f67e..d4696c1 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,50 +1,45 @@ # Copyright (C) 2018 Colin Darie , 2018 Jeremy Lecour , 2018 Evolix # License: GNU AGPL-3+ (see full text in LICENSE file) - # == Schema Information # # Table name: notifications # -# id :bigint(8) not null, primary key -# channel :integer default("email"), not null -# interval :integer not null -# recipient :string(255) not null -# sent_at :datetime -# status :integer default("pending"), not null -# created_at :datetime not null -# updated_at :datetime not null -# check_id :bigint(8) +# id :bigint(8) not null, primary key +# channel :integer default("email"), not null +# checks_count :integer default(0), not null +# interval :integer not null +# label :string(255) +# recipient :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# check_id :bigint(8) +# user_id :bigint(8) # # Indexes # # index_notifications_on_check_id (check_id) +# index_notifications_on_user_id (user_id) # # Foreign Keys # # fk_rails_... (check_id => checks.id) +# fk_rails_... (user_id => users.id) # class Notification < ApplicationRecord - belongs_to :check + belongs_to :user + has_many :check_notifications, dependent: :destroy + has_many :checks, -> { order(domain_expires_at: :asc) }, through: :check_notifications enum channel: [:email] - enum status: [:pending, :ongoing, :succeed, :failed] validates :channel, presence: true validates :interval, numericality: { only_integer: true, greater_than_or_equal_to: 1 } validates :recipient, presence: true - scope :active_check, -> { Check.active } - scope :check_last_run_failed, -> { Check.last_run_failed } + def notifical_label + return label if label.present? - def pending! - self.sent_at = nil - super - end - alias reset! pending! - - def ongoing! - self.sent_at = Time.now - super + "#{recipient} (#{interval})" end end diff --git a/app/models/user.rb b/app/models/user.rb index 8ec2a96..ab649ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -39,7 +39,8 @@ class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :confirmable - has_many :checks + has_many :checks, dependent: :destroy + has_many :notifications, dependent: :destroy validates :tos_accepted, acceptance: true validates :locale, inclusion: { in: I18n.available_locales.map(&:to_s) } diff --git a/app/policies/check_notification_policy.rb b/app/policies/check_notification_policy.rb new file mode 100644 index 0000000..ff9837a --- /dev/null +++ b/app/policies/check_notification_policy.rb @@ -0,0 +1,24 @@ +# Copyright (C) 2018 Colin Darie , 2018 Evolix +# License: GNU AGPL-3+ (see full text in LICENSE file) + +class CheckNotificationPolicy < ApplicationPolicy + class Scope < Scope + def resolve + scope.joins(:check).where(checks: { user: user }) + end + end + + def destroy? + check_owner? + end + + def show? + false + end + + private + + def check_owner? + record.check.user == user + end +end diff --git a/app/policies/notification_policy.rb b/app/policies/notification_policy.rb index ba2a514..c541694 100644 --- a/app/policies/notification_policy.rb +++ b/app/policies/notification_policy.rb @@ -4,21 +4,25 @@ class NotificationPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.joins(:check).where(checks: { user: user }) + scope.where(user: user) end end - def destroy? - check_owner? + def create? + true end - def show? - false + def update? + owner? + end + + def destroy? + owner? end private - def check_owner? - record.check.user == user + def owner? + record.user == user end end diff --git a/app/services/notifier/channels/base.rb b/app/services/notifier/channels/base.rb index 264a318..40a5b49 100644 --- a/app/services/notifier/channels/base.rb +++ b/app/services/notifier/channels/base.rb @@ -4,26 +4,26 @@ module Notifier module Channels class Base - def notify(notification) # rubocop:disable Metrics/MethodLength - return unless supports?(notification) + def notify(check_notification) # rubocop:disable Metrics/MethodLength + return unless supports?(check_notification) - notification.ongoing! + check_notification.ongoing! - case notification.check.kind.to_sym + case check_notification.check.kind.to_sym when :domain - domain_notify_expires_soon(notification) + domain_notify_expires_soon(check_notification) when :ssl - ssl_notify_expires_soon(notification) + ssl_notify_expires_soon(check_notification) else fail ArgumentError, - "Invalid notification for check kind `#{notification.check.kind}`." + "Invalid notification for check kind `#{check_notification.check.kind}`." end end private # :nocov: - def supports?(_notification) + def supports?(_check_notification) fail NotImplementedError, "#{self.class.name} channel did not implemented method #{__callee__}" end diff --git a/app/services/notifier/channels/email.rb b/app/services/notifier/channels/email.rb index 743aa5a..1657ef8 100644 --- a/app/services/notifier/channels/email.rb +++ b/app/services/notifier/channels/email.rb @@ -11,17 +11,21 @@ module Notifier protected - def supports?(_notification) + def supports?(_check_notification) true end # Expiration notifications - def domain_notify_expires_soon(notification) - NotificationsMailer.with(notification: notification).domain_expires_soon.deliver_now + def domain_notify_expires_soon(check_notification) + NotificationsMailer.with(check_notification: check_notification) + .domain_expires_soon + .deliver_now end - def ssl_notify_expires_soon(notification) - NotificationsMailer.with(notification: notification).ssl_expires_soon.deliver_now + def ssl_notify_expires_soon(_notification) + NotificationsMailer.with(check_notification: check_notification) + .ssl_expires_soon + .deliver_now end end end diff --git a/app/services/notifier/processor.rb b/app/services/notifier/processor.rb index 502c867..de60c28 100644 --- a/app/services/notifier/processor.rb +++ b/app/services/notifier/processor.rb @@ -19,8 +19,8 @@ module Notifier end def process_expires_soon - resolver.notifications_expiring_soon.find_each do |notification| - notifier_channel_for(notification).notify(notification) + resolver.notifications_expiring_soon.find_each do |check_notification| + notifier_channel_for(check_notification.notification).notify(check_notification) sleep configuration.interval end diff --git a/app/services/notifier/resolver.rb b/app/services/notifier/resolver.rb index bc1120c..d99577f 100644 --- a/app/services/notifier/resolver.rb +++ b/app/services/notifier/resolver.rb @@ -21,8 +21,8 @@ module Notifier private def scope - Notification - .includes(:check) + CheckNotification + .includes(:check, :notification) .where(status: [:pending, :failed]) .merge(Check.active) .where.not(checks: { user: ignore_users }) diff --git a/app/views/checks/_form.html.erb b/app/views/checks/_form.html.erb index 991494f..3451f8a 100644 --- a/app/views/checks/_form.html.erb +++ b/app/views/checks/_form.html.erb @@ -41,18 +41,17 @@ <%= f.input :active %> <% end %> -

<%= t(".notifications") %>

-

<%= t(".notifications_hint") %>

+

<%= t(".notifications_hint") %>

- <%- check.notifications.each_with_index do |notification, index| %> -
- <%= f.fields_for :notifications, notification do |nf| %> - <%= render "notifications/nested_form_headers", f: nf if index.zero? %> - <%= render "notifications/nested_form", f: nf, check: check %> - <% end %> -
+ <%= f.association :notifications, as: :check_boxes, + collection: policy_scope(Notification), + label_method: :notifical_label, + label_text: false %> + + <%= f.fields_for :notifications, new_notification do |nf| %> + <%= render "notifications/nested_form_headers", f: nf %> + <%= render "notifications/nested_form", f: nf, notification: new_notification %> <% end %> - <%= f.button :submit, class: "btn-primary mt-5" %> <% end %> diff --git a/app/views/checks/_table.html.erb b/app/views/checks/_table.html.erb index cba39e9..8cb7244 100644 --- a/app/views/checks/_table.html.erb +++ b/app/views/checks/_table.html.erb @@ -7,16 +7,20 @@ <%= t(".th.domain") %> - - <%== checks_sort_links(:domain) %> - + <% unless defined?(skip_sort) %> + + <%== checks_sort_links(:domain) %> + + <% end %> <%= t(".th.expiry_date") %> <%= t(".th.expiry_date_short") %> - - <%== checks_sort_links(:domain_expires_at) %> - + <% unless defined?(skip_sort) %> + + <%== checks_sort_links(:domain_expires_at) %> + + <% end %> <%= t(".th.edit") %> @@ -48,4 +52,4 @@ -<%= paginate @checks %> +<%= paginate checks unless defined?(skip_pagination)%> diff --git a/app/views/checks/edit.html.erb b/app/views/checks/edit.html.erb index 1d5d060..fa001ac 100644 --- a/app/views/checks/edit.html.erb +++ b/app/views/checks/edit.html.erb @@ -3,16 +3,16 @@
-

Edit your check

+

<%= t(".title") %>

- <%= render "form", check: @check %> + <%= render "form", check: @check, new_notification: @new_notification %>
- <%= button_to("Delete", check_path(@check), class: "btn btn-danger", method: :delete, - data: { confirm: "Are you sure ?" }) %> + <%= button_to(t("helpers.submit.check.delete"), check_path(@check), class: "btn btn-danger", method: :delete, + data: { confirm: t(".destroy_confirmation") }) %>
diff --git a/app/views/checks/new.html.erb b/app/views/checks/new.html.erb index 1d43968..ab7fb2a 100644 --- a/app/views/checks/new.html.erb +++ b/app/views/checks/new.html.erb @@ -5,7 +5,7 @@

<%= t(".#{@check.kind}.title") %>

- <%= render "form", check: @check %> + <%= render "form", check: @check, new_notification: @new_notification %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6e1ecf0..ba72bdf 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,9 @@ <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> + + + diff --git a/app/views/notifications/_form.html.erb b/app/views/notifications/_form.html.erb new file mode 100644 index 0000000..96acdd5 --- /dev/null +++ b/app/views/notifications/_form.html.erb @@ -0,0 +1,13 @@ +<% # Copyright (C) 2018 Colin Darie , 2018 Evolix %> +<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> +<%= simple_form_for(notification) do |f| %> + <%= f.input :recipient, as: :email, + input_html: { autocapitalize: :none, autocorrect: :off } + %> + + <%= f.input :interval, as: :integer, required: true %> + + <%= f.input :label, hint: t(".label_hint") %> + + <%= f.button :submit, class: "btn-primary mt-3" %> +<% end %> diff --git a/app/views/notifications/_nested_form.html.erb b/app/views/notifications/_nested_form.html.erb index 52e7472..a946ce8 100644 --- a/app/views/notifications/_nested_form.html.erb +++ b/app/views/notifications/_nested_form.html.erb @@ -12,20 +12,16 @@ <% end %> -
+
<%= f.input :recipient, as: :email, label: false %>
- <%= f.input :interval, as: :integer, label: false %> + <%= f.input :interval, as: :integer, label: false, required: true %>
-
- <% if f.object.persisted? %> - <%= link_to check_notification_path(check, f.object), method: :delete, remote: true, class: "btn btn-danger" do %> - <%== Octicons::Octicon.new("x", width: 15, height: 20).to_svg %> - <% end %> - <% end %> +
+ <%= f.input :label, label: false %>
diff --git a/app/views/notifications/_nested_form_headers.html.erb b/app/views/notifications/_nested_form_headers.html.erb index 4e538c4..b0d3077 100644 --- a/app/views/notifications/_nested_form_headers.html.erb +++ b/app/views/notifications/_nested_form_headers.html.erb @@ -7,11 +7,15 @@
<% end %> -
+
<%= f.label :recipient %>
- <%= f.label :interval %> + <%= f.label :interval, required: true %> +
+ +
+ <%= f.label :label %>
diff --git a/app/views/notifications/_table.html.erb b/app/views/notifications/_table.html.erb new file mode 100644 index 0000000..f54721d --- /dev/null +++ b/app/views/notifications/_table.html.erb @@ -0,0 +1,46 @@ +<% # Copyright (C) 2018 Colin Darie , 2018 Evolix %> +<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> +
+ + + + + + + + + + + + <% notifications.each do |notification| %> + + + + + + + + <% end %> + +
+ <%= Notification.human_attribute_name("label") %> + + <%= Notification.human_attribute_name("recipient") %> + + <%= Notification.human_attribute_name("interval") %> + + <%= Notification.human_attribute_name("checks_count") %> + <%= t(".th.edit") %>
+ <%= notification.label %> + + <%= notification.recipient %> + + <%= t(".interval_in_days", count: notification.interval) %> + + <%= notification.checks_count %> + + <%= link_to edit_notification_path(notification), "data-turbolinks" => false do %> + <%== Octicons::Octicon.new("pencil").to_svg %> + <% end %> +
+
diff --git a/app/views/notifications/destroy.js.erb b/app/views/notifications/destroy.js.erb deleted file mode 100644 index e05a19b..0000000 --- a/app/views/notifications/destroy.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% # Copyright (C) 2018 Colin Darie , 2018 Evolix %> -<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> -document.querySelector("[data-notification-id='<%= @notification.id %>']").remove(); diff --git a/app/views/notifications/edit.html.erb b/app/views/notifications/edit.html.erb new file mode 100644 index 0000000..9c996c5 --- /dev/null +++ b/app/views/notifications/edit.html.erb @@ -0,0 +1,27 @@ +<% # Copyright (C) 2018 Colin Darie , 2018 Evolix %> +<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> +
+
+
+

<%= t(".title") %>

+ + <%= render "form", notification: @notification %> +
+
+ +
+
+

<%= t(".checks", count: @notification.checks_count) %>

+ <% if @notification.checks_count.positive? %> + <%= render "checks/table", checks: @notification.checks, skip_sort: true, skip_pagination: true %> + <% end %> +
+
+ +
+
+ <%= button_to(t("helpers.submit.notification.delete"), notification_path(@notification), class: "btn btn-danger", method: :delete, + data: { confirm: t(".destroy_confirmation", count: @notification.checks_count) }) %> +
+
+
diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb new file mode 100644 index 0000000..af5f65b --- /dev/null +++ b/app/views/notifications/index.html.erb @@ -0,0 +1,22 @@ +<% # Copyright (C) 2018 Colin Darie , 2018 Evolix %> +<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> +
+
+
+ <% if @notifications.empty? %> +
+ <%= t(".no_notification_yet_html", new_path: new_notification_path) %> +
+ <% else %> +
+ <%= link_to("Ajouter une notification", new_notification_path, class: "btn btn-primary") %> +
+

<%= t(".title") %>

+ <%= render "table", notifications: @notifications %> + <% end %> +
+

<%= t(".explanation") %>

+
+
+
+
diff --git a/app/views/notifications/new.html.erb b/app/views/notifications/new.html.erb new file mode 100644 index 0000000..6c777a9 --- /dev/null +++ b/app/views/notifications/new.html.erb @@ -0,0 +1,11 @@ +<% # Copyright (C) 2018 Colin Darie , 2018 Evolix %> +<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> +
+
+
+

<%= t(".title") %>

+ + <%= render "form", notification: @notification %> +
+
+
diff --git a/app/views/shared/_navbar.html.erb b/app/views/shared/_navbar.html.erb index 00b87e5..f4ba67b 100644 --- a/app/views/shared/_navbar.html.erb +++ b/app/views/shared/_navbar.html.erb @@ -2,7 +2,7 @@ <% # License: GNU AGPL-3+ (see full text in LICENSE file) %>