Merge pull request #4252 from consul/sdg_goals_yaml

Add Sustainable Development Goals section
This commit is contained in:
Javi Martín
2020-12-03 17:58:58 +01:00
committed by GitHub
40 changed files with 444 additions and 10 deletions

View File

@@ -17,9 +17,7 @@
@include has-fa-icon($name, $style);
&::before {
font-size: rem-calc(20);
margin-left: rem-calc(8);
margin-right: rem-calc(10);
@extend %admin-menu-icon;
}
}

View File

@@ -28,3 +28,4 @@
@import "leaflet";
@import "sticky_overrides";
@import "admin/*";
@import "sdg_management/*";

View File

@@ -141,6 +141,13 @@
}
}
%font-icon {
@extend %fa-icon;
font-family: "Font Awesome 5 Free";
margin-right: rem-calc(4);
vertical-align: middle;
}
%svg-icon {
background: currentcolor;
content: "";
@@ -150,14 +157,17 @@
width: 1em;
}
%admin-menu-icon {
font-size: rem-calc(20);
margin-left: rem-calc(8);
margin-right: rem-calc(10);
}
@mixin has-fa-icon($icon, $style) {
@extend .fa-#{$icon};
&::before {
@extend %fa-icon;
font-family: "Font Awesome 5 Free";
margin-right: rem-calc(4);
vertical-align: middle;
@extend %font-icon;
@if $style == "regular" {
font-weight: normal;

View File

@@ -0,0 +1,10 @@
.sdg-content-menu {
.goals-link::before {
@extend %font-icon;
@extend %svg-icon;
@extend %admin-menu-icon;
mask-image: image-url("sdg.svg");
}
}

View File

@@ -0,0 +1,21 @@
<%= header %>
<table>
<thead>
<tr>
<th><%= attribute_name(:code) %></th>
<th><%= attribute_name(:title) %></th>
<th><%= attribute_name(:description) %></th>
</tr>
</thead>
<tbody>
<% goals.each do |goal| %>
<tr id="<%= dom_id(goal) %>" class="goal">
<td><%= goal.code %></td>
<td><%= goal.title %></td>
<td><%= goal.description %></td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -0,0 +1,19 @@
class SDGManagement::Goals::IndexComponent < ApplicationComponent
include SDGManagement::Header
attr_reader :goals
def initialize(goals)
@goals = goals
end
private
def title
SDG::Goal.model_name.human(count: 2).titleize
end
def attribute_name(attribute)
SDG::Goal.human_attribute_name(attribute)
end
end

View File

@@ -0,0 +1,11 @@
module SDGManagement::Header
extend ActiveSupport::Concern
def header
provide(:title) do
"#{t("sdg_management.header.title")} - #{title}"
end
tag.h2 title
end
end

View File

@@ -0,0 +1,5 @@
<ul class="sdg-content-menu">
<li class="<%= "is-active" if sdg? %>">
<%= link_to t("sdg_management.menu.sdg_content"), sdg_management_goals_path, class: "goals-link" %>
</li>
</ul>

View File

@@ -0,0 +1,7 @@
class SDGManagement::MenuComponent < ApplicationComponent
private
def sdg?
controller_name == "goals"
end
end

View File

@@ -0,0 +1,14 @@
class SDGManagement::BaseController < ApplicationController
layout "admin"
before_action :authenticate_user!
before_action :verify_sdg_manager
skip_authorization_check
private
def verify_sdg_manager
raise CanCan::AccessDenied unless current_user&.administrator?
end
end

View File

@@ -0,0 +1,5 @@
class SDGManagement::GoalsController < SDGManagement::BaseController
def index
@goals = SDG::Goal.order(:code)
end
end

View File

@@ -42,6 +42,6 @@ module AdminHelper
private
def namespace
controller.class.name.downcase.split("::").first
controller.class.name.split("::").first.underscore
end
end

5
app/models/sdg.rb Normal file
View File

@@ -0,0 +1,5 @@
module SDG
def self.table_name_prefix
"sdg_"
end
end

15
app/models/sdg/goal.rb Normal file
View File

@@ -0,0 +1,15 @@
class SDG::Goal < ApplicationRecord
validates :code, presence: true, uniqueness: true, inclusion: { in: 1..17 }
def title
I18n.t("sdg.goals.goal_#{code}.title")
end
def description
I18n.t("sdg.goals.goal_#{code}.description")
end
def self.[](code)
find_by!(code: code)
end
end

View File

@@ -15,6 +15,8 @@
<nav id="side_menu" class="admin-sidebar">
<% if namespace == "admin" %>
<%= render Admin::MenuComponent.new %>
<% elsif namespace == "sdg_management" %>
<%= render SDGManagement::MenuComponent.new %>
<% else %>
<%= render "/#{namespace}/menu" %>
<% end %>

View File

@@ -0,0 +1 @@
<%= render SDGManagement::Goals::IndexComponent.new(@goals) %>

View File

@@ -32,6 +32,12 @@
<%= link_to t("layouts.header.officing"), officing_root_path %>
</li>
<% end %>
<% if current_user.administrator? %>
<li>
<%= link_to t("sdg_management.header.title"), sdg_management_root_path %>
</li>
<% end %>
</ul>
</li>
<% end %>

View File

@@ -45,6 +45,7 @@ data:
- config/locales/%{locale}/user_groups.yml
- config/locales/%{locale}/i18n.yml
- config/locales/%{locale}/milestones.yml
- config/locales/%{locale}/sdg_management.yml
- config/locales/%{locale}/stats.yml
# Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:

View File

@@ -17,5 +17,6 @@
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.plural(/^(\d+)$/i, '\1')
inflect.acronym "SDG"
inflect.irregular "organización", "organizaciones"
end

View File

@@ -72,6 +72,9 @@ en:
proposal:
one: "Citizen proposal"
other: "Citizen proposals"
sdg/goal:
one: "goal"
other: "goals"
site_customization/page:
one: Custom page
other: Custom pages
@@ -308,6 +311,10 @@ en:
signable_type: "Signable type"
signable_id: "Signable ID"
document_numbers: "Documents numbers"
sdg/goal:
code: "Code"
title: "Title"
description: "Description"
site_customization/page:
content: Content
created_at: Created at

54
config/locales/en/sdg.yml Normal file
View File

@@ -0,0 +1,54 @@
en:
sdg:
goals:
goal_1:
title: "No Poverty"
description: "End poverty in all its forms, everywhere."
goal_2:
title: "Zero Hunger"
description: "Zero Hunger"
goal_3:
title: "Good Health and Well-Being"
description: "Ensure healthy lives and promote well-being for all at all ages."
goal_4:
title: "Quality Education"
description: "Quality Education"
goal_5:
title: "Gender Equality"
description: "Achieve gender equality and empower all women and girls."
goal_6:
title: "Clean Water and Sanitation"
description: "Ensure access to water and sanitation for all."
goal_7:
title: "Affordable and Clean Energy"
description: "Ensure access to affordable, reliable, sustainable and modern energy."
goal_8:
title: "Decent Work and Economic Growth"
description: "Promote inclusive and sustainable economic growth, employment and decent work for all."
goal_9:
title: "Industry, Innovation and Infrastructure"
description: "Build resilient infrastructure, promote sustainable industrialization and foster innovation."
goal_10:
title: "Reduced Inequalities"
description: "Reduce inequality within and among countries."
goal_11:
title: "Sustainable Cities and Communities"
description: "Make cities inclusive, safe, resilient and sustainable."
goal_12:
title: "Responsible Consumption and Production"
description: "Ensure sustainable consumption and production patterns."
goal_13:
title: "Climate Action"
description: "Take urgent action to combat climate change and its impacts."
goal_14:
title: "Life Below Water"
description: "Conserve and sustainably use the oceans, seas and marine resources."
goal_15:
title: "Life on Land"
description: "Sustainably manage forests, combat desertification, halt and reverse land degradation, halt biodiversity loss."
goal_16:
title: "Peace, Justice and Strong Institution"
description: "Promote just, peaceful and inclusive societies."
goal_17:
title: "Partnerships For the Goals"
description: "Revitalize the global partnership for Sustainable Development."

View File

@@ -0,0 +1,6 @@
en:
sdg_management:
header:
title: "SDG content"
menu:
sdg_content: "Goals and Targets"

View File

@@ -72,6 +72,9 @@ es:
proposal:
one: "Propuesta ciudadana"
other: "Propuestas ciudadanas"
sdg/goal:
one: "objetivo"
other: "objetivos"
site_customization/page:
one: Página
other: Páginas
@@ -305,6 +308,10 @@ es:
proposal_notification:
body: "Mensaje"
title: "Título"
sdg/goal:
code: "Código"
title: "Título"
description: "Descripción"
signature_sheet:
title: "Título"
signable_type: "Tipo de hoja de firmas"

54
config/locales/es/sdg.yml Normal file
View File

@@ -0,0 +1,54 @@
es:
sdg:
goals:
goal_1:
title: "Fin de la pobreza"
description: "Poner fin a la pobreza en todas sus formas en todo el mundo."
goal_2:
title: "Hambre Cero"
description: "Poner fin al hambre."
goal_3:
title: "Salud y Bienestar"
description: "Garantizar una vida sana y promover el bienestar para todos en todas las edades."
goal_4:
title: "Educación de Calidad"
description: "Garantizar una educación inclusiva, equitativa y de calidad y promover oportunidades de aprendizaje durante toda la vida para todos."
goal_5:
title: "Igualdad de Género"
description: "Lograr la igualdad entre los géneros y empoderar a todas las mujeres y las niñas."
goal_6:
title: "Agua Limpia y Saneamiento"
description: "Garantizar la disponibilidad de agua y su gestión sostenible y el saneamiento para todos."
goal_7:
title: "Energía Sostenible y No Contaminante"
description: "Garantizar el acceso a una energía asequible, segura, sostenible y moderna."
goal_8:
title: "Trabajo Decente y Crecimiento Económico"
description: "Promover el crecimiento económico inclusivo y sostenible, el empleo y el trabajo decente para todos."
goal_9:
title: "Industria, Innovación e Infraestructuras"
description: "Construir infraestructuras resilientes, promover la industrialización sostenible y fomentar la innovación."
goal_10:
title: "Reducción de las Desigualdades"
description: "Reducir la desigualdad en y entre los países."
goal_11:
title: "Ciudades y Comunidades Sostenibles"
description: "Lograr que las ciudades sean más inclusivas, seguras, resilientes y sostenibles."
goal_12:
title: "Producción y Consumo Responsables"
description: "Garantizar modalidades de consumo y producción sostenibles"
goal_13:
title: "Acción Por el Clima"
description: "Adoptar medidas urgentes para combatir el cambio climático y sus efectos."
goal_14:
title: "Vida Submarina"
description: "Conservar y utilizar sosteniblemente los océanos, los mares y los recursos marinos."
goal_15:
title: "Vida de Ecosistemas Terrestres"
description: "Gestionar sosteniblemente los bosques, luchar contra la desertificación, detener e invertir la degradación de las tierras, detener la pérdida de biodiversidad."
goal_16:
title: "Paz, Justicia e Instituciones Sólidas"
description: "Promover sociedades justas, pacíficas e inclusivas."
goal_17:
title: "Alianzas para Lograr los Objetivos"
description: "Revitalizar la Alianza Mundial para el Desarrollo Sostenible."

View File

@@ -0,0 +1,6 @@
es:
sdg_management:
header:
title: "Contenido ODS"
menu:
sdg_content: "Objetivos y Metas"

View File

@@ -21,6 +21,7 @@ Rails.application.routes.draw do
draw :poll
draw :proposal
draw :related_content
draw :sdg_management
draw :tag
draw :user
draw :valuation

View File

@@ -0,0 +1,5 @@
namespace :sdg_management do
root to: "goals#index"
resources :goals, only: [:index]
end

View File

@@ -43,5 +43,6 @@ require_relative "dev_seeds/admin_notifications"
require_relative "dev_seeds/legislation_proposals"
require_relative "dev_seeds/milestones"
require_relative "dev_seeds/pages"
require_relative "dev_seeds/sdg"
log "All dev seeds created successfuly 👍"

3
db/dev_seeds/sdg.rb Normal file
View File

@@ -0,0 +1,3 @@
section "Creating Sustainable Development Goals" do
load Rails.root.join("db", "sdg.rb")
end

View File

@@ -0,0 +1,10 @@
class CreateSDGGoals < ActiveRecord::Migration[5.2]
def change
create_table :sdg_goals do |t|
t.integer :code, null: false
t.timestamps
t.index :code, unique: true
end
end
end

View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_09_08_084257) do
ActiveRecord::Schema.define(version: 2020_11_11_095452) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -1297,6 +1297,13 @@ ActiveRecord::Schema.define(version: 2020_09_08_084257) do
t.index ["process_type", "process_id"], name: "index_reports_on_process_type_and_process_id"
end
create_table "sdg_goals", force: :cascade do |t|
t.integer "code", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["code"], name: "index_sdg_goals_on_code", unique: true
end
create_table "settings", id: :serial, force: :cascade do |t|
t.string "key"
t.string "value"

3
db/sdg.rb Normal file
View File

@@ -0,0 +1,3 @@
(1..17).each do |code|
SDG::Goal.where(code: code).first_or_create!
end

View File

@@ -16,3 +16,6 @@ WebSection.where(name: "help_page").first_or_create!
# Default custom pages
load Rails.root.join("db", "pages.rb")
# Sustainable Development Goals
load Rails.root.join("db", "sdg.rb")

View File

@@ -1,5 +1,11 @@
namespace :consul do
desc "Runs tasks needed to upgrade to the latest version"
task execute_release_tasks: ["settings:rename_setting_keys",
"settings:add_new_settings"]
"settings:add_new_settings",
"execute_release_1.3.0_tasks"]
desc "Runs tasks needed to upgrade from 1.2.0 to 1.3.0"
task "execute_release_1.3.0_tasks": [
"db:load_sdg"
]
end

View File

@@ -4,4 +4,10 @@ namespace :db do
@avoid_log = args[:print_log] == "avoid_log"
load(Rails.root.join("db", "dev_seeds.rb"))
end
desc "Load SDG content into database"
task load_sdg: :environment do
ApplicationLogger.new.info "Adding Sustainable Development Goals content"
load(Rails.root.join("db", "sdg.rb"))
end
end

5
spec/factories/sdg.rb Normal file
View File

@@ -0,0 +1,5 @@
FactoryBot.define do
factory :sdg_goal, class: "SDG::Goal" do
sequence(:code) { |n| n }
end
end

View File

@@ -0,0 +1,28 @@
require "rails_helper"
describe "rake db:load_sdg" do
before { Rake::Task["db:load_sdg"].reenable }
let :run_rake_task do
Rake.application.invoke_task("db:load_sdg")
end
it "populates empty databases correctly" do
SDG::Goal.destroy_all
run_rake_task
expect(SDG::Goal.count).to eq 17
end
it "does not create additional records on populated databases" do
expect(SDG::Goal.count).to eq 17
goal_id = SDG::Goal.last.id
run_rake_task
expect(SDG::Goal.count).to eq 17
expect(SDG::Goal.last.id).to eq goal_id
end
end

View File

@@ -0,0 +1,53 @@
require "rails_helper"
describe SDG::Goal do
describe "validations" do
it "is valid with an existent code" do
goal = SDG::Goal[1]
expect(goal).to be_valid
end
it "is not valid without a code" do
expect(build(:sdg_goal, code: nil)).not_to be_valid
end
it "is not valid with a nonexistent code" do
[0, 18].each do |code|
goal = SDG::Goal.where(code: code).first_or_initialize
expect(goal).not_to be_valid
end
end
end
describe ".[]" do
it "finds existing goals by code" do
expect(SDG::Goal[1].code).to be 1
end
it "raises an exception for non-existing codes" do
expect { SDG::Goal[100] }.to raise_exception ActiveRecord::RecordNotFound
end
end
it "translates title" do
goal = SDG::Goal[1]
expect(goal.title).to eq "No Poverty"
I18n.with_locale(:es) do
expect(goal.title).to eq "Fin de la pobreza"
end
end
it "translates description" do
goal = SDG::Goal[1]
expect(goal.description).to eq "End poverty in all its forms, everywhere."
I18n.with_locale(:es) do
expect(goal.description).to eq "Poner fin a la pobreza en todas sus formas en todo el mundo."
end
end
end

View File

@@ -0,0 +1,18 @@
require "rails_helper"
describe "Goals", :js do
before { login_as(create(:administrator).user) }
describe "Index" do
scenario "Visit the index" do
visit sdg_management_root_path
within("#side_menu") do
click_link "Goals and Targets"
end
expect(page).to have_title "SDG content - Goals"
within("table") { expect(page).to have_content "No Poverty" }
end
end
end

19
vendor/assets/images/sdg.svg vendored Normal file
View File

@@ -0,0 +1,19 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150"><!-- Based on https://en.wikipedia.org/wiki/File:SustainableDevelopmentGoalsLogo.svg -->
<path d="m41.378644,55.666441c1.7345,-2.9481 3.8376,-5.6483 6.2519,-8.0373 l -20.497,-22.473c-5.1528,4.924 -9.5494,10.636 -13.012,16.932z" fill="#56c02b" />
<path d="m91.618644,39.866441c3.1006,1.4232 5.9914,3.234 8.596396,5.3815 l 20.548,-22.434c-5.4133,-4.6699 -11.551,-8.5202 -18.216,-11.367z" fill="#dda83a" />
<path d="m138.67864,46.566441 -27.238,13.578c1.3025,3.037 2.2238,6.2583 2.7257,9.6257 l 30.3,-2.8591c-0.89586,-7.1732 -2.8782,-14.016 -5.7881,-20.344" fill="#c5192d" />
<path d="m109.48864,56.266441 27.231,-13.578c-3.3738,-6.2647 -7.6751,-11.964 -12.726,-16.894 l -20.548,22.428c2.3381,2.408 4.3776,5.1082 6.0423,8.0436" fill="#4c9f38" />
<path d="m35.968644,75.566441c0,-0.6099 0.0191,-1.2262 0.0508,-1.8362 l -30.3069999,-2.713c-0.0953,1.5058 -0.15249,3.018 -0.15249,4.5492 0,5.8135 0.71796,11.462 2.0586,16.856 l 29.2709999,-8.3995c-0.59724,-2.7257 -0.92127,-5.553 -0.92127,-8.4566" fill="#3f7e44" />
<path d="m105.67864,100.46644c-2.1539,2.624 -4.6381,4.9558 -7.389196,6.9508 l 15.997996,25.91c5.9406,-4.0219 11.227,-8.9395 15.668,-14.55z" fill="#fcc30b" />
<path d="m114.59864,75.566441c0,2.8718 -0.30497,5.6674 -0.90221,8.3613 l 29.271,8.4058c1.3343,-5.3688 2.0395,-10.985 2.0395,-16.767 0,-1.4359 -0.0445,-2.8591 -0.13342,-4.2823 l -30.3,2.8654c0.0127,0.4766 0.0254,0.9404 0.0254,1.4169" fill="#ff3a21" />
<path d="m45.378644,101.06644 -24.22,18.413c4.5047,5.5467 9.8354,10.382 15.814,14.327 l 15.998,-25.878c-2.8146,-1.9506 -5.3688,-4.2633 -7.5925,-6.8619" fill="#fd9d24" />
<path d="m36.458644,69.366441c0.54006,-3.4246 1.5376,-6.6967 2.9036,-9.7591 l -27.225,-13.565c-3.0115999,6.398 -5.0764999,13.33 -6.0104999,20.605z" fill="#0a97d9" />
<path d="m110.56864,135.66644 -15.978996,-25.872c-2.9036,1.6392 -6.0296,2.9226 -9.3207,3.7867 l 5.6356,29.932c7.0144,-1.6138 13.634996,-4.2887 19.663996,-7.8467" fill="#a21942" />
<path d="m112.52864,88.166441c-1.061,3.1133 -2.4906,6.0486 -4.2506,8.7616 l 24.296,18.323999c3.9456,-5.6674 7.0652,-11.951 9.1936,-18.679999z" fill="#26bde2" />
<path d="m80.948644,114.46644c-1.8489,0.2669 -3.7423,0.413 -5.6674,0.413 -1.5503,0 -3.0751,-0.095 -4.5809,-0.2732 l -5.6356,29.932c3.3356,0.4893 6.7475,0.7498 10.217,0.7498 3.8439,0 7.6243,-0.3177 11.303,-0.915z" fill="#fd6925" />
<path d="m77.798644,36.366441c3.3801,0.216 6.6395,0.8577 9.7273,1.8807 l 10.935,-28.4070003c-6.5061,-2.3 -13.444,-3.6597 -20.662,-3.9138z" fill="#e5243b" />
<path d="m66.378644,113.86644c-3.4055,-0.7942 -6.6459,-2.0331 -9.6511,-3.647 l -16.011,25.891c6.163,3.5263 12.898,6.1312 20.033,7.6561z" fill="#dd1367" />
<path d="m63.468644,38.066441c3.1577,-0.9975 6.487,-1.6075 9.9307,-1.7663 V 5.8661407c-7.313,0.1906 -14.346,1.5249 -20.935,3.8122z" fill="#19486a" />
<path d="m42.718644,97.566441c-1.9315,-2.8528 -3.5072,-5.9724 -4.6381,-9.2953 l -29.2519999,8.3931c2.2173999,6.976199 5.5021999,13.475999 9.6637999,19.314999z" fill="#bf8b2e" />
<path d="m50.928644,44.766441c2.5732,-2.0331 5.4006,-3.7486 8.4312,-5.1019 l -10.998,-28.375c-6.5506,2.7511 -12.586,6.4743 -17.943,10.992z" fill="#00689d" />
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB