diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index 86eca4ecdc..9c92a15841 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -183,6 +183,10 @@ def default_solr_doc_params(id = nil) def index @presenter = HomeTextPresenter.new(current_user) + unless has_search_parameters? + @presenter.primary_messages = ContentBlock.active.primary + @presenter.secondary_messages = ContentBlock.active.secondary + end super end diff --git a/app/controllers/content_blocks_controller.rb b/app/controllers/content_blocks_controller.rb new file mode 100644 index 0000000000..2d4b6bc5a7 --- /dev/null +++ b/app/controllers/content_blocks_controller.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class ContentBlocksController < ApplicationController + before_action :set_content_block, only: %i[create update destroy] + authorize_resource + + # GET /content_blocks + def index + @unexpired_blocks = ContentBlock.unexpired + @expired_blocks = ContentBlock.expired + end + + # POST /content_blocks + def create + @content_block.save! + redirect_to content_blocks_path + end + + # PATCH/PUT /content_blocks/1 + def update + @content_block.save! + redirect_to content_blocks_path + end + + # DELETE /content_blocks/1 + def destroy + @content_block.destroy + redirect_to content_blocks_path + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_content_block + @content_block = params[:id] ? ContentBlock.find(params[:id]) : ContentBlock.new + return unless params[:content_block] + + start_at = params[:content_block][:start_at].in_time_zone('America/Los_Angeles') + end_at = params[:content_block][:end_at].in_time_zone('America/Los_Angeles').end_of_day + @content_block.attributes = { end_at: end_at, start_at: start_at, ordinal: params[:content_block][:ordinal], value: params[:content_block][:value] } + end +end diff --git a/app/javascript/argo.js b/app/javascript/argo.js index 0caf6cabd9..f8bf661849 100644 --- a/app/javascript/argo.js +++ b/app/javascript/argo.js @@ -1,5 +1,8 @@ import Form from 'modules/apo_form' import CollectionEditor from 'controllers/collection_editor' +import ContentBlockNew from 'controllers/content_block_new' +import ContentBlockEdit from 'controllers/content_block_edit' + import BulkActions from 'controllers/bulk_actions' import BulkUpload from 'controllers/bulk_upload' import FacetFilter from 'controllers/facet_filter' @@ -46,6 +49,8 @@ export default class Argo { application.register("facet-filter", FacetFilter) application.register("workflow-grid", WorkflowGrid) application.register("collection-editor", CollectionEditor) + application.register("content-block-new", ContentBlockNew) + application.register("content-block-edit", ContentBlockEdit) application.register("tokens", Tokens) } diff --git a/app/javascript/controllers/content_block_edit.js b/app/javascript/controllers/content_block_edit.js new file mode 100644 index 0000000000..2bb83e8f36 --- /dev/null +++ b/app/javascript/controllers/content_block_edit.js @@ -0,0 +1,43 @@ +import { Controller } from 'stimulus' + +export default class extends Controller { + static targets = [ "value", "ordinal", "startAt", "endAt" ] + + display(event) { + event.preventDefault() + + // Save the old HTML so we can cancel. + this.existingHTML = this.element.innerHTML + + // Display the editor + let template = document.getElementById('edit-row') + this.element.innerHTML = template.innerHTML + + // Populate the form with the values for this row + this.valueTarget.value = this.data.get('value') + this.ordinalTarget.value = this.data.get('ordinal') + this.startAtTarget.value = this.data.get('start_at') + this.endAtTarget.value = this.data.get('end_at') + } + + save(event) { + // remove the new form fields + document.querySelector('[data-target="content-block-new.form"').remove() + + // Update the form so it updates the current item. + let form = document.querySelector('[data-target="content-block-form"]') + form.action = this.data.get('url') + + // Set the patch method on the form + var input = document.createElement("input"); + input.type = 'hidden' + input.name = '_method' + input.value = 'patch' + form.appendChild(input) + } + + cancel(event) { + event.preventDefault() + this.element.innerHTML = this.existingHTML + } +} diff --git a/app/javascript/controllers/content_block_new.js b/app/javascript/controllers/content_block_new.js new file mode 100644 index 0000000000..d482009fce --- /dev/null +++ b/app/javascript/controllers/content_block_new.js @@ -0,0 +1,23 @@ +import { Controller } from 'stimulus' + +export default class extends Controller { + static targets = [ "button", "form", "headerRow" ] + + display(event) { + event.preventDefault() + this.formTarget.classList.remove('d-none') + // The header row doesn't display if there are no existing records, so display it now. + this.headerRowTarget.classList.remove('d-none') + this.buttonTarget.classList.add('d-none') + } + + cancel(event) { + event.preventDefault() + this.hideForm() + } + + hideForm() { + this.formTarget.classList.add('d-none') + this.buttonTarget.classList.remove('d-none') + } +} diff --git a/app/javascript/style/application.scss b/app/javascript/style/application.scss index 6130f2bc0e..b457a9ed55 100644 --- a/app/javascript/style/application.scss +++ b/app/javascript/style/application.scss @@ -3,6 +3,11 @@ @import 'variables'; @import 'bootstrap/scss/bootstrap'; @import 'bootstrap-overrides'; + +$fa-font-path: '~@fortawesome/fontawesome-free/webfonts'; +@import "@fortawesome/fontawesome-free/scss/fontawesome.scss"; +@import "@fortawesome/fontawesome-free/scss/solid.scss"; + // Override before importing Blacklight $logo-image: "../images/logo.png"; @import 'blacklight-frontend/app/assets/stylesheets/blacklight/blacklight'; diff --git a/app/javascript/style/bootstrap-overrides.scss b/app/javascript/style/bootstrap-overrides.scss index c82f326548..902e505ced 100644 --- a/app/javascript/style/bootstrap-overrides.scss +++ b/app/javascript/style/bootstrap-overrides.scss @@ -32,3 +32,14 @@ color: $body-color; opacity: 1.0; } + +.alert-warning { + @include alert-variant(theme-color-level('warning', $alert-bg-level), $gamboge, $body-color); + + .fa-exclamation-circle { + color: $gamboge; + font-size: 2em; + margin-right: .5em; + vertical-align: middle; + } +} diff --git a/app/javascript/style/variables.scss b/app/javascript/style/variables.scss index 732135ba19..05bc4637be 100644 --- a/app/javascript/style/variables.scss +++ b/app/javascript/style/variables.scss @@ -8,6 +8,7 @@ $barley-corn: #b3995d; $floral-white: #f9f6ef; $tahuna-sands: #d2c295; +$gamboge: #eaab01; $tea: #b6b1a9; $silver: #c5c5c5; diff --git a/app/models/content_block.rb b/app/models/content_block.rb new file mode 100644 index 0000000000..7eccd3567a --- /dev/null +++ b/app/models/content_block.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class ContentBlock < ApplicationRecord + ORDINAL_STRING = { 1 => 'Primary', 2 => 'Secondary' }.freeze + scope :expired, -> { where('end_at < ?', current_time) } + scope :unexpired, -> { where('end_at >= ?', current_time) } + scope :active, -> { where('start_at < ? AND end_at >= ?', current_time, current_time) } + scope :primary, -> { where(ordinal: 1) } + scope :secondary, -> { where(ordinal: 2) } + + validates :ordinal, presence: true, inclusion: { in: [1, 2] } + + def self.current_time + Time.now.in_time_zone('America/Los_Angeles') + end + + def ordinal_string + ORDINAL_STRING.fetch(ordinal) + end + + def pacific_start + start_at.in_time_zone('America/Los_Angeles') + end + + def pacific_end + end_at.in_time_zone('America/Los_Angeles') + end +end diff --git a/app/presenters/home_text_presenter.rb b/app/presenters/home_text_presenter.rb index e09b62e1ec..d2320f71ef 100644 --- a/app/presenters/home_text_presenter.rb +++ b/app/presenters/home_text_presenter.rb @@ -4,6 +4,8 @@ class HomeTextPresenter def initialize(current_user) @current_user = current_user + @primary_messages = [] + @secondary_messages = [] end # @return [Boolean] true if this user has permissions to see anything in Argo @@ -11,6 +13,8 @@ def view_something? is_admin? || is_manager? || is_viewer? || permitted_apos.any? end + attr_accessor :primary_messages, :secondary_messages + private attr_reader :current_user diff --git a/app/views/catalog/_home_text.html.erb b/app/views/catalog/_home_text.html.erb index 4453c43bbe..0637a06cdf 100644 --- a/app/views/catalog/_home_text.html.erb +++ b/app/views/catalog/_home_text.html.erb @@ -9,4 +9,23 @@ You do not appear to have permission to view any items in Argo. Please contact an administrator.
<% end %> + + <% @presenter.primary_messages.each do |block| %> +Primary messages will appear in a yellow box at the top of the homepage. Secondary messages + will display below the yellow primary messages boxes in a bulleted list. Max 1,000 characters per message.
+<%= form_with(model: ContentBlock.new, local: true, data: { controller: 'content-block-new', target: 'content-block-form' }) do |form| %> + +Message alerts | +Primary/Secondary | +Start date | +Expiration date | ++ |
---|---|---|---|---|
<%= block.value %> | +<%= block.ordinal_string %> | +<%= block.pacific_start.to_date %> | +<%= block.pacific_end.to_date %> | ++ + <%= link_to block, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn' do %> + + <% end %> + | +
+ <%= form.label :value, 'Text', class: 'sr-only' %> + <%= form.text_area :value, class: 'form-control' %> + | + ++ <%= form.label :ordinal, 'Primary/Secondary', class: 'sr-only' %> + <%= form.select :ordinal, [['Primary', 1], ['Secondary', 2]], {}, class: 'form-control' %> + | + ++ <%= form.label :start_at, 'Start date', class: 'sr-only' %> + <%= form.date_field :start_at, value: Time.zone.today, class: 'form-control' %> + | + ++ <%= form.label :end_at, 'Expiration date', class: 'sr-only' %> + <%= form.date_field :end_at, value: Time.zone.today + 3.months, class: 'form-control' %> + | + ++ + <%= form.submit 'Save', class: 'btn btn-primary' %> + | +
Expired message alerts | +Primary/Secondary | +Start date | +Expiration date | +
---|---|---|---|
<%= block.value %> | +<%= block.ordinal_string %> | +<%= block.start_at.to_date %> | +<%= block.end_at.to_date %> | +