diff --git a/.rubocop_basic.yml b/.rubocop_basic.yml index 687429ca0..cebf55084 100644 --- a/.rubocop_basic.yml +++ b/.rubocop_basic.yml @@ -35,3 +35,6 @@ Metrics/LineLength: RSpec/NotToNot: Enabled: true + +Style/StringLiterals: + EnforcedStyle: double_quotes diff --git a/.scss-lint.yml b/.scss-lint.yml index dfa46907b..d2d024576 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -175,7 +175,7 @@ linters: StringQuotes: enabled: true - style: single_quotes + style: double_quotes TrailingSemicolon: enabled: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 955ffc300..3121f2670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,30 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html) +## [0.18.1](https://github.com/consul/consul/tree/v0.18.1) (2019-01-17) + +### Added + +- **Legislation:** Legislation process homepage phase [\#3188](https://github.com/consul/consul/pull/3188) +- **Legislation:** Show documents on processes proposals phase [\#3136](https://github.com/consul/consul/pull/3136) +- **Maintenance-Refactorings:** Remove semicolons from controllers [\#3160](https://github.com/consul/consul/pull/3160) +- **Maintenance-Refactorings:** Remove before action not used [\#3167](https://github.com/consul/consul/pull/3167) +- **Maintenance-Rubocop:** Enable double quotes rubocop rule [\#3175](https://github.com/consul/consul/pull/3175) +- **Maintenance-Rubocop:** Enable line length rubocop rule [\#3165](https://github.com/consul/consul/pull/3165) +- **Maintenance-Rubocop:** Add rubocop rule to indent private methods [\#3134](https://github.com/consul/consul/pull/3134) + +### Changed + +- **Admin:** Improve CRUD budgets and content blocks [\#3173](https://github.com/consul/consul/pull/3173) +- **Design/UX:** new CRUD budgets, content blocks and heading map [\#3150](https://github.com/consul/consul/pull/3150) +- **Design/UX:** Processes key dates [\#3137](https://github.com/consul/consul/pull/3137) + +### Fixed + +- **Admin:** checks for deleted proposals [\#3154](https://github.com/consul/consul/pull/3154) +- **Admin:** Add default order for admin budget investments list [\#3151](https://github.com/consul/consul/pull/3151) +- **Budgets:** Bug Management Cannot create Budget Investment without a map location [\#3133](https://github.com/consul/consul/pull/3133) + ## [0.18.0](https://github.com/consul/consul/compare/v0.17...v0.18) (2018-12-27) ### Added @@ -47,6 +71,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - **Admin:** Improve visualization for small resolution [\#3025](https://github.com/consul/consul/pull/3025) - **Admin:** Budgets admin [\#3012](https://github.com/consul/consul/pull/3012) - **Budgets:** Budget investments social share [\#3053](https://github.com/consul/consul/pull/3053) +- **Design/UX:** Documents title [\#3131](https://github.com/consul/consul/pull/3131) - **Design/UX:** Proposal create question [\#3122](https://github.com/consul/consul/pull/3122) - **Design/UX:** Budget investments price explanation [\#3121](https://github.com/consul/consul/pull/3121) - **Design/UX:** Change CRUD for budget groups and headings [\#3106](https://github.com/consul/consul/pull/3106) diff --git a/Gemfile b/Gemfile index f5c8b3f70..ab26b135a 100644 --- a/Gemfile +++ b/Gemfile @@ -54,6 +54,7 @@ gem 'unicorn', '~> 5.4.1' gem 'whenever', '~> 0.10.0', require: false gem 'globalize', '~> 5.0.0' gem 'globalize-accessors', '~> 0.2.1' +gem 'recipient_interceptor', '~> 0.2.0' source 'https://rails-assets.org' do gem 'rails-assets-leaflet' diff --git a/Gemfile.lock b/Gemfile.lock index 64a662dd4..f60d15f15 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -356,6 +356,8 @@ GEM rainbow (3.0.0) raindrops (0.19.0) rake (12.3.1) + recipient_interceptor (0.2.0) + mail redcarpet (3.4.0) referer-parser (0.3.0) request_store (1.3.2) @@ -551,6 +553,7 @@ DEPENDENCIES rails (= 4.2.11) rails-assets-leaflet! rails-assets-markdown-it (~> 8.2.1)! + recipient_interceptor (~> 0.2.0) redcarpet (~> 3.4.0) responders (~> 2.4.0) rinku (~> 2.0.2) diff --git a/app/assets/images/map.jpg b/app/assets/images/map.jpg index 0b3ad3516..b35490b52 100644 Binary files a/app/assets/images/map.jpg and b/app/assets/images/map.jpg differ diff --git a/app/assets/javascripts/forms.js.coffee b/app/assets/javascripts/forms.js.coffee index edf4c525f..1bda27b2e 100644 --- a/app/assets/javascripts/forms.js.coffee +++ b/app/assets/javascripts/forms.js.coffee @@ -23,8 +23,36 @@ App.Forms = false ) + synchronizeInputs: -> + progress_bar = "[name='progress_bar[percentage]']" + process_background = "[name='legislation_process[background_color]']" + process_font = "[name='legislation_process[font_color]']" + + inputs = $("#{progress_bar}, #{process_background}, #{process_font}") + inputs.on + input: -> + $("[name='#{this.name}']").val($(this).val()) + + inputs.trigger("input") + + hideOrShowFieldsAfterSelection: -> + $("[name='progress_bar[kind]']").on + change: -> + title_field = $("[name^='progress_bar'][name$='[title]']").parent() + + if this.value == "primary" + title_field.hide() + $("#globalize_locales").hide() + else + title_field.show() + $("#globalize_locales").show() + + $("[name='progress_bar[kind]']").change() + initialize: -> App.Forms.disableEnter() App.Forms.submitOnChange() App.Forms.toggleLink() + App.Forms.synchronizeInputs() + App.Forms.hideOrShowFieldsAfterSelection() false diff --git a/app/assets/javascripts/tags.js.coffee b/app/assets/javascripts/tags.js.coffee index 6e3c7165c..e641203f7 100644 --- a/app/assets/javascripts/tags.js.coffee +++ b/app/assets/javascripts/tags.js.coffee @@ -8,7 +8,7 @@ App.Tags = unless $this.data('initialized') is 'yes' $this.on('click', -> - name = $(this).text() + name = '"' + $(this).text() + '"' current_tags = $tag_input.val().split(',').filter(Boolean) if $.inArray(name, current_tags) >= 0 diff --git a/app/assets/stylesheets/_consul_settings.scss b/app/assets/stylesheets/_consul_settings.scss index 4a083bb62..d92b90301 100644 --- a/app/assets/stylesheets/_consul_settings.scss +++ b/app/assets/stylesheets/_consul_settings.scss @@ -71,7 +71,7 @@ $color-alert: #a94442; $black: #222; $white: #fff; -$body-font-family: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif !important; +$body-font-family: "Source Sans Pro", "Helvetica", "Arial", sans-serif !important; $header-font-family: $body-font-family; @@ -79,24 +79,24 @@ $global-radius: rem-calc(3); $button-radius: $global-radius; -$font-family-serif: Georgia, 'Times New Roman', Times, serif; +$font-family-serif: Georgia, "Times New Roman", Times, serif; $header-styles: ( small: ( - 'h1': ('font-size': 34), - 'h2': ('font-size': 24), - 'h3': ('font-size': 20), - 'h4': ('font-size': 18), - 'h5': ('font-size': 16), - 'h6': ('font-size': 14), + "h1": ("font-size": 34), + "h2": ("font-size": 24), + "h3": ("font-size": 20), + "h4": ("font-size": 18), + "h5": ("font-size": 16), + "h6": ("font-size": 14), ), medium: ( - 'h1': ('font-size': 44), - 'h2': ('font-size': 34), - 'h3': ('font-size': 24), - 'h4': ('font-size': 19), - 'h5': ('font-size': 16), - 'h6': ('font-size': 13), + "h1": ("font-size": 44), + "h2": ("font-size": 34), + "h3": ("font-size": 24), + "h4": ("font-size": 19), + "h5": ("font-size": 16), + "h6": ("font-size": 13), ), ); diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss index 296cccde6..305ca3d64 100644 --- a/app/assets/stylesheets/_settings.scss +++ b/app/assets/stylesheets/_settings.scss @@ -60,7 +60,7 @@ // 55. Top Bar // 56. Xy Grid -@import 'util/util'; +@import "util/util"; // 1. Global // --------- @@ -82,7 +82,7 @@ $black: #0a0a0a; $white: #fefefe; $body-background: $white; $body-font-color: $black; -$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; +$body-font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; $body-antialiased: true; $global-margin: 1rem; $global-padding: 1rem; @@ -124,7 +124,7 @@ $grid-column-gutter: ( medium: 30px, ); $grid-column-align-edge: true; -$grid-column-alias: 'columns'; +$grid-column-alias: "columns"; $block-grid-max: 8; // 4. Base Typography @@ -133,26 +133,26 @@ $block-grid-max: 8; $header-font-family: $body-font-family; $header-font-weight: $global-weight-normal; $header-font-style: normal; -$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; +$font-family-monospace: Consolas, "Liberation Mono", Courier, monospace; $header-color: inherit; $header-lineheight: 1.4; $header-margin-bottom: 0.5rem; $header-styles: ( small: ( - 'h1': ('font-size': 24), - 'h2': ('font-size': 20), - 'h3': ('font-size': 19), - 'h4': ('font-size': 18), - 'h5': ('font-size': 17), - 'h6': ('font-size': 16), + "h1": ("font-size": 24), + "h2": ("font-size": 20), + "h3": ("font-size": 19), + "h4": ("font-size": 18), + "h5": ("font-size": 17), + "h6": ("font-size": 16), ), medium: ( - 'h1': ('font-size': 48), - 'h2': ('font-size': 40), - 'h3': ('font-size': 31), - 'h4': ('font-size': 25), - 'h5': ('font-size': 20), - 'h6': ('font-size': 16), + "h1": ("font-size": 48), + "h2": ("font-size": 40), + "h3": ("font-size": 31), + "h4": ("font-size": 25), + "h5": ("font-size": 20), + "h6": ("font-size": 16), ), ); $header-text-rendering: optimizeLegibility; @@ -188,7 +188,7 @@ $blockquote-padding: rem-calc(9 20 0 19); $blockquote-border: 1px solid $medium-gray; $cite-font-size: rem-calc(13); $cite-color: $dark-gray; -$cite-pseudo-content: '\2014 \0020'; +$cite-pseudo-content: "\2014 \0020"; $keystroke-font: $font-family-monospace; $keystroke-color: $black; $keystroke-background: $light-gray; @@ -271,8 +271,8 @@ $breadcrumbs-item-color-disabled: $medium-gray; $breadcrumbs-item-margin: 0.75rem; $breadcrumbs-item-uppercase: true; $breadcrumbs-item-separator: true; -$breadcrumbs-item-separator-item: '/'; -$breadcrumbs-item-separator-item-rtl: '\\'; +$breadcrumbs-item-separator-item: "/"; +$breadcrumbs-item-separator-item-rtl: "\\"; $breadcrumbs-item-separator-color: $medium-gray; // 11. Button @@ -305,7 +305,7 @@ $button-transition: background-color 0.25s ease-out, color 0.25s ease-out; $buttongroup-margin: 1rem; $buttongroup-spacing: 1px; -$buttongroup-child-selector: '.button'; +$buttongroup-child-selector: ".button"; $buttongroup-expand-max: 6; $buttongroup-radius-on-each: true; @@ -511,7 +511,7 @@ $offcanvas-transition-length: 0.5s; $offcanvas-transition-timing: ease; $offcanvas-fixed-reveal: true; $offcanvas-exit-background: rgba($white, 0.25); -$maincontent-class: 'off-canvas-content'; +$maincontent-class: "off-canvas-content"; // 26. Orbit // --------- diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index f08d14fda..77032d155 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -251,6 +251,13 @@ $sidebar-active: #f4fcd0; max-width: none; } + form { + + .input-group-label { + height: $line-height * 2; + } + } + .menu.simple { margin-bottom: $line-height / 2; @@ -424,7 +431,7 @@ $sidebar-active: #f4fcd0; > a::after { border: 0; - content: '\61' !important; + content: "\61" !important; font-family: "icons" !important; height: auto; position: absolute !important; @@ -1106,7 +1113,7 @@ table { } .map-icon::after { - content: ''; + content: ""; width: 14px; height: 14px; margin: 8px 0 0 8px; @@ -1166,7 +1173,7 @@ table { &.enabled::before, &.disabled::before { - font-family: 'icons'; + font-family: "icons"; left: 0; position: absolute; } @@ -1176,7 +1183,7 @@ table { &::before { color: $check; - content: '\6c'; + content: "\6c"; } } @@ -1185,7 +1192,7 @@ table { &::before { color: #000; - content: '\76'; + content: "\76"; } } } diff --git a/app/assets/stylesheets/annotator_overrides.scss b/app/assets/stylesheets/annotator_overrides.scss index fcc127ecd..0bdb28ade 100644 --- a/app/assets/stylesheets/annotator_overrides.scss +++ b/app/assets/stylesheets/annotator_overrides.scss @@ -14,7 +14,7 @@ } .annotator-adder { - background-image: image-url('annotator_adder.png'); + background-image: image-url("annotator_adder.png"); margin-top: -52px; } @@ -43,7 +43,7 @@ .annotator-widget::after, .annotator-editor.annotator-invert-y .annotator-widget::after { - background-image: image-url('annotator_items.png'); + background-image: image-url("annotator_items.png"); } .annotator-editor a, diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 3f93ffa6b..d783dea37 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,22 +1,23 @@ -@import 'social-share-button'; -@import 'foundation_and_overrides'; -@import 'fonts'; -@import 'icons'; -@import 'mixins'; -@import 'admin'; -@import 'layout'; -@import 'participation'; -@import 'pages'; -@import 'legislation'; -@import 'legislation_process'; -@import 'community'; -@import 'custom'; -@import 'c3'; -@import 'annotator.min'; -@import 'annotator_overrides'; -@import 'jquery-ui/datepicker'; -@import 'datepicker_overrides'; -@import 'jquery-ui/autocomplete'; -@import 'autocomplete_overrides'; -@import 'jquery-ui/sortable'; -@import 'leaflet'; +@import "social-share-button"; +@import "foundation_and_overrides"; +@import "fonts"; +@import "icons"; +@import "mixins"; +@import "admin"; +@import "layout"; +@import "participation"; +@import "milestones"; +@import "pages"; +@import "legislation"; +@import "legislation_process"; +@import "community"; +@import "custom"; +@import "c3"; +@import "annotator.min"; +@import "annotator_overrides"; +@import "jquery-ui/datepicker"; +@import "datepicker_overrides"; +@import "jquery-ui/autocomplete"; +@import "autocomplete_overrides"; +@import "jquery-ui/sortable"; +@import "leaflet"; diff --git a/app/assets/stylesheets/datepicker_overrides.scss b/app/assets/stylesheets/datepicker_overrides.scss index 33c611d1c..6082592a3 100644 --- a/app/assets/stylesheets/datepicker_overrides.scss +++ b/app/assets/stylesheets/datepicker_overrides.scss @@ -51,11 +51,11 @@ } .ui-datepicker-prev::after { - content: '\62'; + content: "\62"; } .ui-datepicker-next::after { - content: '\63'; + content: "\63"; } table { diff --git a/app/assets/stylesheets/fonts.scss b/app/assets/stylesheets/fonts.scss index 61429e800..83ce4b078 100644 --- a/app/assets/stylesheets/fonts.scss +++ b/app/assets/stylesheets/fonts.scss @@ -8,88 +8,88 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - @font-face { - font-family: 'Source Sans Pro'; + font-family: "Source Sans Pro"; font-style: normal; font-weight: 300; - src: font-url('sourcesanspro-light-webfont.eot'); - src: font-url('sourcesanspro-light-webfont.eot?#iefix') format('embedded-opentype'), - font-url('sourcesanspro-light-webfont.woff2') format('woff2'), - font-url('sourcesanspro-light-webfont.woff') format('woff'), - font-url('sourcesanspro-light-webfont.ttf') format('truetype'), - font-url('sourcesanspro-light-webfont.svg#source_sans_prolight') format('svg'); + src: font-url("sourcesanspro-light-webfont.eot"); + src: font-url("sourcesanspro-light-webfont.eot?#iefix") format("embedded-opentype"), + font-url("sourcesanspro-light-webfont.woff2") format("woff2"), + font-url("sourcesanspro-light-webfont.woff") format("woff"), + font-url("sourcesanspro-light-webfont.ttf") format("truetype"), + font-url("sourcesanspro-light-webfont.svg#source_sans_prolight") format("svg"); } @font-face { - font-family: 'Source Sans Pro'; + font-family: "Source Sans Pro"; font-style: normal; font-weight: 400; - src: font-url('sourcesanspro-regular-webfont.eot'); - src: font-url('sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'), - font-url('sourcesanspro-regular-webfont.woff2') format('woff2'), - font-url('sourcesanspro-regular-webfont.woff') format('woff'), - font-url('sourcesanspro-regular-webfont.ttf') format('truetype'), - font-url('sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg'); + src: font-url("sourcesanspro-regular-webfont.eot"); + src: font-url("sourcesanspro-regular-webfont.eot?#iefix") format("embedded-opentype"), + font-url("sourcesanspro-regular-webfont.woff2") format("woff2"), + font-url("sourcesanspro-regular-webfont.woff") format("woff"), + font-url("sourcesanspro-regular-webfont.ttf") format("truetype"), + font-url("sourcesanspro-regular-webfont.svg#source_sans_proregular") format("svg"); } @font-face { - font-family: 'Source Sans Pro'; + font-family: "Source Sans Pro"; font-style: italic; font-weight: 400; - src: font-url('sourcesanspro-italic-webfont.eot'); - src: font-url('sourcesanspro-italic-webfont.eot?#iefix') format('embedded-opentype'), - font-url('sourcesanspro-italic-webfont.woff2') format('woff2'), - font-url('sourcesanspro-italic-webfont.woff') format('woff'), - font-url('sourcesanspro-italic-webfont.ttf') format('truetype'), - font-url('sourcesanspro-italic-webfont.svg#source_sans_proitalic') format('svg'); + src: font-url("sourcesanspro-italic-webfont.eot"); + src: font-url("sourcesanspro-italic-webfont.eot?#iefix") format("embedded-opentype"), + font-url("sourcesanspro-italic-webfont.woff2") format("woff2"), + font-url("sourcesanspro-italic-webfont.woff") format("woff"), + font-url("sourcesanspro-italic-webfont.ttf") format("truetype"), + font-url("sourcesanspro-italic-webfont.svg#source_sans_proitalic") format("svg"); } @font-face { - font-family: 'Source Sans Pro'; + font-family: "Source Sans Pro"; font-style: normal; font-weight: 700; - src: font-url('sourcesanspro-bold-webfont.eot'); - src: font-url('sourcesanspro-bold-webfont.eot?#iefix') format('embedded-opentype'), - font-url('sourcesanspro-bold-webfont.woff2') format('woff2'), - font-url('sourcesanspro-bold-webfont.woff') format('woff'), - font-url('sourcesanspro-bold-webfont.ttf') format('truetype'), - font-url('sourcesanspro-bold-webfont.svg#source_sans_probold') format('svg'); + src: font-url("sourcesanspro-bold-webfont.eot"); + src: font-url("sourcesanspro-bold-webfont.eot?#iefix") format("embedded-opentype"), + font-url("sourcesanspro-bold-webfont.woff2") format("woff2"), + font-url("sourcesanspro-bold-webfont.woff") format("woff"), + font-url("sourcesanspro-bold-webfont.ttf") format("truetype"), + font-url("sourcesanspro-bold-webfont.svg#source_sans_probold") format("svg"); } // 02. Lato // - - - - - - - - - - - - - - - - - - - - - - - - - @font-face { - font-family: 'Lato'; - src: font-url('lato-light.eot'); - src: font-url('lato-light.eot?#iefix') format('embedded-opentype'), - font-url('lato-light.woff2') format('woff2'), - font-url('lato-light.woff') format('woff'), - font-url('lato-light.ttf') format('truetype'), - font-url('lato-light.svg#latolight') format('svg'); + font-family: "Lato"; + src: font-url("lato-light.eot"); + src: font-url("lato-light.eot?#iefix") format("embedded-opentype"), + font-url("lato-light.woff2") format("woff2"), + font-url("lato-light.woff") format("woff"), + font-url("lato-light.ttf") format("truetype"), + font-url("lato-light.svg#latolight") format("svg"); font-weight: lighter; font-style: normal; } @font-face { - font-family: 'Lato'; - src: font-url('lato-regular.eot'); - src: font-url('lato-regular.eot?#iefix') format('embedded-opentype'), - font-url('lato-regular.woff2') format('woff2'), - font-url('lato-regular.woff') format('woff'), - font-url('lato-regular.ttf') format('truetype'), - font-url('lato-regular.svg#latoregular') format('svg'); + font-family: "Lato"; + src: font-url("lato-regular.eot"); + src: font-url("lato-regular.eot?#iefix") format("embedded-opentype"), + font-url("lato-regular.woff2") format("woff2"), + font-url("lato-regular.woff") format("woff"), + font-url("lato-regular.ttf") format("truetype"), + font-url("lato-regular.svg#latoregular") format("svg"); font-weight: normal; font-style: normal; } @font-face { - font-family: 'Lato'; - src: font-url('lato-bold.eot'); - src: font-url('lato-bold.eot?#iefix') format('embedded-opentype'), - font-url('lato-bold.woff2') format('woff2'), - font-url('lato-bold.woff') format('woff'), - font-url('lato-bold.ttf') format('truetype'), - font-url('lato-bold.svg#latobold') format('svg'); + font-family: "Lato"; + src: font-url("lato-bold.eot"); + src: font-url("lato-bold.eot?#iefix") format("embedded-opentype"), + font-url("lato-bold.woff2") format("woff2"), + font-url("lato-bold.woff") format("woff"), + font-url("lato-bold.ttf") format("truetype"), + font-url("lato-bold.svg#latobold") format("svg"); font-weight: bold; font-style: normal; } diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss index 99e77f57d..c4fa6944e 100644 --- a/app/assets/stylesheets/foundation_and_overrides.scss +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -1,11 +1,11 @@ -@charset 'utf-8'; +@charset "utf-8"; -@import 'settings'; -@import 'consul_settings'; -@import 'custom_settings'; -@import 'foundation'; +@import "settings"; +@import "consul_settings"; +@import "custom_settings"; +@import "foundation"; -@import 'motion-ui/motion-ui'; +@import "motion-ui/motion-ui"; @include foundation-global-styles; // @include foundation-xy-grid-classes; diff --git a/app/assets/stylesheets/icons.scss b/app/assets/stylesheets/icons.scss index 3d97084f4..44f35d62a 100644 --- a/app/assets/stylesheets/icons.scss +++ b/app/assets/stylesheets/icons.scss @@ -1,12 +1,12 @@ @charset "UTF-8"; @font-face { - font-family: 'icons'; - src: font-url('icons.eot'); - src: font-url('icons.eot?#iefix') format('embedded-opentype'), - font-url('icons.woff') format('woff'), - font-url('icons.ttf') format('truetype'), - font-url('icons.svg#icons') format('svg'); + font-family: "icons"; + src: font-url("icons.eot"); + src: font-url("icons.eot?#iefix") format("embedded-opentype"), + font-url("icons.woff") format("woff"), + font-url("icons.ttf") format("truetype"), + font-url("icons.svg#icons") format("svg"); font-weight: normal; font-style: normal; } @@ -38,257 +38,257 @@ } .icon-angle-down::before { - content: '\61'; + content: "\61"; } .icon-angle-left::before { - content: '\62'; + content: "\62"; } .icon-angle-right::before { - content: '\63'; + content: "\63"; } .icon-angle-up::before { - content: '\64'; + content: "\64"; } .icon-comments::before { - content: '\65'; + content: "\65"; } .icon-twitter::before { - content: '\66'; + content: "\66"; } .icon-calendar::before { - content: '\67'; + content: "\67"; } .icon-debates::before { - content: '\69'; + content: "\69"; } .icon-unlike::before { - content: '\6a'; + content: "\6a"; } .icon-like::before { - content: '\6b'; + content: "\6b"; } .icon-check::before { - content: '\6c'; + content: "\6c"; } .icon-edit::before { - content: '\6d'; + content: "\6d"; } .icon-user::before { - content: '\6f'; + content: "\6f"; } .icon-settings::before { - content: '\71'; + content: "\71"; } .icon-stats::before { - content: '\72'; + content: "\72"; } .icon-proposals::before { - content: '\68'; + content: "\68"; } .icon-organizations::before { - content: '\73'; + content: "\73"; } .icon-deleted::before { - content: '\74'; + content: "\74"; } .icon-tag::before { - content: '\75'; + content: "\75"; } .icon-eye::before { - content: '\70'; + content: "\70"; } .icon-x::before { - content: '\76'; + content: "\76"; } .icon-flag::before { - content: '\77'; + content: "\77"; } .icon-comment::before { - content: '\79'; + content: "\79"; } .icon-reply::before { - content: '\7a'; + content: "\7a"; } .icon-facebook::before { - content: '\41'; + content: "\41"; } .icon-google-plus::before { - content: '\42'; + content: "\42"; } .icon-search::before { - content: '\45'; + content: "\45"; } .icon-external::before { - content: '\46'; + content: "\46"; } .icon-video::before { - content: '\44'; + content: "\44"; } .icon-document::before { - content: '\47'; + content: "\47"; } .icon-print::before { - content: '\48'; + content: "\48"; } .icon-blog::before { - content: '\4a'; + content: "\4a"; } .icon-box::before { - content: '\49'; + content: "\49"; } .icon-youtube::before { - content: '\4b'; + content: "\4b"; } .icon-letter::before { - content: '\4c'; + content: "\4c"; } .icon-circle::before { - content: '\43'; + content: "\43"; } .icon-circle-o::before { - content: '\4d'; + content: "\4d"; } .icon-help::before { - content: '\4e'; + content: "\4e"; } .icon-budget::before { - content: '\53'; + content: "\53"; } .icon-notification::before { - content: '\6e'; + content: "\6e"; } .icon-no-notification::before { - content: '\78'; + content: "\78"; } .icon-whatsapp::before { - content: '\50'; + content: "\50"; } .icon-zip::before { - content: '\4f'; + content: "\4f"; } .icon-banner::before { - content: '\51'; + content: "\51"; } .icon-arrow-down::before { - content: '\52'; + content: "\52"; } .icon-arrow-left::before { - content: '\54'; + content: "\54"; } .icon-arrow-right::before { - content: '\55'; + content: "\55"; } .icon-check-circle::before { - content: '\56'; + content: "\56"; } .icon-arrow-top::before { - content: '\57'; + content: "\57"; } .icon-checkmark-circle::before { - content: '\59'; + content: "\59"; } .icon-minus-square::before { - content: '\58'; + content: "\58"; } .icon-plus-square::before { - content: '\5a'; + content: "\5a"; } .icon-expand::before { - content: '\30'; + content: "\30"; } .icon-telegram::before { - content: '\31'; + content: "\31"; } .icon-instagram::before { - content: '\32'; + content: "\32"; } .icon-image::before { - content: '\33'; + content: "\33"; } .icon-search-plus::before { - content: '\34'; + content: "\34"; } .icon-search-minus::before { - content: '\35'; + content: "\35"; } .icon-calculator::before { - content: '\36'; + content: "\36"; } .icon-map-marker::before { - content: '\37'; + content: "\37"; } .icon-user-plus::before { - content: '\38'; + content: "\38"; } .icon-file-text-o::before { - content: '\39'; + content: "\39"; } .icon-file-text::before { - content: '\21'; + content: "\21"; } .icon-bars::before { - content: '\22'; + content: "\22"; } diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index 88738c072..513975a38 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -372,7 +372,7 @@ a { text-decoration: none; } - &[aria-selected='true'], + &[aria-selected="true"], &.is-active { border-bottom: 0; color: $brand; @@ -382,7 +382,7 @@ a { background: $brand; border-bottom: 2px solid $brand; bottom: 0; - content: ''; + content: ""; left: 0; position: absolute; width: 100%; @@ -459,7 +459,7 @@ header { &::after { color: #808080; - content: '\61'; + content: "\61"; font-family: "icons" !important; font-size: $small-font-size; pointer-events: none; @@ -501,7 +501,7 @@ header { a { color: #fff; display: inline-block; - font-family: 'Lato' !important; + font-family: "Lato" !important; font-size: rem-calc(24); font-weight: lighter; line-height: $line-height * 2; @@ -646,7 +646,7 @@ header { display: inline-block; &::after { - content: '|'; + content: "|"; } &:last-child::after { @@ -794,7 +794,7 @@ footer { color: $text; .logo a { - font-family: 'Lato' !important; + font-family: "Lato" !important; text-decoration: none; &:hover { @@ -906,7 +906,7 @@ footer { } .auth-image { - background: $brand image-url('auth_bg.jpg'); + background: $brand image-url("auth_bg.jpg"); background-repeat: no-repeat; background-size: cover; @@ -980,7 +980,7 @@ footer { } .locale-switcher { - background: #1a1a1a; + background: #001d33; border: 0; border-radius: rem-calc(4); color: #fff; @@ -1279,7 +1279,7 @@ form { &::before { background: $border; - content: ''; + content: ""; height: 100%; left: 7px; position: absolute; @@ -1325,14 +1325,14 @@ form { } &::before { - content: '\43'; + content: "\43"; } } &::before { background: #fff; color: $brand; - content: '\4d'; + content: "\4d"; font-family: "icons" !important; font-size: $small-font-size; height: rem-calc(20); @@ -1487,7 +1487,7 @@ table { &::before { color: #45b0e3; - content: 'f'; + content: "f"; font-family: "icons" !important; font-size: rem-calc(24); left: 0; @@ -1507,7 +1507,7 @@ table { width: $line-height * 2 !important; &::before { - content: 'f'; + content: "f"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1530,7 +1530,7 @@ table { &::before { color: #3b5998; - content: 'A'; + content: "A"; font-family: "icons" !important; font-size: rem-calc(24); left: 0; @@ -1550,7 +1550,7 @@ table { width: rem-calc(48) !important; &::before { - content: 'A'; + content: "A"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1573,7 +1573,7 @@ table { &::before { color: #de4c34; - content: 'B'; + content: "B"; font-family: "icons" !important; font-size: rem-calc(24); left: 0; @@ -1593,7 +1593,7 @@ table { width: $line-height * 2 !important; &::before { - content: 'B'; + content: "B"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1616,7 +1616,7 @@ table { &::before { color: #08c; - content: '1'; + content: "1"; font-family: "icons" !important; font-size: rem-calc(24); left: 0; @@ -1636,7 +1636,7 @@ table { width: $line-height * 2 !important; &::before { - content: '1'; + content: "1"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1689,7 +1689,7 @@ table { width: $line-height * 2; &::before { - content: 'f'; + content: "f"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1714,7 +1714,7 @@ table { width: rem-calc(48); &::before { - content: 'A'; + content: "A"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1739,7 +1739,7 @@ table { width: rem-calc(48); &::before { - content: 'B'; + content: "B"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1764,7 +1764,7 @@ table { width: $line-height * 2; &::before { - content: '1'; + content: "1"; font-family: "icons" !important; font-size: rem-calc(24); left: 50%; @@ -1808,7 +1808,7 @@ table { top: 24px; @include breakpoint(medium) { - content: 'c'; + content: "c"; } } } @@ -2260,15 +2260,15 @@ table { @include breakpoint(large) { .banner-img-one { - background-image: image-url('banners/banner1.png'); + background-image: image-url("banners/banner1.png"); } .banner-img-two { - background-image: image-url('banners/banner2.png'); + background-image: image-url("banners/banner2.png"); } .banner-img-three { - background-image: image-url('banners/banner3.png'); + background-image: image-url("banners/banner3.png"); } } @@ -2385,7 +2385,7 @@ table { } .card .orbit .orbit-wrapper .truncate { - background: image-url('truncate.png'); + background: image-url("truncate.png"); background-repeat: repeat-x; bottom: 0; height: rem-calc(20); @@ -2668,7 +2668,7 @@ table { &.score-positive::before, &.score-negative::before { - font-family: 'icons'; + font-family: "icons"; left: 0; position: absolute; } @@ -2678,7 +2678,7 @@ table { &::before { color: $color-success; - content: '\6c'; + content: "\6c"; } } @@ -2687,7 +2687,7 @@ table { &::before { color: $color-alert; - content: '\76'; + content: "\76"; } } } @@ -2728,7 +2728,8 @@ table { // 24. Homepage // ------------ -.home-page { +.home-page, +.custom-page { a { @@ -2868,11 +2869,19 @@ table { .figure-card { display: flex; margin: 0 0 $line-height; + overflow: hidden; position: relative; + @include breakpoint(medium down) { + min-height: $line-height * 4; + } + @include breakpoint(medium) { max-height: rem-calc(185); - overflow: hidden; + } + + @include breakpoint(large) { + min-height: rem-calc(185); } a { @@ -2904,8 +2913,16 @@ table { h3, .title { - font-size: rem-calc(24); - line-height: rem-calc(24); + font-size: $base-font-size; + + @include breakpoint(medium) { + font-size: rem-calc(20); + } + + @include breakpoint(large) { + font-size: rem-calc(24); + line-height: rem-calc(24); + } } span { diff --git a/app/assets/stylesheets/legislation_process.scss b/app/assets/stylesheets/legislation_process.scss index 990581236..474d80bbb 100644 --- a/app/assets/stylesheets/legislation_process.scss +++ b/app/assets/stylesheets/legislation_process.scss @@ -24,7 +24,7 @@ &::before { color: #8aa8be; - content: '■'; + content: "■"; padding-right: $line-height / 4; vertical-align: text-bottom; } @@ -60,12 +60,14 @@ border: 1px solid $border; display: block; margin: rem-calc(-1) 0; + min-height: $line-height * 3; position: relative; + vertical-align: top; @include breakpoint(large down) { &::after { - content: '\63'; + content: "\63"; font-family: "icons" !important; font-size: rem-calc(24); pointer-events: none; @@ -90,7 +92,7 @@ } &::after { - content: ''; + content: ""; } } @@ -136,7 +138,7 @@ } &::after { - content: ''; + content: ""; } } } @@ -466,8 +468,8 @@ cursor: pointer; position: absolute; margin-left: rem-calc(-20); - font-family: 'icons'; - content: '\58'; + font-family: "icons"; + content: "\58"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -476,8 +478,8 @@ cursor: pointer; position: absolute; margin-left: rem-calc(-20); - font-family: 'icons'; - content: '\5a'; + font-family: "icons"; + content: "\5a"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -505,7 +507,7 @@ .anchor::before { display: none; - content: '#'; + content: "#"; color: $text-medium; position: absolute; left: 0; @@ -757,7 +759,7 @@ display: inline-block; &::after { - content: '|'; + content: "|"; color: #838383; } } @@ -778,7 +780,7 @@ &::after { margin-left: rem-calc(4); - content: '|'; + content: "|"; } } @@ -828,7 +830,7 @@ &::before { margin-right: rem-calc(4); - content: '—'; + content: "—"; } } } @@ -979,4 +981,4 @@ font-size: rem-calc(20); margin-top: 0; } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/milestones.scss b/app/assets/stylesheets/milestones.scss new file mode 100644 index 000000000..ba60057de --- /dev/null +++ b/app/assets/stylesheets/milestones.scss @@ -0,0 +1,127 @@ +$progress-bar-background: #fef0e2; +$progress-bar-color: #fea230; + +.tab-milestones { + + .progress-bars { + margin-bottom: $line-height * 2; + margin-top: $line-height; + + h5 { + font-size: rem-calc(24); + } + + .progress { + background: $progress-bar-background; + border-radius: rem-calc(6); + position: relative; + } + + .progress-meter { + background: $progress-bar-color; + border-radius: rem-calc(6); + } + + .progress-meter-text { + color: #000; + right: 12px; + text-align: right; + transform: translate(0%, -50%); + } + + .milestone-progress .row { + margin-bottom: $line-height / 2; + } + } +} + +.tab-milestones .timeline li { + margin: 0 auto; + position: relative; + width: 0; + + @include breakpoint(small only) { + width: 100%; + } + + &::before { + background: $budget; + border-radius: rem-calc(20); + content: ""; + height: rem-calc(20); + position: absolute; + top: 5px; + transform: translateX(-50%); + width: rem-calc(20); + z-index: 2; + } + + &::after { + background: $light-gray; + bottom: 100%; + content: ""; + height: 100%; + position: absolute; + top: 25px; + width: 1px; + z-index: 1; + } + + .milestone-content { + padding: $line-height / 6 $line-height / 2; + position: relative; + + @include breakpoint(medium) { + width: rem-calc(300); + } + + @include breakpoint(large) { + width: rem-calc(450); + } + + h3 { + margin-bottom: 0; + } + + .milestone-date { + color: $text-medium; + font-size: $small-font-size; + } + } + + &:nth-child(odd) { + + .milestone-content { + text-align: right; + + @include breakpoint(medium) { + margin-left: rem-calc(-315); + } + + @include breakpoint(large) { + margin-left: rem-calc(-465); + } + + @include breakpoint(small only) { + left: 15px; + text-align: left; + } + } + } + + &:nth-child(even) { + + .milestone-content { + left: 15px; + } + } +} + +.milestone-status { + background: $budget; + border-radius: rem-calc(4); + color: #fff; + display: inline-block; + margin-top: $line-height / 6; + padding: $line-height / 4 $line-height / 2; +} diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss index 902b090f4..e1f293c13 100644 --- a/app/assets/stylesheets/mixins.scss +++ b/app/assets/stylesheets/mixins.scss @@ -11,7 +11,7 @@ @mixin logo { color: #fff; display: inline-block; - font-family: 'Lato' !important; + font-family: "Lato" !important; font-size: rem-calc(24); font-weight: lighter; diff --git a/app/assets/stylesheets/pages.scss b/app/assets/stylesheets/pages.scss index efde88d07..3df5ac3c1 100644 --- a/app/assets/stylesheets/pages.scss +++ b/app/assets/stylesheets/pages.scss @@ -23,11 +23,6 @@ &.light { background: #ecf0f1; } - - h1, - p { - color: $text; - } } .lead { diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 023686b6e..554c8e9ac 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -287,7 +287,7 @@ margin: $line-height / 2 0; &::before { - content: 'l '; + content: "l "; font-family: "icons" !important; } } @@ -523,118 +523,6 @@ } } -.tab-milestones ul { - margin-top: rem-calc(40); - position: relative; - - li { - margin: 0 auto; - position: relative; - width: 0; - } - - li::before { - background: $budget; - border-radius: rem-calc(20); - content: ''; - height: rem-calc(20); - position: absolute; - top: 5px; - transform: translateX(-50%); - width: rem-calc(20); - z-index: 2; - } - - li::after { - background: $light-gray; - bottom: 100%; - content: ''; - height: 100%; - position: absolute; - top: 25px; - width: 1px; - z-index: 1; - } -} - -.tab-milestones ul .milestone-content { - padding: $line-height / 6 $line-height / 2; - position: relative; - - h3 { - margin-bottom: 0; - } - - .milestone-date { - color: $text-medium; - font-size: $small-font-size; - } -} - -.tab-milestones .timeline ul li:nth-child(odd), -.tab-milestones .timeline ul li:nth-child(even) { - - .milestone-content { - - @include breakpoint(medium) { - width: rem-calc(300); - } - - @include breakpoint(large) { - width: rem-calc(450); - } - } -} - -.tab-milestones .timeline ul li:nth-child(odd) { - - .milestone-content { - text-align: right; - - @include breakpoint(medium) { - margin-left: rem-calc(-315); - } - - @include breakpoint(large) { - margin-left: rem-calc(-465); - } - } -} - -.tab-milestones .timeline ul li:nth-child(even) { - - .milestone-content { - left: 15px; - } -} - -.tab-milestones { - @include breakpoint(small only) { - - .timeline ul li { - width: 100%; - - &:nth-child(odd), - &:nth-child(even) { - - .milestone-content { - left: 15px; - text-align: left; - } - } - } - } -} - -.milestone-status { - background: $budget; - border-radius: rem-calc(4); - color: #fff; - display: inline-block; - margin-top: $line-height / 6; - padding: $line-height / 4 $line-height / 2; -} - .show-actions-menu { [class^="icon-"] { @@ -845,7 +733,7 @@ } .truncate { - background: image-url('truncate.png'); + background: image-url("truncate.png"); background-repeat: repeat-x; bottom: 0; height: rem-calc(24); @@ -1050,7 +938,7 @@ &::before { color: $text; - font-family: 'icons'; + font-family: "icons"; } } @@ -1059,7 +947,7 @@ .button { &::before { - content: '\51'; + content: "\51"; } } } @@ -1069,7 +957,7 @@ .button { &::before { - content: '\22'; + content: "\22"; } } } @@ -1078,8 +966,8 @@ position: relative; &::before { - content: '\22'; - font-family: 'icons'; + content: "\22"; + font-family: "icons"; left: 0; position: absolute; top: 6px; @@ -1090,8 +978,8 @@ position: relative; &::before { - content: '\51'; - font-family: 'icons'; + content: "\51"; + font-family: "icons"; left: 0; position: absolute; top: 6px; @@ -1102,8 +990,8 @@ color: $brand; &::after { - content: '\6c'; - font-family: 'icons'; + content: "\6c"; + font-family: "icons"; font-size: $tiny-font-size; } } @@ -1365,16 +1253,12 @@ display: inline-block; margin-bottom: $line-height / 2; - &:hover { - background: $highlight; - text-decoration: none; - } - a { display: block; padding: $line-height / 2; &:hover { + background: $highlight; text-decoration: none; } } @@ -1422,8 +1306,8 @@ &::before { color: #a5a1ff; - content: '\57'; - font-family: 'icons'; + content: "\57"; + font-family: "icons"; font-size: $small-font-size; position: absolute; right: -6px; @@ -1566,8 +1450,8 @@ font-weight: bold; &::after { - content: '\56'; - font-family: 'icons'; + content: "\56"; + font-family: "icons"; font-size: $small-font-size; font-weight: normal; line-height: $line-height; @@ -1642,7 +1526,7 @@ background-color: #fff; border: 4px solid $budget; border-radius: 100%; - content: ''; + content: ""; height: 16px; left: -22px; position: absolute; @@ -1784,7 +1668,7 @@ &::after { color: #1b254c; - content: '\59'; + content: "\59"; font-family: "icons" !important; left: 34px; position: absolute; @@ -1977,7 +1861,7 @@ &::after { color: $color-info; - content: '\6c'; + content: "\6c"; } } @@ -1986,7 +1870,7 @@ &::after { color: $color-alert; - content: '\74'; + content: "\74"; } } @@ -1995,7 +1879,7 @@ &::after { color: $color-info; - content: '\6f'; + content: "\6f"; } } @@ -2004,7 +1888,7 @@ &::after { color: $color-warning; - content: '\6f'; + content: "\6f"; } } @@ -2013,7 +1897,7 @@ &::after { color: $color-success; - content: '\59'; + content: "\59"; } } } @@ -2079,7 +1963,7 @@ &::after { background: #92ba48; border-radius: rem-calc(20); - content: '\6c'; + content: "\6c"; color: #fff; font-family: "icons" !important; font-size: rem-calc(12); diff --git a/app/controllers/admin/budget_groups_controller.rb b/app/controllers/admin/budget_groups_controller.rb index b6def19ed..aa87e2373 100644 --- a/app/controllers/admin/budget_groups_controller.rb +++ b/app/controllers/admin/budget_groups_controller.rb @@ -1,4 +1,5 @@ class Admin::BudgetGroupsController < Admin::BaseController + include Translatable include FeatureFlags feature_flag :budgets @@ -57,7 +58,8 @@ class Admin::BudgetGroupsController < Admin::BaseController end def budget_group_params - params.require(:budget_group).permit(:name, :max_votable_headings) + valid_attributes = [:max_votable_headings] + params.require(:budget_group).permit(*valid_attributes, translation_params(Budget::Group)) end end diff --git a/app/controllers/admin/budget_headings_controller.rb b/app/controllers/admin/budget_headings_controller.rb index 98ec7a261..31617698e 100644 --- a/app/controllers/admin/budget_headings_controller.rb +++ b/app/controllers/admin/budget_headings_controller.rb @@ -1,4 +1,5 @@ class Admin::BudgetHeadingsController < Admin::BaseController + include Translatable include FeatureFlags feature_flag :budgets @@ -62,8 +63,8 @@ class Admin::BudgetHeadingsController < Admin::BaseController end def budget_heading_params - params.require(:budget_heading).permit(:name, :price, :population, :allow_custom_content, - :latitude, :longitude) + valid_attributes = [:price, :population, :allow_custom_content, :latitude, :longitude] + params.require(:budget_heading).permit(*valid_attributes, translation_params(Budget::Heading)) end end diff --git a/app/controllers/admin/budget_investment_progress_bars_controller.rb b/app/controllers/admin/budget_investment_progress_bars_controller.rb new file mode 100644 index 000000000..bb4db0d79 --- /dev/null +++ b/app/controllers/admin/budget_investment_progress_bars_controller.rb @@ -0,0 +1,8 @@ +class Admin::BudgetInvestmentProgressBarsController < Admin::ProgressBarsController + + private + + def progressable + Budget::Investment.find(params[:budget_investment_id]) + end +end diff --git a/app/controllers/admin/budget_phases_controller.rb b/app/controllers/admin/budget_phases_controller.rb index d0eef18d8..3dd08675b 100644 --- a/app/controllers/admin/budget_phases_controller.rb +++ b/app/controllers/admin/budget_phases_controller.rb @@ -1,4 +1,5 @@ class Admin::BudgetPhasesController < Admin::BaseController + include Translatable before_action :load_phase, only: [:edit, :update] @@ -21,8 +22,8 @@ class Admin::BudgetPhasesController < Admin::BaseController end def budget_phase_params - valid_attributes = [:starts_at, :ends_at, :summary, :description, :enabled] - params.require(:budget_phase).permit(*valid_attributes) + valid_attributes = [:starts_at, :ends_at, :enabled] + params.require(:budget_phase).permit(*valid_attributes, translation_params(Budget::Phase)) end end diff --git a/app/controllers/admin/budgets_controller.rb b/app/controllers/admin/budgets_controller.rb index dab8dcad2..132a757ba 100644 --- a/app/controllers/admin/budgets_controller.rb +++ b/app/controllers/admin/budgets_controller.rb @@ -1,4 +1,5 @@ class Admin::BudgetsController < Admin::BaseController + include Translatable include FeatureFlags feature_flag :budgets @@ -56,8 +57,8 @@ class Admin::BudgetsController < Admin::BaseController def budget_params descriptions = Budget::Phase::PHASE_KINDS.map{|p| "description_#{p}"}.map(&:to_sym) - valid_attributes = [:name, :phase, :currency_symbol] + descriptions - params.require(:budget).permit(*valid_attributes) + valid_attributes = [:phase, :currency_symbol] + descriptions + params.require(:budget).permit(*valid_attributes, translation_params(Budget)) end end diff --git a/app/controllers/admin/legislation/processes_controller.rb b/app/controllers/admin/legislation/processes_controller.rb index 780ee7478..bf02dc7b6 100644 --- a/app/controllers/admin/legislation/processes_controller.rb +++ b/app/controllers/admin/legislation/processes_controller.rb @@ -1,12 +1,13 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseController include Translatable - has_filters %w{open next past all}, only: :index + has_filters %w[open all], only: :index load_and_authorize_resource :process, class: "Legislation::Process" def index - @processes = ::Legislation::Process.send(@current_filter).order('id DESC').page(params[:page]) + @processes = ::Legislation::Process.send(@current_filter).order(start_date: :desc) + .page(params[:page]) end def create @@ -66,8 +67,11 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll :result_publication_enabled, :published, :custom_list, + :background_color, + :font_color, translation_params(::Legislation::Process), - documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy] + documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], + image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy] ] end diff --git a/app/controllers/admin/legislation/progress_bars_controller.rb b/app/controllers/admin/legislation/progress_bars_controller.rb new file mode 100644 index 000000000..ba00d5e91 --- /dev/null +++ b/app/controllers/admin/legislation/progress_bars_controller.rb @@ -0,0 +1,14 @@ +class Admin::Legislation::ProgressBarsController < Admin::ProgressBarsController + include FeatureFlags + feature_flag :legislation + + def index + @process = progressable + end + + private + + def progressable + ::Legislation::Process.find(params[:process_id]) + end +end diff --git a/app/controllers/admin/poll/polls_controller.rb b/app/controllers/admin/poll/polls_controller.rb index dfd986fdf..91a01988e 100644 --- a/app/controllers/admin/poll/polls_controller.rb +++ b/app/controllers/admin/poll/polls_controller.rb @@ -7,6 +7,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController before_action :load_geozones, only: [:new, :create, :edit, :update] def index + @polls = Poll.order(starts_at: :desc) end def show @@ -51,7 +52,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController end def booth_assignments - @polls = Poll.current_or_incoming + @polls = Poll.current end private diff --git a/app/controllers/admin/poll/shifts_controller.rb b/app/controllers/admin/poll/shifts_controller.rb index d2ef8e74e..3396224dc 100644 --- a/app/controllers/admin/poll/shifts_controller.rb +++ b/app/controllers/admin/poll/shifts_controller.rb @@ -6,8 +6,8 @@ class Admin::Poll::ShiftsController < Admin::Poll::BaseController def new load_shifts @shift = ::Poll::Shift.new - @voting_polls = @booth.polls.current_or_incoming - @recount_polls = @booth.polls.current_or_recounting_or_incoming + @voting_polls = @booth.polls.current + @recount_polls = @booth.polls.current_or_recounting end def create @@ -26,9 +26,14 @@ class Admin::Poll::ShiftsController < Admin::Poll::BaseController def destroy @shift = Poll::Shift.find(params[:id]) - @shift.destroy - notice = t("admin.poll_shifts.flash.destroy") - redirect_to new_admin_booth_shift_path(@booth), notice: notice + if @shift.unable_to_destroy? + alert = t("admin.poll_shifts.flash.unable_to_destroy") + redirect_to new_admin_booth_shift_path(@booth), alert: alert + else + @shift.destroy + notice = t("admin.poll_shifts.flash.destroy") + redirect_to new_admin_booth_shift_path(@booth), notice: notice + end end def search_officers diff --git a/app/controllers/admin/progress_bars_controller.rb b/app/controllers/admin/progress_bars_controller.rb new file mode 100644 index 000000000..a9611b364 --- /dev/null +++ b/app/controllers/admin/progress_bars_controller.rb @@ -0,0 +1,69 @@ +class Admin::ProgressBarsController < Admin::BaseController + include Translatable + + before_action :load_progressable + before_action :load_progress_bar, only: [:edit, :update, :destroy] + helper_method :progress_bars_index + + def index + end + + def new + @progress_bar = @progressable.progress_bars.new + end + + def create + @progress_bar = @progressable.progress_bars.new(progress_bar_params) + if @progress_bar.save + redirect_to progress_bars_index, notice: t("admin.progress_bars.create.notice") + else + render :new + end + end + + def edit + end + + def update + if @progress_bar.update(progress_bar_params) + redirect_to progress_bars_index, notice: t('admin.progress_bars.update.notice') + else + render :edit + end + end + + def destroy + @progress_bar.destroy + redirect_to progress_bars_index, notice: t('admin.progress_bars.delete.notice') + end + + private + + def progress_bar_params + params.require(:progress_bar).permit(allowed_params) + end + + def allowed_params + [ + :kind, + :percentage, + translation_params(ProgressBar) + ] + end + + def load_progressable + @progressable = progressable + end + + def progressable + raise "This method must be implemented in subclass #{self.class.name}" + end + + def load_progress_bar + @progress_bar = progressable.progress_bars.find(params[:id]) + end + + def progress_bars_index + polymorphic_path([:admin, *resource_hierarchy_for(@progressable), ProgressBar.new]) + end +end diff --git a/app/controllers/admin/proposal_progress_bars_controller.rb b/app/controllers/admin/proposal_progress_bars_controller.rb new file mode 100644 index 000000000..9259acc4b --- /dev/null +++ b/app/controllers/admin/proposal_progress_bars_controller.rb @@ -0,0 +1,7 @@ +class Admin::ProposalProgressBarsController < Admin::ProgressBarsController + + private + def progressable + Proposal.find(params[:proposal_id]) + end +end diff --git a/app/controllers/admin/site_customization/cards_controller.rb b/app/controllers/admin/site_customization/cards_controller.rb new file mode 100644 index 000000000..c0d06018e --- /dev/null +++ b/app/controllers/admin/site_customization/cards_controller.rb @@ -0,0 +1,9 @@ +class Admin::SiteCustomization::CardsController < Admin::SiteCustomization::BaseController + skip_authorization_check + + def index + @page = ::SiteCustomization::Page.find(params[:page_id]) + @cards = @page.cards + end + +end diff --git a/app/controllers/admin/widget/cards_controller.rb b/app/controllers/admin/widget/cards_controller.rb index ccc05f3f2..eb1e6ba79 100644 --- a/app/controllers/admin/widget/cards_controller.rb +++ b/app/controllers/admin/widget/cards_controller.rb @@ -3,14 +3,17 @@ class Admin::Widget::CardsController < Admin::BaseController include ImageAttributes def new - @card = ::Widget::Card.new(header: header_card?) + if header_card? + @card = ::Widget::Card.new(header: header_card?) + else + @card = ::Widget::Card.new(site_customization_page_id: params[:page_id]) + end end def create @card = ::Widget::Card.new(card_params) if @card.save - notice = "Success" - redirect_to admin_homepage_url, notice: notice + redirect_to_customization_page_cards_or_homepage else render :new end @@ -23,8 +26,7 @@ class Admin::Widget::CardsController < Admin::BaseController def update @card = ::Widget::Card.find(params[:id]) if @card.update(card_params) - notice = "Updated" - redirect_to admin_homepage_url, notice: notice + redirect_to_customization_page_cards_or_homepage else render :edit end @@ -34,25 +36,39 @@ class Admin::Widget::CardsController < Admin::BaseController @card = ::Widget::Card.find(params[:id]) @card.destroy - notice = "Removed" - redirect_to admin_homepage_url, notice: notice + redirect_to_customization_page_cards_or_homepage end private - def card_params - params.require(:widget_card).permit( - :link_url, :button_text, :button_url, :alignment, :header, - translation_params(Widget::Card), - image_attributes: image_attributes - ) - end + def card_params + params.require(:widget_card).permit( + :link_url, :button_text, :button_url, :alignment, :header, :site_customization_page_id, + :columns, + translation_params(Widget::Card), + image_attributes: image_attributes + ) + end - def header_card? - params[:header_card].present? - end + def header_card? + params[:header_card].present? + end - def resource - Widget::Card.find(params[:id]) - end + def redirect_to_customization_page_cards_or_homepage + notice = t("admin.site_customization.pages.cards.#{params[:action]}.notice") + + if @card.site_customization_page_id + redirect_to admin_site_customization_page_cards_path(page), notice: notice + else + redirect_to admin_homepage_url, notice: notice + end + end + + def page + ::SiteCustomization::Page.find(@card.site_customization_page_id) + end + + def resource + Widget::Card.find(params[:id]) + end end diff --git a/app/controllers/annotations_controller.rb b/app/controllers/annotations_controller.rb deleted file mode 100644 index 8b004076c..000000000 --- a/app/controllers/annotations_controller.rb +++ /dev/null @@ -1,40 +0,0 @@ -class AnnotationsController < ApplicationController - skip_before_action :verify_authenticity_token - load_and_authorize_resource - - def create - @annotation = Annotation.new(annotation_params) - @annotation.user = current_user - if @annotation.save - render json: @annotation.to_json(methods: :permissions) - end - end - - def update - @annotation = Annotation.find(params[:id]) - if @annotation.update_attributes(annotation_params) - render json: @annotation.to_json(methods: :permissions) - end - end - - def destroy - @annotation = Annotation.find(params[:id]) - @annotation.destroy - render json: { status: :ok } - end - - def search - @annotations = Annotation.where(legacy_legislation_id: params[:legacy_legislation_id]) - annotations_hash = { total: @annotations.size, rows: @annotations } - render json: annotations_hash.to_json(methods: :permissions) - end - - private - - def annotation_params - params - .require(:annotation) - .permit(:quote, :text, ranges: [:start, :startOffset, :end, :endOffset]) - .merge(legacy_legislation_id: params[:legacy_legislation_id]) - end -end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e97b87cd3..37014703a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -120,6 +120,8 @@ class ApplicationController < ActionController::Base def set_default_budget_filter if @budget.try(:balloting?) || @budget.try(:publishing_prices?) params[:filter] ||= "selected" + elsif @budget.try(:finished?) + params[:filter] ||= "winners" end end diff --git a/app/controllers/budgets/executions_controller.rb b/app/controllers/budgets/executions_controller.rb index 25f27b1ca..54decebee 100644 --- a/app/controllers/budgets/executions_controller.rb +++ b/app/controllers/budgets/executions_controller.rb @@ -25,7 +25,7 @@ module Budgets end def load_budget - @budget = Budget.find_by(slug: params[:id]) || Budget.find_by(id: params[:id]) + @budget = Budget.find_by_slug_or_id params[:budget_id] end def investments_by_heading_ordered_alphabetically diff --git a/app/controllers/budgets/groups_controller.rb b/app/controllers/budgets/groups_controller.rb index d84eb2fdd..f298b5a93 100644 --- a/app/controllers/budgets/groups_controller.rb +++ b/app/controllers/budgets/groups_controller.rb @@ -4,7 +4,7 @@ module Budgets load_and_authorize_resource :group, class: "Budget::Group" before_action :set_default_budget_filter, only: :show - has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: [:show] + has_filters %w[not_unfeasible feasible unfeasible unselected selected winners], only: [:show] def show end diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb index 8ca9a8d71..73c127db4 100644 --- a/app/controllers/budgets/investments_controller.rb +++ b/app/controllers/budgets/investments_controller.rb @@ -27,7 +27,9 @@ module Budgets has_orders %w{most_voted newest oldest}, only: :show has_orders ->(c) { c.instance_variable_get(:@budget).investments_orders }, only: :index - has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: [:index, :show, :suggest] + + valid_filters = %w[not_unfeasible feasible unfeasible unselected selected winners] + has_filters valid_filters, only: [:index, :show, :suggest] invisible_captcha only: [:create, :update], honeypot: :subtitle, scope: :budget_investment @@ -35,18 +37,10 @@ module Budgets respond_to :html, :js def index - all_investments = if @budget.finished? - investments.winners - else - investments - end - - @investments = all_investments.page(params[:page]).per(10).for_render + @investments = investments.page(params[:page]).per(10).for_render @investment_ids = @investments.pluck(:id) - @investments_map_coordinates = MapLocation.where(investment: all_investments).map do |loc| - loc.json_data - end + @investments_map_coordinates = MapLocation.where(investment: investments).map(&:json_data) load_investment_votes(@investments) @tag_cloud = tag_cloud diff --git a/app/controllers/budgets_controller.rb b/app/controllers/budgets_controller.rb index 70efd04e9..e9cfae97c 100644 --- a/app/controllers/budgets_controller.rb +++ b/app/controllers/budgets_controller.rb @@ -5,7 +5,7 @@ class BudgetsController < ApplicationController load_and_authorize_resource before_action :set_default_budget_filter, only: :show - has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: :show + has_filters %w[not_unfeasible feasible unfeasible unselected selected winners], only: :show respond_to :html, :js diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb index 001d23446..1d6df8d14 100644 --- a/app/controllers/documents_controller.rb +++ b/app/controllers/documents_controller.rb @@ -11,7 +11,7 @@ class DocumentsController < ApplicationController else flash[:alert] = t "documents.actions.destroy.alert" end - redirect_to params[:from] + redirect_to request.referer end format.js do if @document.destroy diff --git a/app/controllers/installation_controller.rb b/app/controllers/installation_controller.rb index bc0e32943..8aef8b659 100644 --- a/app/controllers/installation_controller.rb +++ b/app/controllers/installation_controller.rb @@ -12,7 +12,7 @@ class InstallationController < ApplicationController def consul_installation_details { - release: 'v0.18' + release: "v0.18.1" }.merge(features: settings_feature_flags) end diff --git a/app/controllers/legacy_legislations_controller.rb b/app/controllers/legacy_legislations_controller.rb deleted file mode 100644 index 103c81cea..000000000 --- a/app/controllers/legacy_legislations_controller.rb +++ /dev/null @@ -1,8 +0,0 @@ -class LegacyLegislationsController < ApplicationController - load_and_authorize_resource - - def show - @legacy_legislation = LegacyLegislation.find(params[:id]) - end - -end diff --git a/app/controllers/legislation/processes_controller.rb b/app/controllers/legislation/processes_controller.rb index e450b759c..0e5d030be 100644 --- a/app/controllers/legislation/processes_controller.rb +++ b/app/controllers/legislation/processes_controller.rb @@ -1,5 +1,5 @@ class Legislation::ProcessesController < Legislation::BaseController - has_filters %w[open next past], only: :index + has_filters %w[open past], only: :index has_filters %w[random winners], only: :proposals load_and_authorize_resource @@ -9,7 +9,7 @@ class Legislation::ProcessesController < Legislation::BaseController def index @current_filter ||= 'open' @processes = ::Legislation::Process.send(@current_filter).published - .not_in_draft.page(params[:page]) + .not_in_draft.order(start_date: :desc).page(params[:page]) end def show diff --git a/app/controllers/management/budgets/investments_controller.rb b/app/controllers/management/budgets/investments_controller.rb index 2e879b6e1..ff1e7ee86 100644 --- a/app/controllers/management/budgets/investments_controller.rb +++ b/app/controllers/management/budgets/investments_controller.rb @@ -4,7 +4,6 @@ class Management::Budgets::InvestmentsController < Management::BaseController load_resource :investment, through: :budget, class: 'Budget::Investment' before_action :only_verified_users, except: :print - before_action :load_heading, only: [:index, :show, :print] def index @investments = @investments.apply_filters_and_search(@budget, params).page(params[:page]) @@ -61,10 +60,6 @@ class Management::Budgets::InvestmentsController < Management::BaseController check_verified_user t("management.budget_investments.alert.unverified_user") end - def load_heading - @heading = @budget.headings.find(params[:heading_id]) if params[:heading_id].present? - end - def load_categories @categories = ActsAsTaggableOn::Tag.category.order(:name) end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 489ea9dcf..eae9e7509 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -9,6 +9,7 @@ class PagesController < ApplicationController @banners = Banner.in_section('help_page').with_active if @custom_page.present? + @cards = @custom_page.cards render action: :custom_page else render action: params[:id] diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 708f68abb..8378b083d 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -3,7 +3,7 @@ class PollsController < ApplicationController load_and_authorize_resource - has_filters %w{current expired incoming} + has_filters %w[current expired] has_orders %w{most_voted newest oldest}, only: :show ::Poll::Answer # trigger autoload diff --git a/app/controllers/related_contents_controller.rb b/app/controllers/related_contents_controller.rb index db6be0018..9dc753fee 100644 --- a/app/controllers/related_contents_controller.rb +++ b/app/controllers/related_contents_controller.rb @@ -31,7 +31,7 @@ class RelatedContentsController < ApplicationController private def score(action) - @related = RelatedContent.find_by(id: params[:id]) + @related = RelatedContent.find params[:id] @related.send("score_#{action}", current_user) render template: 'relationable/_refresh_score_actions' diff --git a/app/controllers/valuation/budget_investments_controller.rb b/app/controllers/valuation/budget_investments_controller.rb index d8b832d47..d5a6706e6 100644 --- a/app/controllers/valuation/budget_investments_controller.rb +++ b/app/controllers/valuation/budget_investments_controller.rb @@ -75,8 +75,8 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController def heading_filters investments = @budget.investments.by_valuator(current_user.valuator.try(:id)) .visible_to_valuators.distinct - - investment_headings = Budget::Heading.where(id: investments.pluck(:heading_id).uniq) + investment_headings = Budget::Heading.joins(:translations) + .where(id: investments.pluck(:heading_id).uniq) .order(name: :asc) all_headings_filter = [ diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index 903a1e0a3..255020c1f 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -29,6 +29,10 @@ module AdminHelper "hidden_budget_investments"] end + def menu_budgets? + controller_name.starts_with?("budget") + end + def menu_budget? ["spending_proposals"].include?(controller_name) end @@ -50,11 +54,16 @@ module AdminHelper end def menu_customization? - ["pages", "banners", "information_texts"].include?(controller_name) || menu_homepage? + ["pages", "banners", "information_texts"].include?(controller_name) || + menu_homepage? || menu_pages? end def menu_homepage? - ["homepage", "cards"].include?(controller_name) + ["homepage", "cards"].include?(controller_name) && params[:page_id].nil? + end + + def menu_pages? + ["pages", "cards"].include?(controller_name) && params[:page_id].present? end def official_level_options diff --git a/app/helpers/budget_headings_helper.rb b/app/helpers/budget_headings_helper.rb index 22eabfe11..80c21e9e8 100644 --- a/app/helpers/budget_headings_helper.rb +++ b/app/helpers/budget_headings_helper.rb @@ -1,7 +1,7 @@ module BudgetHeadingsHelper def budget_heading_select_options(budget) - budget.headings.order_by_group_name.map do |heading| + budget.headings.sort_by_name.map do |heading| [heading.name_scoped_by_group, heading.id] end end diff --git a/app/helpers/budgets_helper.rb b/app/helpers/budgets_helper.rb index b4717fbdf..8611fc652 100644 --- a/app/helpers/budgets_helper.rb +++ b/app/helpers/budgets_helper.rb @@ -48,8 +48,8 @@ module BudgetsHelper end def css_for_ballot_heading(heading) - return '' if current_ballot.blank? - current_ballot.has_lines_in_heading?(heading) ? 'is-active' : '' + return "" if current_ballot.blank? || @current_filter == "unfeasible" + current_ballot.has_lines_in_heading?(heading) ? "is-active" : "" end def current_ballot @@ -60,13 +60,17 @@ module BudgetsHelper Budget::Investment.by_budget(budget).tags_on(:valuation).order(:name).select(:name).distinct end + def unfeasible_or_unselected_filter + ["unselected", "unfeasible"].include?(@current_filter) + end + def budget_published?(budget) !budget.drafting? || current_user&.administrator? end def current_budget_map_locations return unless current_budget.present? - if current_budget.valuating_or_later? + if current_budget.publishing_prices_or_later? && current_budget.investments.selected.any? investments = current_budget.investments.selected else investments = current_budget.investments @@ -86,4 +90,10 @@ module BudgetsHelper t("admin.budgets.winners.recalculate") end end + + def display_support_alert?(investment) + current_user && + !current_user.voted_in_group?(investment.group) && + investment.group.headings.count > 1 + end end diff --git a/app/helpers/feeds_helper.rb b/app/helpers/feeds_helper.rb index 3a5ee8f3d..1657a6887 100644 --- a/app/helpers/feeds_helper.rb +++ b/app/helpers/feeds_helper.rb @@ -12,8 +12,20 @@ module FeedsHelper feed.kind == "processes" end + def feed_debates_enabled? + Setting["feature.homepage.widgets.feeds.debates"].present? + end + + def feed_proposals_enabled? + Setting["feature.homepage.widgets.feeds.proposals"].present? + end + def feed_processes_enabled? - Setting['feature.homepage.widgets.feeds.processes'].present? + Setting["feature.homepage.widgets.feeds.processes"].present? + end + + def feed_debates_and_proposals_enabled? + feed_debates_enabled? && feed_proposals_enabled? end end diff --git a/app/helpers/legislation_helper.rb b/app/helpers/legislation_helper.rb index 413dc3515..d695e0400 100644 --- a/app/helpers/legislation_helper.rb +++ b/app/helpers/legislation_helper.rb @@ -37,4 +37,15 @@ module LegislationHelper "milestones" => admin_legislation_process_milestones_path(process) } end + + def banner_color? + @process.background_color.present? && @process.font_color.present? + end + + def css_for_process_header + if banner_color? + "background:" + @process.background_color + ";color:" + @process.font_color + ";" + end + end + end diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb new file mode 100644 index 000000000..ed8a1e38b --- /dev/null +++ b/app/helpers/milestones_helper.rb @@ -0,0 +1,18 @@ +module MilestonesHelper + def progress_tag_for(progress_bar) + text = number_to_percentage(progress_bar.percentage, precision: 0) + + content_tag :div, class: "progress", + role: "progressbar", + "aria-valuenow": "#{progress_bar.percentage}", + "aria-valuetext": "#{progress_bar.percentage}%", + "aria-valuemax": ProgressBar::RANGE.max, + "aria-valuemin": "0", + tabindex: "0" do + content_tag(:span, "", + class: "progress-meter", + style: "width: #{progress_bar.percentage}%;") + + content_tag(:p, text, class: "progress-meter-text") + end + end +end diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb index 0cb875dff..83200c621 100644 --- a/app/helpers/polls_helper.rb +++ b/app/helpers/polls_helper.rb @@ -49,4 +49,19 @@ module PollsHelper question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at > vote.updated_at } end + def show_stats_or_results? + @poll.expired? && (@poll.results_enabled? || @poll.stats_enabled?) + end + + def results_menu? + controller_name == "polls" && action_name == "results" + end + + def stats_menu? + controller_name == "polls" && action_name == "stats" + end + + def info_menu? + controller_name == "polls" && action_name == "show" + end end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index bdc457bc0..6e879a6a9 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -57,8 +57,6 @@ module Abilities can [:search, :create, :index, :destroy], ::Manager can [:search, :index], ::User - can :manage, Annotation - can [:read, :update, :valuate, :destroy, :summary], SpendingProposal can [:index, :read, :new, :create, :update, :destroy, :calculate_winners], Budget can [:read, :create, :update, :destroy], Budget::Group @@ -93,6 +91,7 @@ module Abilities cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal] can [:create], Document + can [:destroy], Document, documentable_type: "Poll::Question::Answer" can [:create, :destroy], DirectUpload can [:deliver], Newsletter, hidden_at: nil diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 7c84089b4..2305a0176 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -92,9 +92,6 @@ module Abilities can [:create, :show], ProposalNotification, proposal: { author_id: user.id } - can :create, Annotation - can [:update, :destroy], Annotation, user_id: user.id - can [:create], Topic can [:update, :destroy], Topic, author_id: user.id diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb index ab5a095e0..a20a119fe 100644 --- a/app/models/abilities/everyone.rb +++ b/app/models/abilities/everyone.rb @@ -16,9 +16,7 @@ module Abilities can :read, Poll::Question can [:read, :welcome], Budget can :read, SpendingProposal - can :read, LegacyLegislation can :read, User - can [:search, :read], Annotation can [:read], Budget can [:read], Budget::Group can [:read, :print, :json_data], Budget::Investment diff --git a/app/models/annotation.rb b/app/models/annotation.rb deleted file mode 100644 index 295badd92..000000000 --- a/app/models/annotation.rb +++ /dev/null @@ -1,10 +0,0 @@ -class Annotation < ActiveRecord::Base - serialize :ranges, Array - - belongs_to :legacy_legislation - belongs_to :user - - def permissions - { update: [user_id], delete: [user_id], admin: [] } - end -end diff --git a/app/models/budget.rb b/app/models/budget.rb index 3f4bed9a1..53bd02e82 100644 --- a/app/models/budget.rb +++ b/app/models/budget.rb @@ -3,9 +3,14 @@ class Budget < ActiveRecord::Base include Measurable include Sluggable + translates :name, touch: true + include Globalizable + CURRENCY_SYMBOLS = %w(€ $ £ ¥).freeze - validates :name, presence: true, uniqueness: true + before_validation :assign_model_to_translations + + validates_translation :name, presence: true validates :phase, inclusion: { in: Budget::Phase::PHASE_KINDS } validates :currency_symbol, presence: true validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ @@ -105,8 +110,8 @@ class Budget < ActiveRecord::Base Budget::Phase::PUBLISHED_PRICES_PHASES.include?(phase) end - def valuating_or_later? - valuating? || publishing_prices? || balloting_or_later? + def publishing_prices_or_later? + publishing_prices? || balloting_or_later? end def balloting_process? diff --git a/app/models/budget/group.rb b/app/models/budget/group.rb index bfbfd4741..37d6e658b 100644 --- a/app/models/budget/group.rb +++ b/app/models/budget/group.rb @@ -2,14 +2,21 @@ class Budget class Group < ActiveRecord::Base include Sluggable + translates :name, touch: true + include Globalizable + belongs_to :budget has_many :headings, dependent: :destroy + before_validation :assign_model_to_translations + + validates_translation :name, presence: true validates :budget_id, presence: true - validates :name, presence: true, uniqueness: { scope: :budget } validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ + scope :sort_by_name, -> { includes(:translations).order(:name) } + def single_heading_group? headings.count == 1 end diff --git a/app/models/budget/group/translation.rb b/app/models/budget/group/translation.rb new file mode 100644 index 000000000..36489eb10 --- /dev/null +++ b/app/models/budget/group/translation.rb @@ -0,0 +1,13 @@ +class Budget::Group::Translation < Globalize::ActiveRecord::Translation + delegate :budget, to: :globalized_model + + validate :name_uniqueness_by_budget + + def name_uniqueness_by_budget + if budget.groups.joins(:translations) + .where(name: name) + .where.not("budget_group_translations.budget_group_id": budget_group_id).any? + errors.add(:name, I18n.t("errors.messages.taken")) + end + end +end diff --git a/app/models/budget/heading.rb b/app/models/budget/heading.rb index 50c5d3992..ac9ac6492 100644 --- a/app/models/budget/heading.rb +++ b/app/models/budget/heading.rb @@ -4,13 +4,18 @@ class Budget include Sluggable + translates :name, touch: true + include Globalizable + belongs_to :group has_many :investments has_many :content_blocks + before_validation :assign_model_to_translations + + validates_translation :name, presence: true validates :group_id, presence: true - validates :name, presence: true, uniqueness: { if: :name_exists_in_budget_headings } validates :price, presence: true validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ validates :population, numericality: { greater_than: 0 }, allow_nil: true @@ -21,17 +26,19 @@ class Budget delegate :budget, :budget_id, to: :group, allow_nil: true - scope :order_by_group_name, -> { includes(:group).order('budget_groups.name', 'budget_headings.name') } - scope :allow_custom_content, -> { where(allow_custom_content: true).order(:name) } + scope :i18n, -> { includes(:translations) } + scope :allow_custom_content, -> { i18n.where(allow_custom_content: true).order(:name) } + + def self.sort_by_name + all.sort do |heading, other_heading| + [other_heading.group.name, heading.name] <=> [heading.group.name, other_heading.name] + end + end def name_scoped_by_group group.single_heading_group? ? name : "#{group.name}: #{name}" end - def name_exists_in_budget_headings - group.budget.headings.where(name: name).where.not(id: id).any? - end - def can_be_deleted? investments.empty? end diff --git a/app/models/budget/heading/translation.rb b/app/models/budget/heading/translation.rb new file mode 100644 index 000000000..3cf930f66 --- /dev/null +++ b/app/models/budget/heading/translation.rb @@ -0,0 +1,14 @@ +class Budget::Heading::Translation < Globalize::ActiveRecord::Translation + delegate :budget, to: :globalized_model + + validate :name_uniqueness_by_budget + + def name_uniqueness_by_budget + if budget.headings + .joins(:translations) + .where(name: name) + .where.not("budget_heading_translations.budget_heading_id": budget_heading_id).any? + errors.add(:name, I18n.t("errors.messages.taken")) + end + end +end diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 1b528a9cb..fc157a999 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -257,7 +257,7 @@ class Budget end def can_vote_in_another_heading?(user) - headings_voted_by_user(user).count < group.max_votable_headings + user.headings_voted_within_group(group).count < group.max_votable_headings end def headings_voted_by_user(user) @@ -265,7 +265,7 @@ class Budget end def voted_in?(heading, user) - headings_voted_by_user(user).include?(heading.id) + user.headings_voted_within_group(group).where(id: heading.id).exists? end def ballotable_by?(user) diff --git a/app/models/budget/phase.rb b/app/models/budget/phase.rb index 432c4b609..de089413a 100644 --- a/app/models/budget/phase.rb +++ b/app/models/budget/phase.rb @@ -6,20 +6,22 @@ class Budget SUMMARY_MAX_LENGTH = 1000 DESCRIPTION_MAX_LENGTH = 2000 + translates :summary, touch: true + translates :description, touch: true + include Globalizable + belongs_to :budget belongs_to :next_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id has_one :prev_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id + validates_translation :summary, length: { maximum: SUMMARY_MAX_LENGTH } + validates_translation :description, length: { maximum: DESCRIPTION_MAX_LENGTH } validates :budget, presence: true validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: PHASE_KINDS } - validates :summary, length: { maximum: SUMMARY_MAX_LENGTH } - validates :description, length: { maximum: DESCRIPTION_MAX_LENGTH } validate :invalid_dates_range? validate :prev_phase_dates_valid? validate :next_phase_dates_valid? - before_validation :sanitize_description - after_save :adjust_date_ranges after_save :touch_budget @@ -87,8 +89,5 @@ class Budget end end - def sanitize_description - self.description = WYSIWYGSanitizer.new.sanitize(description) - end end end diff --git a/app/models/budget/phase/translation.rb b/app/models/budget/phase/translation.rb new file mode 100644 index 000000000..53390143a --- /dev/null +++ b/app/models/budget/phase/translation.rb @@ -0,0 +1,9 @@ +class Budget::Phase::Translation < Globalize::ActiveRecord::Translation + before_validation :sanitize_description + + private + + def sanitize_description + self.description = WYSIWYGSanitizer.new.sanitize(description) + end +end diff --git a/app/models/budget/translation.rb b/app/models/budget/translation.rb new file mode 100644 index 000000000..1f3d93ea1 --- /dev/null +++ b/app/models/budget/translation.rb @@ -0,0 +1,11 @@ +class Budget::Translation < Globalize::ActiveRecord::Translation + validate :name_uniqueness_by_budget + + def name_uniqueness_by_budget + if Budget.joins(:translations) + .where(name: name) + .where.not("budget_translations.budget_id": budget_id).any? + errors.add(:name, I18n.t("errors.messages.taken")) + end + end +end diff --git a/app/models/concerns/globalizable.rb b/app/models/concerns/globalizable.rb index 386047f8b..e8772f19c 100644 --- a/app/models/concerns/globalizable.rb +++ b/app/models/concerns/globalizable.rb @@ -8,6 +8,10 @@ module Globalizable def locales_not_marked_for_destruction translations.reject(&:_destroy).map(&:locale) end + + def assign_model_to_translations + translations.each { |translation| translation.globalized_model = self } + end end class_methods do diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb index 2e961c613..66de28d6c 100644 --- a/app/models/concerns/milestoneable.rb +++ b/app/models/concerns/milestoneable.rb @@ -5,5 +5,15 @@ module Milestoneable has_many :milestones, as: :milestoneable, dependent: :destroy scope :with_milestones, -> { joins(:milestones).distinct } + + has_many :progress_bars, as: :progressable + + def primary_progress_bar + progress_bars.primary.first + end + + def secondary_progress_bars + progress_bars.secondary + end end end diff --git a/app/models/concerns/sluggable.rb b/app/models/concerns/sluggable.rb index 495ffaf77..8fb308d22 100644 --- a/app/models/concerns/sluggable.rb +++ b/app/models/concerns/sluggable.rb @@ -3,6 +3,10 @@ module Sluggable included do before_validation :generate_slug, if: :generate_slug? + + def self.find_by_slug_or_id(slug_or_id) + find_by_slug(slug_or_id) || find_by_id(slug_or_id) + end end def generate_slug diff --git a/app/models/debate.rb b/app/models/debate.rb index a73a1ab6c..2aa1bdce4 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -88,6 +88,10 @@ class Debate < ActiveRecord::Base cached_votes_total end + def votes_score + cached_votes_score + end + def total_anonymous_votes cached_anonymous_votes_total end diff --git a/app/models/legacy_legislation.rb b/app/models/legacy_legislation.rb deleted file mode 100644 index ddc267e3a..000000000 --- a/app/models/legacy_legislation.rb +++ /dev/null @@ -1,3 +0,0 @@ -class LegacyLegislation < ActiveRecord::Base - has_many :annotations -end diff --git a/app/models/legislation/process.rb b/app/models/legislation/process.rb index be8cc74c3..c4101bc87 100644 --- a/app/models/legislation/process.rb +++ b/app/models/legislation/process.rb @@ -2,6 +2,7 @@ class Legislation::Process < ActiveRecord::Base include ActsAsParanoidAliases include Taggable include Milestoneable + include Imageable include Documentable documentable max_documents_allowed: 3, max_file_size: 3.megabytes, @@ -18,8 +19,10 @@ class Legislation::Process < ActiveRecord::Base translates :homepage, touch: true include Globalizable - PHASES_AND_PUBLICATIONS = %i[draft_phase debate_phase allegations_phase proposals_phase - draft_publication result_publication].freeze + PHASES_AND_PUBLICATIONS = %i[homepage_phase draft_phase debate_phase allegations_phase + proposals_phase draft_publication result_publication].freeze + + CSS_HEX_COLOR = /\A#?(?:[A-F0-9]{3}){1,2}\z/i has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id', @@ -43,17 +46,21 @@ class Legislation::Process < ActiveRecord::Base validates :allegations_end_date, presence: true, if: :allegations_start_date? validates :proposals_phase_end_date, presence: true, if: :proposals_phase_start_date? validate :valid_date_ranges + validates :background_color, format: { allow_blank: true, with: CSS_HEX_COLOR } + validates :font_color, format: { allow_blank: true, with: CSS_HEX_COLOR } - scope :open, -> { where("start_date <= ? and end_date >= ?", Date.current, Date.current) - .order('id DESC') } - scope :next, -> { where("start_date > ?", Date.current).order('id DESC') } - scope :past, -> { where("end_date < ?", Date.current).order('id DESC') } + scope :open, -> { where("start_date <= ? and end_date >= ?", Date.current, Date.current) } + scope :past, -> { where("end_date < ?", Date.current) } scope :published, -> { where(published: true) } scope :not_in_draft, -> { where("draft_phase_enabled = false or (draft_start_date IS NOT NULL and draft_end_date IS NOT NULL and (draft_start_date > ? or draft_end_date < ?))", Date.current, Date.current) } + def homepage_phase + Legislation::Process::Phase.new(start_date, end_date, homepage_enabled) + end + def draft_phase Legislation::Process::Phase.new(draft_start_date, draft_end_date, draft_phase_enabled) end diff --git a/app/models/legislation/proposal.rb b/app/models/legislation/proposal.rb index d7c5e4807..15ed53428 100644 --- a/app/models/legislation/proposal.rb +++ b/app/models/legislation/proposal.rb @@ -47,7 +47,7 @@ class Legislation::Proposal < ActiveRecord::Base scope :sort_by_most_commented, -> { reorder(comments_count: :desc) } scope :sort_by_title, -> { reorder(title: :asc) } scope :sort_by_id, -> { reorder(id: :asc) } - scope :sort_by_supports, -> { reorder(cached_votes_up: :desc) } + scope :sort_by_supports, -> { reorder(cached_votes_score: :desc) } scope :sort_by_random, -> { reorder("RANDOM()") } scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) } scope :last_week, -> { where("proposals.created_at >= ?", 7.days.ago)} @@ -96,6 +96,10 @@ class Legislation::Proposal < ActiveRecord::Base cached_votes_total end + def votes_score + cached_votes_score + end + def voters User.active.where(id: votes_for.voters) end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 5abd5cb4f..d4ef41137 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -14,7 +14,7 @@ class Milestone < ActiveRecord::Base validates :milestoneable, presence: true validates :publication_date, presence: true - before_validation :assign_milestone_to_translations + before_validation :assign_model_to_translations validates_translation :description, presence: true, unless: -> { status_id.present? } scope :order_by_publication_date, -> { order(publication_date: :asc, created_at: :asc) } @@ -25,9 +25,4 @@ class Milestone < ActiveRecord::Base 80 end - private - - def assign_milestone_to_translations - translations.each { |translation| translation.globalized_model = self } - end end diff --git a/app/models/poll.rb b/app/models/poll.rb index 35b888c90..4733432c3 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -28,7 +28,6 @@ class Poll < ActiveRecord::Base validate :date_range scope :current, -> { where('starts_at <= ? and ? <= ends_at', Date.current.beginning_of_day, Date.current.beginning_of_day) } - scope :incoming, -> { where('? < starts_at', Date.current.beginning_of_day) } scope :expired, -> { where('ends_at < ?', Date.current.beginning_of_day) } scope :recounting, -> { Poll.where(ends_at: (Date.current.beginning_of_day - RECOUNT_DURATION)..Date.current.beginning_of_day) } scope :published, -> { where('published = ?', true) } @@ -45,20 +44,12 @@ class Poll < ActiveRecord::Base starts_at <= timestamp && timestamp <= ends_at end - def incoming?(timestamp = Date.current.beginning_of_day) - timestamp < starts_at - end - def expired?(timestamp = Date.current.beginning_of_day) ends_at < timestamp end - def self.current_or_incoming - current + incoming - end - - def self.current_or_recounting_or_incoming - current + recounting + incoming + def self.current_or_recounting + current + recounting end def answerable_by?(user) diff --git a/app/models/poll/booth.rb b/app/models/poll/booth.rb index b9cba45b1..e794a0190 100644 --- a/app/models/poll/booth.rb +++ b/app/models/poll/booth.rb @@ -12,7 +12,7 @@ class Poll end def self.available - where(polls: { id: Poll.current_or_recounting_or_incoming }).includes(:polls) + where(polls: { id: Poll.current_or_recounting }).includes(:polls) end def assignment_on_poll(poll) diff --git a/app/models/poll/booth_assignment.rb b/app/models/poll/booth_assignment.rb index 81759ee0f..811b98923 100644 --- a/app/models/poll/booth_assignment.rb +++ b/app/models/poll/booth_assignment.rb @@ -15,6 +15,10 @@ class Poll shifts.empty? ? false : true end + def unable_to_destroy? + (partial_results.count + recounts.count).positive? + end + private def shifts diff --git a/app/models/poll/shift.rb b/app/models/poll/shift.rb index d9803f237..13b5c2009 100644 --- a/app/models/poll/shift.rb +++ b/app/models/poll/shift.rb @@ -35,6 +35,10 @@ class Poll end end + def unable_to_destroy? + booth.booth_assignments.map(&:unable_to_destroy?).any? + end + def destroy_officer_assignments Poll::OfficerAssignment.where(booth_assignment: booth.booth_assignments, officer: officer, diff --git a/app/models/progress_bar.rb b/app/models/progress_bar.rb new file mode 100644 index 000000000..2f494196e --- /dev/null +++ b/app/models/progress_bar.rb @@ -0,0 +1,23 @@ +class ProgressBar < ActiveRecord::Base + self.inheritance_column = nil + RANGE = 0..100 + + enum kind: %i[primary secondary] + + belongs_to :progressable, polymorphic: true + + translates :title, touch: true + include Globalizable + + validates :progressable, presence: true + validates :kind, presence: true, + uniqueness: { + scope: [:progressable_type, :progressable_id], + conditions: -> { primary } + } + validates :percentage, presence: true, inclusion: RANGE, numericality: { only_integer: true } + + before_validation :assign_model_to_translations + validates_translation :title, presence: true, unless: :primary? + +end diff --git a/app/models/progress_bar/translation.rb b/app/models/progress_bar/translation.rb new file mode 100644 index 000000000..d61f1d47b --- /dev/null +++ b/app/models/progress_bar/translation.rb @@ -0,0 +1,3 @@ +class ProgressBar::Translation < Globalize::ActiveRecord::Translation + delegate :primary?, to: :globalized_model +end diff --git a/app/models/site_customization/image.rb b/app/models/site_customization/image.rb index c3219e427..e933c40a0 100644 --- a/app/models/site_customization/image.rb +++ b/app/models/site_customization/image.rb @@ -4,13 +4,14 @@ class SiteCustomization::Image < ActiveRecord::Base "social_media_icon" => [470, 246], "social_media_icon_twitter" => [246, 246], "apple-touch-icon-200" => [200, 200], - "budget_execution_no_image" => [800, 600] + "budget_execution_no_image" => [800, 600], + "map" => [420, 500] } has_attached_file :image validates :name, presence: true, uniqueness: true, inclusion: { in: VALID_IMAGES.keys } - validates_attachment_content_type :image, content_type: ["image/png"] + validates_attachment_content_type :image, content_type: ["image/png", "image/jpeg"] validate :check_image def self.all_images diff --git a/app/models/site_customization/page.rb b/app/models/site_customization/page.rb index 9940e66d9..6dd8f8d2f 100644 --- a/app/models/site_customization/page.rb +++ b/app/models/site_customization/page.rb @@ -1,5 +1,6 @@ class SiteCustomization::Page < ActiveRecord::Base - VALID_STATUSES = %w(draft published) + VALID_STATUSES = %w[draft published] + has_many :cards, class_name: "Widget::Card", foreign_key: "site_customization_page_id" translates :title, touch: true translates :subtitle, touch: true @@ -12,9 +13,12 @@ class SiteCustomization::Page < ActiveRecord::Base format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format } validates :status, presence: true, inclusion: { in: VALID_STATUSES } - scope :published, -> { where(status: 'published').order('id DESC') } - scope :with_more_info_flag, -> { where(status: 'published', more_info_flag: true).order('id ASC') } - scope :with_same_locale, -> { joins(:translations).where("site_customization_page_translations.locale": I18n.locale) } + scope :published, -> { where(status: "published").sort_desc } + scope :sort_asc, -> { order("id ASC") } + scope :sort_desc, -> { order("id DESC") } + scope :with_more_info_flag, -> { where(status: "published", more_info_flag: true).sort_asc } + scope :with_same_locale, -> { joins(:translations).locale } + scope :locale, -> { where("site_customization_page_translations.locale": I18n.locale) } def url "/#{slug}" diff --git a/app/models/tag.rb b/app/models/tag.rb new file mode 100644 index 000000000..ef3d4af06 --- /dev/null +++ b/app/models/tag.rb @@ -0,0 +1,2 @@ +class Tag < ActsAsTaggableOn::Tag +end diff --git a/app/models/user.rb b/app/models/user.rb index 3a274f056..0f58594ab 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -127,6 +127,14 @@ class User < ActiveRecord::Base votes.for_budget_investments(Budget::Investment.where(group: group)).exists? end + def headings_voted_within_group(group) + Budget::Heading.order("name").where(id: voted_investments.by_group(group).pluck(:heading_id)) + end + + def voted_investments + Budget::Investment.where(id: votes.for_budget_investments.pluck(:votable_id)) + end + def administrator? administrator.present? end diff --git a/app/models/widget/card.rb b/app/models/widget/card.rb index 4a7733e24..5ec0d4944 100644 --- a/app/models/widget/card.rb +++ b/app/models/widget/card.rb @@ -1,5 +1,6 @@ class Widget::Card < ActiveRecord::Base include Imageable + belongs_to :page, class_name: "SiteCustomization::Page", foreign_key: "site_customization_page_id" # table_name must be set before calls to 'translates' self.table_name = "widget_cards" @@ -15,6 +16,12 @@ class Widget::Card < ActiveRecord::Base end def self.body - where(header: false).order(:created_at) + where(header: false, site_customization_page_id: nil).order(:created_at) end + + #add widget cards to custom pages + def self.page(page_id) + where(site_customization_page_id: page_id) + end + end diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 6e393e805..acc59b45a 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -56,8 +56,7 @@ <% end %> <% if feature?(:budgets) %> -
<%= t("admin.legislation.processes.form.color_help") %>
+<%= t("admin.legislation.processes.form.color_help") %>
+| - <%= l poll.starts_at.to_date %> - <%= l poll.ends_at.to_date %> + | + <%= l poll.starts_at.to_date %> | -
-
+
+ <%= l poll.ends_at.to_date %>
+ |
+
<%= link_to t("admin.actions.edit"),
edit_admin_poll_path(poll),
- class: "button hollow expanded" %>
-
- |
diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb
index ece32decb..2881adb36 100644
--- a/app/views/admin/poll/polls/index.html.erb
+++ b/app/views/admin/poll/polls/index.html.erb
@@ -7,8 +7,9 @@
<% if @polls.any? %>
+ class: "button hollow" %>
+
<%= link_to t("admin.actions.configure"),
admin_poll_path(poll),
- class: "button hollow expanded" %>
-
+ class: "button hollow " %>
+ <%= t("admin.progress_bars.index.no_progress_bars") %>
+
+<% end %>
diff --git a/app/views/admin/progress_bars/edit.html.erb b/app/views/admin/progress_bars/edit.html.erb
new file mode 100644
index 000000000..21dd27d9a
--- /dev/null
+++ b/app/views/admin/progress_bars/edit.html.erb
@@ -0,0 +1,15 @@
+<% if @progress_bar.primary? %>
+ <% bar_title = t("admin.progress_bars.edit.title.primary") %>
+<% else %>
+ <% bar_title = t("admin.progress_bars.edit.title.secondary", title: @progress_bar.title) %>
+<% end %>
+
+<% provide :title do %>
+ <%= "#{t("admin.header.title")} - #{bar_title}" %>
+<% end %>
+
+<%= back_link_to progress_bars_index %>
+
+<%= bar_title %>+ +<%= render "form" %> diff --git a/app/views/admin/progress_bars/index.html.erb b/app/views/admin/progress_bars/index.html.erb new file mode 100644 index 000000000..bcac8d7a4 --- /dev/null +++ b/app/views/admin/progress_bars/index.html.erb @@ -0,0 +1,9 @@ +<% provide :title do %> + <%= "#{t("admin.header.title")} - #{t("admin.progress_bars.index.title")}" %> +<% end %> + +<%= back_link_to polymorphic_path([:admin, *resource_hierarchy_for(@progressable)]) %> + + + +<%= render "admin/progress_bars/progress_bars", progressable: @progressable %> diff --git a/app/views/admin/progress_bars/new.html.erb b/app/views/admin/progress_bars/new.html.erb new file mode 100644 index 000000000..8c379ac3a --- /dev/null +++ b/app/views/admin/progress_bars/new.html.erb @@ -0,0 +1,9 @@ +<% provide :title do %> + <%= "#{t("admin.header.title")} - #{t("admin.progress_bars.new.creating")}" %> +<% end %> + +<%= back_link_to progress_bars_index %> + +<%= t("admin.progress_bars.new.creating") %>+ +<%= render "form" %> diff --git a/app/views/admin/settings/_configuration.html.erb b/app/views/admin/settings/_configuration.html.erb index f2d5a7605..2bca8b9ea 100644 --- a/app/views/admin/settings/_configuration.html.erb +++ b/app/views/admin/settings/_configuration.html.erb @@ -19,10 +19,10 @@
<%= form_for(setting, url: admin_setting_path(setting), html: { id: "edit_#{dom_id(setting)}"}) do |f| %>
- |
+
<%= f.text_area :value, label: false, id: dom_id(setting), lines: 1 %>
-
+
<%= f.submit(t('admin.settings.index.update_setting'), class: "button hollow expanded") %>
<% end %>
diff --git a/app/views/admin/shared/_common_globalize_locales.html.erb b/app/views/admin/shared/_common_globalize_locales.html.erb
index b4633cde2..7b7e82821 100644
--- a/app/views/admin/shared/_common_globalize_locales.html.erb
+++ b/app/views/admin/shared/_common_globalize_locales.html.erb
@@ -1,18 +1,20 @@
-<% I18n.available_locales.each do |locale| %>
-
- <%= link_to t("admin.translations.remove_language"), "#",
- id: "js_delete_#{locale}",
- style: display_translation_style(resource, locale),
- class: 'delete js-delete-language',
- data: { locale: locale } %>
+
+ <% I18n.available_locales.each do |locale| %>
+
+ <%= link_to t("admin.translations.remove_language"), "#",
+ id: "js_delete_#{locale}",
+ style: display_translation_style(resource, locale),
+ class: 'delete js-delete-language',
+ data: { locale: locale } %>
+
+ <% end %>
+
+ <%= render "admin/shared/globalize_tabs", resource: resource, display_style: display_style %>
+
+
+ <%= select_tag :translation_locale,
+ options_for_locale_select,
+ prompt: t("admin.translations.add_language"),
+ class: "js-globalize-locale" %>
-<% end %>
-
-<%= render "admin/shared/globalize_tabs", resource: resource, display_style: display_style %>
-
-
- <%= select_tag :translation_locale,
- options_for_locale_select,
- prompt: t("admin.translations.add_language"),
- class: "js-globalize-locale" %>
diff --git a/app/views/admin/shared/_globalize_tabs.html.erb b/app/views/admin/shared/_globalize_tabs.html.erb
index 15ed0ff09..9b9fc81af 100644
--- a/app/views/admin/shared/_globalize_tabs.html.erb
+++ b/app/views/admin/shared/_globalize_tabs.html.erb
@@ -1,4 +1,4 @@
-
|