From 281caaf0fd6671a64ec3c332792df88670f52455 Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Fri, 14 Apr 2017 11:34:01 +0200 Subject: [PATCH] Manage publicities --- .gitignore | 3 +- app/assets/stylesheets/application.sass | 5 ++- .../admin/application_controller.rb | 12 ++++++- .../admin/publicities_controller.rb | 29 +++++++++++++++ app/controllers/application_controller.rb | 4 +++ app/models/supporter.rb | 1 + app/views/admin/publicities/_form.slim | 14 ++++++++ app/views/admin/publicities/edit.slim | 1 + app/views/admin/publicities/index.slim | 19 ++++++++++ app/views/layouts/application.html.slim | 2 +- app/views/shared/_topnavigation.slim | 3 ++ app/views/supporters/_publicity.slim | 5 +-- config/locales/admin.de.yml | 8 +++++ config/locales/admin.fr.yml | 8 +++++ config/locales/admin.it.yml | 8 +++++ config/locales/de.yml | 11 ++++-- config/locales/fr.yml | 12 +++++-- config/locales/it.yml | 9 +++-- config/routes.rb | 5 +-- spec/features/publicity_spec.rb | 36 ++++++++++++++++++- 20 files changed, 176 insertions(+), 19 deletions(-) create mode 100644 app/controllers/admin/publicities_controller.rb create mode 100644 app/views/admin/publicities/_form.slim create mode 100644 app/views/admin/publicities/edit.slim create mode 100644 app/views/admin/publicities/index.slim create mode 100644 config/locales/admin.de.yml create mode 100644 config/locales/admin.fr.yml create mode 100644 config/locales/admin.it.yml diff --git a/.gitignore b/.gitignore index f8f9ae3..63888d9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,8 @@ /.bundle /.rspec .ruby-version - +.env +/avatars # Ignore all logfiles and tempfiles. /log/* !/log/.keep diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass index 76da4d7..a24a73f 100644 --- a/app/assets/stylesheets/application.sass +++ b/app/assets/stylesheets/application.sass @@ -35,12 +35,15 @@ $font-size-h3: floor($font-size-base * 1.2) .alert-notice @extend .alert-info +body.admin + background: repeating-linear-gradient(45deg, yellow, yellow 50px, black 50px, black 100px) + body > .container box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19) padding: 20px margin-top: 10px - + background: #FFF header h1 font-size: 20px diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index 8d84545..b4853a4 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -1,5 +1,15 @@ module Admin class ApplicationController < ::ApplicationController - http_basic_authenticate_with name: 'admin', password: ENV['ADMIN_PASSWORD'] unless Rails.env.development? + before_action :authenticate_supporter! + before_action :authenticate_admin! + + def authenticate_admin! + return true if current_supporter.admin? + head(:forbidden) + end + + def admin_area + true + end end end diff --git a/app/controllers/admin/publicities_controller.rb b/app/controllers/admin/publicities_controller.rb new file mode 100644 index 0000000..1e793b9 --- /dev/null +++ b/app/controllers/admin/publicities_controller.rb @@ -0,0 +1,29 @@ +module Admin + class PublicitiesController < Admin::ApplicationController + def index + @pending = Supporter.where('publicity.state' => :pending).asc(:created_at) + @active = Supporter.where('publicity.state' => :approved).asc(:created_at) + end + + def edit + @publicity = Supporter.find(params[:id]).publicity + end + + def update + @publicity = Supporter.find(params[:id]).publicity + return redirect_to(admin_publicities_path) if @publicity.update_attributes(publicity_params) + render :edit + end + + def destroy + current_supporter.publicity&.destroy + redirect_to(admin_publicities_path) + end + + private + + def publicity_params + params.require(:publicity).permit(:organisation, :statement, :avatar, :state) + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 97edce3..f89a0ce 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -29,6 +29,10 @@ class ApplicationController < ActionController::Base options.merge locale: I18n.locale end + def admin_area + false + end + protected def configure_permitted_parameters diff --git a/app/models/supporter.rb b/app/models/supporter.rb index 8c6a75e..5d3fd57 100644 --- a/app/models/supporter.rb +++ b/app/models/supporter.rb @@ -14,6 +14,7 @@ class Supporter ## Database authenticatable field :email, type: String, default: '' field :encrypted_password, type: String, default: '' + field :admin, type: Boolean, default: false ## Recoverable field :reset_password_token, type: String diff --git a/app/views/admin/publicities/_form.slim b/app/views/admin/publicities/_form.slim new file mode 100644 index 0000000..4677346 --- /dev/null +++ b/app/views/admin/publicities/_form.slim @@ -0,0 +1,14 @@ +h1= title "#{t('.title')} #{@publicity.supporter.first_name} #{@publicity.supporter.last_name}, #{@publicity.supporter.city}" += simple_form_for(@publicity, url: admin_publicity_path(@publicity.supporter)) do |form| + .form-group + = "#{@publicity.supporter.first_name} #{@publicity.supporter.last_name}, #{@publicity.supporter.city}" + + = form.input :organisation, required: false + = form.input :statement, as: :text, required: false + = form.input :avatar, as: :file, required: false + - if @publicity.avatar + .form-group + = image_tag(@publicity.avatar.url(:medium)) + = form.input :state, as: :radio_buttons, collection: t('publicity_states').map{ |x| [x.first, raw(x.last)]}, label_method: :last, value_method: :first, required: false + = form.submit t('shared.save'), class: 'btn btn-primary' + \ No newline at end of file diff --git a/app/views/admin/publicities/edit.slim b/app/views/admin/publicities/edit.slim new file mode 100644 index 0000000..86842fe --- /dev/null +++ b/app/views/admin/publicities/edit.slim @@ -0,0 +1 @@ += render 'form' \ No newline at end of file diff --git a/app/views/admin/publicities/index.slim b/app/views/admin/publicities/index.slim new file mode 100644 index 0000000..73161e2 --- /dev/null +++ b/app/views/admin/publicities/index.slim @@ -0,0 +1,19 @@ +h1 = title t('.title') +table.table + tbody + - @pending.each do | supporter | + tr + td + = "#{supporter.first_name} #{supporter.last_name}" + br + = supporter.city + br + = mail_to supporter.email, supporter.email + br + = supporter.publicity.organisation + td width="50%" = supporter.publicity.statement + td = image_tag(supporter.publicity.avatar.url(:small)) + td = link_to t('shared.edit'), edit_admin_publicity_path(supporter) + + + \ No newline at end of file diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index 9efb0c8..332178b 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -26,7 +26,7 @@ html lang="#{I18n.locale}" meta content="/ms-icon-144x144.png" name="msapplication-TileImage" / meta content="#ffffff" name="theme-color" / - body + body class="#{'admin' if controller.admin_area}" javascript: (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), diff --git a/app/views/shared/_topnavigation.slim b/app/views/shared/_topnavigation.slim index 458c103..2d7adbb 100644 --- a/app/views/shared/_topnavigation.slim +++ b/app/views/shared/_topnavigation.slim @@ -11,3 +11,6 @@ = navbar_item t('.sponsoring'), sponsoring_path = navbar_item t('.sign_in'), new_supporter_session_path unless supporter_signed_in? = navbar_item t('.sign_out'), destroy_supporter_session_path, nil, 'data-method' => :delete if supporter_signed_in? + - if supporter_signed_in? && current_supporter.admin? + = navbar_dropdown t('admin.title') do + = navbar_item t('admin.publicities.index.title'), admin_publicities_path diff --git a/app/views/supporters/_publicity.slim b/app/views/supporters/_publicity.slim index 8b52df5..9a9cb65 100644 --- a/app/views/supporters/_publicity.slim +++ b/app/views/supporters/_publicity.slim @@ -6,10 +6,7 @@ .panel-body dl.dl-horizontal dt = Publicity.human_attribute_name(:status) - - if current_supporter.publicity.state == 'pending' - dd.text-danger = t('.pending') - - if current_supporter.publicity.state == 'approved' - dd.text-success = t('.pending') + dd= t("publicity_states.#{current_supporter.publicity.state}") - unless current_supporter.publicity.organisation.blank? dt = Publicity.human_attribute_name(:organisation) dd = current_supporter.publicity.organisation diff --git a/config/locales/admin.de.yml b/config/locales/admin.de.yml new file mode 100644 index 0000000..c1d34ba --- /dev/null +++ b/config/locales/admin.de.yml @@ -0,0 +1,8 @@ +de: + admin: + title: Administration + publicities: + index: + title: Unveröffentlichte Statements + form: + title: Statement \ No newline at end of file diff --git a/config/locales/admin.fr.yml b/config/locales/admin.fr.yml new file mode 100644 index 0000000..9691325 --- /dev/null +++ b/config/locales/admin.fr.yml @@ -0,0 +1,8 @@ +fr: + admin: + title: Administration + publicities: + index: + title: Déclarations non publiées + form: + title: Déclaration diff --git a/config/locales/admin.it.yml b/config/locales/admin.it.yml new file mode 100644 index 0000000..084c1f3 --- /dev/null +++ b/config/locales/admin.it.yml @@ -0,0 +1,8 @@ +it: + admin: + title: Amministrazione + publicities: + index: + title: Dichiarazioni non pubblicati + form: + title: Dichiarazione \ No newline at end of file diff --git a/config/locales/de.yml b/config/locales/de.yml index e3a38d5..3329f77 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -17,6 +17,8 @@ de: numbers: Zahlen are_you_sure: Bist du sicher? + edit: Bearbeiten + save: Speichern counter: supporters: "Unterstützer:" @@ -38,6 +40,11 @@ de: young: Ich bin 18 bis 30 Jahre alt middle: Ich bin 30 bis 64 Jahre alt retired: Ich bin über 64 Jahre alt + + publicity_states: + pending: Die Veröffentlichung wurde noch nicht genehmigt + approved: Das Statement wurde Veröffentlicht + declined: Das Statement wurde abgelehnt languages: de: Deutsch @@ -64,8 +71,6 @@ de: title: Mein Statement renew: Statement neu einreichen delete: Statement löschen - pending: Die Veröffentlichung wurde noch nicht genehmigt - approved: Das statement wurde Veröffentlicht create_publicity: Deine Meinung zählt, darum bitten wir dir hier die Möglichkeit öffentlich deine Meinung zur Cannabis-Initiative kundzutun. Gib ein Starkes Statement ab und zeig dein Gesicht! Meine Unterstützung öffentlich kundtun ... create: @@ -125,7 +130,7 @@ de: password_confirmation: Passwort bestätigen current_password: Aktuelles Passwort publicity: - status: Status + state: Status organisation: Organisation statement: Statement avatar: Bild \ No newline at end of file diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 2f5ee65..bfa9241 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -22,6 +22,8 @@ fr: numbers: Chiffres (en allemand) are_you_sure: Tu es sûre? + edit: Éditer + save: Sauver welcome_email: subject: Merci beaucoup pour ton soutien! @@ -37,7 +39,12 @@ fr: young: J’ai entre 18 et 30 ans middle: J’ai entre 30 et 64 ans retired: J’ai plus que 64 ans - + + publicity_states: + pending: La publication n'a pas été approuvé + approved: La déclaration a été publiée + declined: La déclaration a été rejetée + languages: de: Deutsch fr: Français @@ -56,12 +63,11 @@ fr: city: Hinterpfupfikon zip: "4200" email: hans.muster@hanflegal.ch + publicity: title: Ma déclaration renew: resoumettre déclaration delete: supprimer déclaration - pending: La publication n'a pas été approuvé - approved: La déclaration a été publiée create_publicity: Votre opinion compte, nous vous demandons ici d'exprimer publiquement votre avis sur initiative de cannabis possible. Rendre public mon soutien ... create: diff --git a/config/locales/it.yml b/config/locales/it.yml index f80f6a8..e40582c 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -23,6 +23,8 @@ it: amount_of_supporters: Al momento abbiamo %{amount} sostenitori. are_you_sure: Sei sicuro? + edit: Modifica + save: Salvare welcome_email: subject: Grazie mille per il tuo sostegno! @@ -39,6 +41,11 @@ it: middle: Ho tra i 30 ed i 64 anni retired: Ho più di 64 anni + publicity_states: + pending: La pubblicazione non è stato approvato + approved: La dichiarazione è stata rilasciata + declined: La dichiarazione è stata respinta + languages: de: Deutsch fr: Français @@ -63,8 +70,6 @@ it: title: La mia dichiarazione renew: Ripresentare Statement delete: Eliminare la dichiarazione - pending: La pubblicazione non è stato approvato - approved: La dichiarazione è stata rilasciata create_publicity: La tua opinione conta, quindi vi chiediamo qui pubblicamente esprimere la tua opinione su iniziativa di cannabis possibile. Girare in una dichiarazione forte e mostrare il tuo volto! Il mio supporto rendere pubblico ... create: diff --git a/config/routes.rb b/config/routes.rb index b2c600a..8f28b07 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,12 +2,11 @@ Rails.application.routes.draw do devise_for :supporters root to: 'supporters#new' - mount RailsAdmin::Engine => '/admin', as: 'rails_admin' - get "/pages/:page" => "pages#show" namespace :admin do get '/map', to: 'pages#map', as: :map + resources :publicities # resources :supporters, only: :index end @@ -28,4 +27,6 @@ Rails.application.routes.draw do get '/thanks', to: 'pages#thanks', as: :thanks get '/spenden', to: 'pages#spenden', as: :spenden end + + mount RailsAdmin::Engine => '/admin', as: 'rails_admin' end diff --git a/spec/features/publicity_spec.rb b/spec/features/publicity_spec.rb index d924069..9a88c36 100644 --- a/spec/features/publicity_spec.rb +++ b/spec/features/publicity_spec.rb @@ -1,7 +1,8 @@ require 'rails_helper' feature 'Publicity' do - let(:supporter) { create :supporter } + let(:supporter) { create :supporter, first_name: 'Hans', last_name: 'Muster' } + let(:admin) { create :supporter, admin: true } before { sign_in(supporter) } @@ -38,4 +39,37 @@ feature 'Publicity' do expect(page).to have_content 'Besten Dank die Daten werden überprüft.' expect(page).to have_content 'Die Veröffentlichung wurde noch nicht genehmigt' end + + scenario 'non admin users cannot manage pending publicities' do + visit admin_publicities_path + expect(page.status_code).to eq 403 + end + context 'management' do + + + before { sign_in(admin) } + + scenario 'an administrator approves a pending announcement' do + create :publicity, state: :pending, supporter: supporter + + # Already declined, so we don't list it' + create :publicity, state: :declined, supporter: create(:supporter, first_name: 'Donald', last_name: 'Trump') + + visit admin_publicities_path + + expect(page).to have_content 'Hans Muster' + expect(page).not_to have_content 'Donald Trump' + + click_link 'Bearbeiten' + + fill_in 'Organisation', with: 'Free Hemp Association' + fill_in 'Statement', with: 'Marihuana ist die Heilung der Nation, Alkohol die Zerstörung.' + attach_file('publicity_avatar', "#{Rails.root}/spec/support/fixtures/image.jpg") + choose 'Das Statement wurde Veröffentlicht' + + click_button 'Speichern' + + expect(page).not_to have_content 'Hans Muster' + end + end end \ No newline at end of file