Skip to content

Add news popups #539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 14 commits into
base: mampf-next
Choose a base branch
from
29 changes: 29 additions & 0 deletions app/assets/javascripts/news_popups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
console.log('loaded');

// <input class="form-control" value="<%= popup.name %>">


$(document).on('turbolinks:load', () => {
registerNewsPopupsAdminTableHandlers();
});

function registerNewsPopupsAdminTableHandlers() {
$('.news-popups-name').on('click', (e) => {
// If has input, do nothing
if ($(e.target).find('input').length > 0) {
return;
}

const rowId = $(e.target).parent().attr('id').split('-').pop();
console.log('rowId: ' + rowId);

const text = $(e.target).text().trim();
const inputHtml = `<input class="form-control news-popups-name-current" value="${text}">`;
$(e.target).html(inputHtml);

$('.news-popups-name-current').focus();
});


console.log('admin table registered');
}
5 changes: 5 additions & 0 deletions app/assets/stylesheets/admin.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
.admin-background {
background-size: 20px 20px;
background-image: radial-gradient(circle, #bebebe 1px, #ffffff00 1px);
}


#admin-news {
max-width: 1400px;
}
7 changes: 7 additions & 0 deletions app/assets/stylesheets/news_popups.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#news-popups-list-header {
font-weight: bold;
}

#news-popups-list-header {
word-wrap: break-word;
}
1 change: 1 addition & 0 deletions app/controllers/announcements_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def index
.order(:created_at)
.reverse)
.page(params[:page]).per(10)
@news_popups = NewsPopup.all
end

def new
Expand Down
35 changes: 35 additions & 0 deletions app/controllers/news_popups_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class NewsPopupsController < ApplicationController
before_action :set_news_popup, only: [:edit, :cancel_edit, :update]

def index
respond_to do |format|
format.json { render json: unseen_news_popups.pluck(:name) }
end
end

def edit; end

def cancel_edit; end

def update
@news_popup.update(news_popup_params)
end

private

def unseen_news_popups
NewsPopup
.where(active: true)
.where.not(id: HasSeenNewsPopup
.where(user: current_user)
.pluck(:news_popup_id))
end

def set_news_popup
@news_popup = NewsPopup.find_by(id: params[:id])
end

def news_popup_params
params.require(:news_popup).permit(:name, :active)
end
end
101 changes: 100 additions & 1 deletion app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,103 @@ document.addEventListener("turbolinks:load", function () {
$('.masonry-grid').masonry({
percentPosition: true
});
})

// TODO (Splines): outsource news popups logic to separate file
handleNewsPopups();
});

const NEWS_POPUPS_BASE_PATH = '/news_popups/';
const NEWS_POPUPS_CONTAINER_PATH = '/news_popups/_container.html';

function handleNewsPopups() {
$.get({
url: Routes.news_popups_path(),
type: 'GET',
dataType: 'json',
success: (popupNames) => {
console.log(`Found unread news popups: ${popupNames}`);
openNewsPopups(popupNames);
},
error: (xhr, status) => {
console.log('ERROR fetching news popups');
console.log(xhr);
console.log(status);
}
});
}

async function openNewsPopups(popupNames) {
// Are there any unread news popups?
if (popupNames.length === 0) {
console.log('No unread news popups found. Aborting.');
return;
}

// Container
let containerHtml = "";
try {
containerHtml = await fetchNewsPopupsContainerHtml();
} catch (error) {
console.log('Container for news popups could not be fetched. Aborting.');
console.log(error);
return;
}

// Contents
const contentsHtml = await fetchNewsPopupsContentHtml(popupNames);
if (contentsHtml.length === 0) {
console.log('No news popups content could be fetched. Aborting.');
return;
}

showNewsPopupsInDom(containerHtml, contentsHtml);
}

async function fetchNewsPopupsContainerHtml() {
return new Promise((resolve, reject) => {
$.ajax({
url: NEWS_POPUPS_CONTAINER_PATH,
type: 'GET',
dataType: 'html',
success: (html, textStatus, xhr) => {
resolve(html);
},
error: (xhr, status) => {
console.log(xhr);
console.log(status);
reject('ERROR getting HTML for news popups container');
}
});
});
}

async function fetchNewsPopupsContentHtml(popupNames) {
return await Promise.all(popupNames.map(async (popupName) => {
return new Promise((resolve, reject) => {
$.ajax({
url: NEWS_POPUPS_BASE_PATH + popupName + '.html',
type: 'GET',
dataType: 'html',
success: (html, textStatus, xhr) => {
resolve(html);
},
error: (xhr, status) => {
// Note that this this not occur if the file does not exist.
// In that case, the success callback is called since MaMpf
// is redirecting and we get back the HTML of the redirect.
// This is why admins must check if the file exists before
// activating the news popup.
const errorReason = `ERROR getting HTML for news popup: ${popupName} `;
reject(errorReason);
}
});
});
}));
}

function showNewsPopupsInDom(containerHtml, contentsHtml) {
const container = $(containerHtml);
$('#news-popup-body', container).append(contentsHtml);
$('body').append(container);
$('#news-popup-modal').modal('show');
}
4 changes: 4 additions & 0 deletions app/models/has_seen_news_popup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class HasSeenNewsPopup < ApplicationRecord
belongs_to :user
belongs_to :news_popup
end
2 changes: 2 additions & 0 deletions app/models/news_popup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NewsPopup < ApplicationRecord
end
138 changes: 88 additions & 50 deletions app/views/announcements/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,55 +1,93 @@
<div class="row mt-3 p-2">
<div class="col-7">
<h4>
<%= t('basics.news') %>
</h4>
<%= javascript_include_tag :news_popups %>
<%= stylesheet_link_tag :news_popups %>

<div class="container" id="admin-news">

<%# News popups %>
<div class="row p-3">
<h4>News Popups</h4>

<div class="list-group">
<div class="list-group-item bg-light" id="news-popups-list-header">
<div class="row">
<div class="col-2">
<%= t('basics.created_at') %>
</div>
<div class="col-2">
<%= t('basics.updated_at') %>
</div>
<div class="col-5">
<%= t('basics.name') %>
</div>
<div class="col-2">
<%= t('basics.active') %>
</div>
<div class="col-1">
<%= t('basics.action') %>
</div>
</div>
</div>
<% @news_popups.each do |news_popup| %>
<%= render partial: 'news_popups/row',
locals: { popup: news_popup} %>
<% end %>
</div>
</div>
<div class="col-3">
<%= paginate @announcements, window: 2 %>

<%# News %>
<div class="row mt-3 p-2">
<div class="col-7">
<h4>
<%= t('basics.news') %>
</h4>
</div>
<div class="col-3">
<%= paginate @announcements, window: 2 %>
</div>
<div class="col-2 text-end">
<%= link_to t('buttons.create_announcement'),
new_announcement_path,
class: 'btn btn-sm btn-secondary',
remote: true %>
</div>
</div>
<div class="col-2 text-end">
<%= link_to t('buttons.create_announcement'),
new_announcement_path,
class: 'btn btn-sm btn-secondary',
remote: true %>
<div class="row bg-mdb-color-lighten-2 mx-2 px-4 py-3">
<div class="col-2 text-light">
<strong>
<%= t('basics.date') %>
</strong>
</div>
<div class="col-2 text-light">
<strong>
<%= t('basics.author') %>
</strong>
</div>
<div class="col-5 text-light">
<strong>
<%= t('basics.text') %>
</strong>
</div>
<div class="col-1 text-light">
<strong>
<%= t('admin.announcement.main_page') %>
</strong>
</div>
<div class="col-2 text-light">
<strong>
<%= t('basics.action') %>
</strong>
</div>
</div>
</div>
<div class="row bg-mdb-color-lighten-2 mx-2 px-4 py-3">
<div class="col-2 text-light">
<strong>
<%= t('basics.date') %>
</strong>
</div>
<div class="col-2 text-light">
<strong>
<%= t('basics.author') %>
</strong>
</div>
<div class="col-5 text-light">
<strong>
<%= t('basics.text') %>
</strong>
</div>
<div class="col-1 text-light">
<strong>
<%= t('admin.announcement.main_page') %>
</strong>
<div id="row-new-announcement"
class="border-bottom mx-2 py-2"
style="display: none;">
</div>
<div class="col-2 text-light">
<strong>
<%= t('basics.action') %>
</strong>
</div>
</div>
<div id="row-new-announcement"
class="border-bottom mx-2 py-2"
style="display: none;" >
<% @announcements.each do |a| %>
<div class="row border-bottom mx-2 px-4 py-2 bg-white"
id="row-announcement-<%= a.id %>">
<%= render partial: 'announcements/row',
locals: { announcement: a } %>
</div>
<% end %>
<%= render partial: 'announcements/modal' %>
</div>
<% @announcements.each do |a| %>
<div class="row border-bottom mx-2 px-4 py-2"
id="row-announcement-<%= a.id %>">
<%= render partial: 'announcements/row',
locals: { announcement: a }%>
</div>
<% end %>
<%= render partial: 'announcements/modal' %>
40 changes: 40 additions & 0 deletions app/views/news_popups/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<div class="list-group-item news-popup-row" data-id="<%= popup.id.to_i %>">
<%= form_with model: popup do |f| %>
<div class="row align-items-center">
<div class="col-2 fw-light">
<%= popup.created_at %>
</div>
<div class="col-2 fw-light">
<%= popup.updated_at %>
</div>
<div class="col-3">
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="col-2">
<%= link_to 'Test',
'/news_popups/' + popup.name + '.html',
target: :_blank,
role: 'button',
class: 'btn btn-primary' %>
</div>
<div class="col-2">
<%= f.check_box :active, checked: popup.active,
class: "form-check-input" %>
</div>

<%# Actions %>
<div class="col-1">
<%= f.button nil, class: "btn btn-success p-1" do %>
<i class="bi bi-check-lg"></i>
<% end %>
<%= link_to cancel_editing_news_popups_path(popup),
class: 'btn btn-secondary p-1',
role: 'button',
title: t('buttons.edit'),
remote: true do %>
<i class="bi bi-x"></i>
<% end %>
</div>
</div>
<% end %>
</div>
Loading