Merge branch 'legislation-module-stable' of https://github.com/medialab-prado/consul into medialab-legislation

This commit is contained in:
decabeza
2017-05-22 18:43:49 +02:00
177 changed files with 10710 additions and 125 deletions

View File

@@ -66,6 +66,9 @@ gem 'turnout', '~> 2.4.0'
gem 'redcarpet', '~> 3.4.0' gem 'redcarpet', '~> 3.4.0'
gem 'paperclip' gem 'paperclip'
gem 'rails-assets-markdown-it', source: 'https://rails-assets.org'
gem 'cocoon'
group :development, :test do group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console # Call 'byebug' anywhere in the code to stop execution and get a debugger console

View File

@@ -1,5 +1,6 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
remote: https://rails-assets.org/
specs: specs:
actionmailer (4.2.8) actionmailer (4.2.8)
actionpack (= 4.2.8) actionpack (= 4.2.8)
@@ -101,6 +102,7 @@ GEM
cliver (0.3.2) cliver (0.3.2)
cocaine (0.5.8) cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
cocoon (1.2.9)
coffee-rails (4.2.1) coffee-rails (4.2.1)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.2.x) railties (>= 4.0.0, < 5.2.x)
@@ -318,6 +320,7 @@ GEM
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.2.8) railties (= 4.2.8)
sprockets-rails sprockets-rails
rails-assets-markdown-it (8.2.1)
rails-deprecated_sanitizer (1.0.3) rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha) activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.8) rails-dom-testing (1.0.8)
@@ -482,6 +485,7 @@ DEPENDENCIES
capistrano3-delayed-job (~> 1.7.3) capistrano3-delayed-job (~> 1.7.3)
capybara (~> 2.14.0) capybara (~> 2.14.0)
ckeditor (~> 4.2.3) ckeditor (~> 4.2.3)
cocoon
coffee-rails (~> 4.2.1) coffee-rails (~> 4.2.1)
coveralls (~> 0.8.21) coveralls (~> 0.8.21)
daemons daemons
@@ -519,6 +523,7 @@ DEPENDENCIES
poltergeist (~> 1.15.0) poltergeist (~> 1.15.0)
quiet_assets quiet_assets
rails (= 4.2.8) rails (= 4.2.8)
rails-assets-markdown-it!
redcarpet (~> 3.4.0) redcarpet (~> 3.4.0)
responders (~> 2.4.0) responders (~> 2.4.0)
rinku (~> 2.0.2) rinku (~> 2.0.2)

View File

@@ -50,6 +50,15 @@
//= require banners //= require banners
//= require social_share //= require social_share
//= require checkbox_toggle //= require checkbox_toggle
//= require markdown-it
//= require markdown_editor
//= require cocoon
//= require legislation_admin
//= require legislation
//= require legislation_allegations
//= require legislation_annotatable
//= require watch_form_changes
//= require tree_navigator
//= require custom //= require custom
var initialize_modules = function() { var initialize_modules = function() {
@@ -76,6 +85,14 @@ var initialize_modules = function() {
App.Banners.initialize(); App.Banners.initialize();
App.SocialShare.initialize(); App.SocialShare.initialize();
App.CheckboxToggle.initialize(); App.CheckboxToggle.initialize();
App.MarkdownEditor.initialize();
App.LegislationAdmin.initialize();
App.LegislationAllegations.initialize();
App.Legislation.initialize();
if ( $(".legislation-annotatable").length )
App.LegislationAnnotatable.initialize();
App.WatchFormChanges.initialize();
App.TreeNavigator.initialize();
}; };
$(function(){ $(function(){

View File

@@ -0,0 +1,25 @@
App.Legislation =
initialize: ->
$('#js-toggle-debate').on
click: ->
$('#debate-show').toggle()
$('#js-toggle-small-debate').on
click: ->
$('#debate-show').toggle()
$('span').toggleClass('icon-angle-up')
$('form#new_legislation_answer input.button').hide()
$('form#new_legislation_answer input[type=radio]').on
click: ->
$('form#new_legislation_answer').submit()
$('form#draft_version_go_to_version input.button').hide()
$('form#draft_version_go_to_version select').on
change: ->
$('form#draft_version_go_to_version').submit()
$('#js-toggle-legislation-process-header').on
click: ->
$('[data-target="legislation-header-full"]').toggle()

View File

@@ -0,0 +1,14 @@
App.LegislationAdmin =
initialize: ->
$("input[type='checkbox'][data-disable-date]").on
change: ->
checkbox = $(this)
parent = $(this).parents('.row:eq(0)')
date_selector = $(this).data('disable-date')
parent.find("input[type='text'][id^='"+date_selector+"']").each ->
if checkbox.is(':checked')
$(this).removeAttr("disabled")
else
$(this).val("")

View File

@@ -0,0 +1,25 @@
App.LegislationAllegations =
toggle_comments: ->
if !App.LegislationAnnotatable.isMobile()
$('.draft-allegation').toggleClass('comments-on')
$('#comments-box').html('').hide()
show_comments: ->
if !App.LegislationAnnotatable.isMobile()
$('.draft-allegation').addClass('comments-on')
initialize: ->
$('.js-toggle-allegations .draft-panel').on
click: (e) ->
e.preventDefault()
e.stopPropagation()
if !App.LegislationAnnotatable.isMobile()
App.LegislationAllegations.toggle_comments()
$('.js-toggle-allegations').on
click: (e) ->
# Toggle comments when the section title is visible
if !App.LegislationAnnotatable.isMobile()
if $(this).find('.draft-panel .panel-title:visible').length == 0
App.LegislationAllegations.toggle_comments()

View File

@@ -0,0 +1,215 @@
_t = (key) -> new Gettext().gettext(key)
App.LegislationAnnotatable =
makeEditableAndHighlight: (colour) ->
sel = window.getSelection()
if sel.rangeCount and sel.getRangeAt
range = sel.getRangeAt(0)
document.designMode = 'on'
if range
sel.removeAllRanges()
sel.addRange range
# Use HiliteColor since some browsers apply BackColor to the whole block
if !document.execCommand('HiliteColor', false, colour)
document.execCommand 'BackColor', false, colour
document.designMode = 'off'
return
highlight: (colour) ->
if window.getSelection
# IE9 and non-IE
try
if !document.execCommand('BackColor', false, colour)
App.LegislationAnnotatable.makeEditableAndHighlight colour
catch ex
App.LegislationAnnotatable.makeEditableAndHighlight colour
else if document.selection and document.selection.createRange
# IE <= 8 case
range = document.selection.createRange()
range.execCommand 'BackColor', false, colour
return
remove_highlight: ->
$('[data-legislation-draft-version-id] span[style]').replaceWith(->
return $(this).contents()
)
return
renderAnnotationComments: (event) ->
if event.offset
$("#comments-box").css({top: event.offset - $('.calc-comments').offset().top})
if App.LegislationAnnotatable.isMobile()
return
$.ajax
method: "GET"
url: event.annotation_url + "/annotations/" + event.annotation_id + "/comments"
dataType: 'script'
onClick: (event) ->
event.preventDefault()
event.stopPropagation()
if App.LegislationAnnotatable.isMobile()
annotation_url = $(event.target).closest(".legislation-annotatable").data("legislation-annotatable-base-url")
window.location.href = annotation_url + "/annotations/" + $(this).data('annotation-id')
return
$('[data-annotation-id]').removeClass('current-annotation')
target = $(this)
parents = target.parents('.annotator-hl')
parents_ids = parents.map (_, elem) ->
$(elem).data("annotation-id")
annotation_id = target.data('annotation-id')
$('[data-annotation-id="'+annotation_id+'"]').addClass('current-annotation')
$('#comments-box').html('')
App.LegislationAllegations.show_comments()
$("#comments-box").show()
$.event.trigger
type: "renderLegislationAnnotation"
annotation_id: target.data("annotation-id")
annotation_url: target.closest(".legislation-annotatable").data("legislation-annotatable-base-url")
offset: target.offset()["top"]
parents_ids.each (i, pid) ->
$.event.trigger
type: "renderLegislationAnnotation"
annotation_id: pid
annotation_url: target.closest(".legislation-annotatable").data("legislation-annotatable-base-url")
isMobile: () ->
return window.innerWidth <= 652
viewerExtension: (viewer) ->
viewer._onHighlightMouseover = (event) ->
return
customShow: (position) ->
$(@element).html ''
# Clean comments section and open it
$('#comments-box').html ''
App.LegislationAllegations.show_comments()
$('#comments-box').show()
annotation_url = $('[data-legislation-annotatable-base-url]').data('legislation-annotatable-base-url')
$.ajax(
method: 'GET'
url: annotation_url + '/annotations/new'
dataType: 'script').done (->
$('#new_legislation_annotation #legislation_annotation_quote').val(@annotation.quote)
$('#new_legislation_annotation #legislation_annotation_ranges').val(JSON.stringify(@annotation.ranges))
$('#comments-box').css({top: position.top - $('.calc-comments').offset().top})
unless $('[data-legislation-open-phase]').data('legislation-open-phase') == false
App.LegislationAnnotatable.highlight('#7fff9a')
$('#comments-box textarea').focus()
$("#new_legislation_annotation").on("ajax:complete", (e, data, status, xhr) ->
App.LegislationAnnotatable.app.destroy()
if data.status == 200
App.LegislationAnnotatable.remove_highlight()
$("#comments-box").html("").hide()
$.ajax
method: "GET"
url: annotation_url + "/annotations/" + data.responseJSON.id + "/comments"
dataType: 'script'
else
$(e.target).find('label').addClass('error')
$('<small class="error">' + data.responseJSON[0] + '</small>').insertAfter($(e.target).find('textarea'))
return true
)
return
).bind(this)
editorExtension: (editor) ->
editor.show = App.LegislationAnnotatable.customShow
scrollToAnchor: ->
annotationsLoaded: (annotations) ->
anchor = $(location).attr('hash')
if anchor && anchor.startsWith('#annotation')
ann_id = anchor.split("-")[-1..]
checkExist = setInterval((->
if $("span[data-annotation-id='" + ann_id + "']").length
el = $("span[data-annotation-id='" + ann_id + "']")
el.addClass('current-annotation')
$('#comments-box').html('')
App.LegislationAllegations.show_comments()
$('html,body').animate({scrollTop: el.offset().top})
$.event.trigger
type: "renderLegislationAnnotation"
annotation_id: ann_id
annotation_url: el.closest(".legislation-annotatable").data("legislation-annotatable-base-url")
offset: el.offset()["top"]
clearInterval checkExist
return
), 100)
propotionalWeight: (v, max) ->
Math.floor(v*5/(max+1)) + 1
addWeightClasses: ->
annotationsLoaded: (annotations) ->
return if annotations.length == 0
weights = annotations.map (ann) -> ann.weight
max_weight = Math.max.apply(null, weights)
last_annotation = annotations[annotations.length - 1]
checkExist = setInterval((->
if $("span[data-annotation-id='" + last_annotation.id + "']").length
for annotation in annotations
ann_weight = App.LegislationAnnotatable.propotionalWeight(annotation.weight, max_weight)
el = $("span[data-annotation-id='" + annotation.id + "']")
el.addClass('weight-' + ann_weight)
clearInterval checkExist
return
), 100)
initialize: ->
$(document).off("renderLegislationAnnotation").on("renderLegislationAnnotation", App.LegislationAnnotatable.renderAnnotationComments)
$(document).off('click', '[data-annotation-id]').on('click', '[data-annotation-id]', App.LegislationAnnotatable.onClick)
$(document).off('click', '[data-cancel-annotation]').on('click', '[data-cancel-annotation]', (e) ->
e.preventDefault()
$('#comments-box').html('')
$('#comments-box').hide()
App.LegislationAnnotatable.remove_highlight()
return
)
current_user_id = $('html').data('current-user-id')
$(".legislation-annotatable").each ->
$this = $(this)
ann_type = "legislation_draft_version"
ann_id = $this.data("legislation-draft-version-id")
base_url = $this.data("legislation-annotatable-base-url")
App.LegislationAnnotatable.app = new annotator.App()
.include ->
beforeAnnotationCreated: (ann) ->
ann["legislation_draft_version_id"] = ann_id
ann.permissions = ann.permissions || {}
ann.permissions.admin = []
.include(annotator.ui.main, {
element: this,
viewerExtensions: [App.LegislationAnnotatable.viewerExtension],
editorExtensions: [App.LegislationAnnotatable.editorExtension]
})
.include(App.LegislationAnnotatable.scrollToAnchor)
.include(App.LegislationAnnotatable.addWeightClasses)
.include(annotator.storage.http, { prefix: base_url, urls: { search: "/annotations/search" } })
App.LegislationAnnotatable.app.start().then ->
App.LegislationAnnotatable.app.ident.identity = current_user_id
options = {}
options["legislation_draft_version_id"] = ann_id
App.LegislationAnnotatable.app.annotations.load(options)

View File

@@ -0,0 +1,39 @@
App.MarkdownEditor =
refresh_preview: (element, md) ->
textarea_content = element.find('textarea').val()
result = md.render(textarea_content)
element.find('#markdown-preview').html(result)
initialize: ->
$('.markdown-editor').each ->
md = window.markdownit({
html: true,
breaks: true,
typographer: true,
})
App.MarkdownEditor.refresh_preview($(this), md)
$(this).on 'change input paste keyup', ->
App.MarkdownEditor.refresh_preview($(this), md)
$('.legislation-draft-versions-edit .warning').show()
return
$(this).find('textarea').on 'scroll', ->
$('#markdown-preview').scrollTop($(this).scrollTop())
$(this).find('.fullscreen-toggle').on 'click', ->
$('.markdown-editor').toggleClass('fullscreen')
$('.fullscreen-container').toggleClass('medium-8', 'medium-12')
span = $(this).find('span')
current_html = span.html()
if(current_html == span.data('open-text'))
span.html(span.data('closed-text'))
else
span.html(span.data('open-text'))
if $('.markdown-editor').hasClass('fullscreen')
$('.markdown-editor textarea').height($(window).height() - 100)
else
$('.markdown-editor textarea').height("10em")

View File

@@ -0,0 +1,37 @@
App.TreeNavigator =
setNodes: (nodes) ->
children = nodes.children('ul')
if(children.length == 0)
return
children.each ->
link = $(this).prev('a')
$('<span class="open"></span>').insertBefore(link)
App.TreeNavigator.setNodes($(this).children())
initialize: ->
elem = $('[data-tree-navigator]')
if(elem.length == 0)
return
ul = elem.find('ul:eq(0)')
if(ul.length && ul.children().length)
App.TreeNavigator.setNodes(ul.children())
$('[data-tree-navigator] span').on
click: (e) ->
elem = $(this)
if(elem.hasClass('open'))
elem.removeClass('open').addClass('closed')
elem.siblings('ul').hide()
else if(elem.hasClass('closed'))
elem.removeClass('closed').addClass('open')
elem.siblings('ul').show()
if anchor = $(location).attr('hash')
if link = elem.find('a[href="'+anchor+'"]')
link.parents('ul').each ->
$(this).show()
$(this).siblings('span').removeClass('closed').addClass('open')

View File

@@ -13,4 +13,6 @@ App.Votes =
initialize: -> initialize: ->
App.Votes.hoverize "div.votes" App.Votes.hoverize "div.votes"
App.Votes.hoverize "div.supports" App.Votes.hoverize "div.supports"
App.Votes.hoverize "div.debate-questions"
App.Votes.hoverize "div.comment-footer"
false false

View File

@@ -0,0 +1,30 @@
App.WatchFormChanges =
forms: ->
return $('form[data-watch-changes]')
msg: ->
if($('[data-watch-form-message]').length)
return $('[data-watch-form-message]').data('watch-form-message')
checkChanges: (event) ->
changes = false
App.WatchFormChanges.forms().each ->
form = $(this)
if form.serialize() != form.data('watchChanges')
changes = true
if changes
return confirm(App.WatchFormChanges.msg())
else
return true
initialize: ->
if App.WatchFormChanges.forms().length == 0 || App.WatchFormChanges.msg() == undefined
return
$(document).off('page:before-change').on('page:before-change', (e) -> App.WatchFormChanges.checkChanges(e))
App.WatchFormChanges.forms().each ->
form = $(this)
form.data('watchChanges', form.serialize())
false

View File

@@ -164,6 +164,7 @@ $header-font-family: $body-font-family;
$header-font-weight: $global-weight-normal; $header-font-weight: $global-weight-normal;
$header-font-style: normal; $header-font-style: normal;
$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; $font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
$font-family-serif: Georgia, 'Times New Roman', Times, serif;
$header-sizes: ( $header-sizes: (
small: ( small: (
'h1': 34, 'h1': 34,

View File

@@ -6,6 +6,8 @@
// 04. Stats // 04. Stats
// 05. Management // 05. Management
// 06. Polls // 06. Polls
// 07. Legislation
// 08. CMS
// //
// 01. Global styles // 01. Global styles
@@ -538,7 +540,75 @@ table {
} }
} }
// 07. CMS // 07. Legislation
// --------------
// Markdown Editor
// ---------------
.markdown-editor {
background-color: white;
.markdown-area,
#markdown-preview {
display: none;
}
}
.markdown-editor #markdown-preview {
overflow-y: auto;
height: 15em;
}
.markdown-editor textarea {
height: 15em;
}
.markdown-editor.fullscreen {
z-index: 9999;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
}
.markdown-editor.fullscreen #markdown-preview {
height: 99%;
}
.edit_legislation_draft_version .row {
margin-bottom: 2rem;
}
.legislation-admin {
.menu .active > a {
background: none;
}
}
.legislation-process-save {
@include breakpoint(medium) {
float: right;
}
}
.legislation-question-delete {
@include breakpoint(medium) {
text-align: right;
}
}
.legislation-process-index {
.legislation-process-new {
@include breakpoint(medium) {
text-align: right;
}
}
}
// 08. CMS
// -------------- // --------------
.cms_page_list { .cms_page_list {
@@ -547,3 +617,289 @@ table {
vertical-align: middle; vertical-align: middle;
} }
} }
.legislation-process-edit {
.edit_legislation_process {
small {
color: $text-medium;
}
input[type]:not([type="submit"]):not([type="file"]):not([type="checkbox"]):not([type="radio"]) {
background: $white;
}
.legislation-process-start, .legislation-process-end {
@include breakpoint(medium) {
line-height: 3rem;
}
}
.legislation-process-end {
@include breakpoint(medium) {
text-align: right;
}
}
}
}
.legislation-draft-versions-index {
.legislation-process-question {
@include breakpoint(medium) {
text-align: right;
}
}
table tr td {
padding: 0.25rem 0.375rem;
}
}
.legislation-questions-form {
input[type]:not([type="submit"]):not([type="file"]):not([type="checkbox"]):not([type="radio"]) {
background: $white;
margin-bottom: 0;
@include breakpoint(medium) {
margin-bottom: 1rem;
}
}
input::-webkit-input-placeholder {
font-style: italic;
}
input:-moz-placeholder { /* Firefox 18- */
font-style: italic;
}
input::-moz-placeholder { /* Firefox 19+ */
font-style: italic;
}
input:-ms-input-placeholder {
font-style: italic;
}
.legislation-questions-answers {
margin-bottom: 1rem;
}
.field {
margin-bottom: 1rem;
@include breakpoint(medium) {
margin-bottom: 0;
}
a {
line-height: 3rem;
color: $delete;
span {
text-decoration: underline;
}
.icon-x {
vertical-align: sub;
text-decoration: none;
line-height: 0;
}
&:active,
&:focus,
&:hover {
text-decoration: none;
}
}
}
}
.legislation-draft-versions-form {
.legislation-process-version {
@include breakpoint(medium) {
text-align: right;
}
}
input[type]:not([type="submit"]):not([type="file"]):not([type="checkbox"]):not([type="radio"]) {
background: $white;
}
.control {
cursor: pointer;
margin-bottom: 1rem;
small {
display: block;
margin-top: -1rem;
color: $text-medium;
@include breakpoint(medium) {
margin-left: 0.25rem;
display: inline-block;
margin-top: 0;
}
}
}
.fullscreen-container {
text-align: center;
background: #ccdbe6;
.markdown-editor-header,
.markdown-editor-buttons {
display: none;
}
a {
line-height: 8rem;
span {
text-decoration: none;
font-size: $small-font-size;
}
.icon-expand {
margin-left: 0.25rem;
vertical-align: sub;
text-decoration: none;
line-height: 0;
}
&:active,
&:focus,
&:hover {
text-decoration: none;
}
}
}
#legislation_draft_version_body {
font-family: $font-family-serif;
background: #f5f5f5;
height: 16em;
&:focus {
border: 1px solid #cacaca;
box-shadow: inset 0 1px 2px rgba(34, 34, 34, 0.1);
}
}
#markdown-preview {
font-family: $font-family-serif;
border: 1px solid #cacaca;
margin-bottom: 2rem;
h1, h2, h3, h4, h5, h6 {
font-family: $font-family-serif !important;
font-size: 1rem;
line-height: 1.625rem;
margin-bottom: 0;
}
p {
font-size: 1rem;
line-height: 1.625rem;
}
}
.fullscreen {
.markdown-area,
#markdown-preview {
display: block;
}
.column {
padding: 0;
}
.fullscreen-container {
text-align: left;
background: $admin-color;
padding: 0.5rem 1rem;
margin-bottom: 0;
a {
line-height: 3rem;
@include breakpoint(medium) {
float: right;
}
}
.markdown-editor-header {
vertical-align: top;
display: inline-block;
color: $white;
@include breakpoint(medium) {
line-height: 3rem;
}
}
.truncate {
@include breakpoint(medium) {
width: 40vw;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.markdown-editor-buttons {
display: block;
@include breakpoint(medium) {
display: inline-block;
float: right;
padding-left: 1rem;
}
input {
font-size: $small-font-size;
padding: 0.5em 1em;
margin-left: 0;
margin-bottom: 0;
margin-top: 1rem;
@include breakpoint(medium) {
margin: 0.5rem;
}
}
}
a {
color: $white;
}
}
#legislation_draft_version_body {
border-radius: 0;
padding: 1rem;
border: none;
@include breakpoint(medium) {
padding: 1rem 2rem;
}
&:focus {
border: none;
}
}
#markdown-preview {
padding: 1rem;
border: none;
@include breakpoint(medium) {
padding: 1rem 2rem;
}
}
}
}

View File

@@ -97,3 +97,28 @@
} }
} }
} }
.annotator-hl {
cursor: pointer;
background: rgba(255, 255, 10, 0.2);
}
.annotator-hl.weight-1 {
background: #FFF9DA;
}
.annotator-hl.weight-2 {
background: #FFF5BC;
}
.annotator-hl.weight-3 {
background: #FFF1A2;
}
.annotator-hl.weight-4 {
background: #FFEF8C;
}
.annotator-hl.weight-5 {
background: #FFE95F;
}
.current-annotation {
text-decoration: underline;
}

View File

@@ -7,6 +7,8 @@
@import "layout"; @import "layout";
@import "participation"; @import "participation";
@import "pages"; @import "pages";
@import "legislation";
@import "legislation_process";
@import "custom"; @import "custom";
@import "c3"; @import "c3";
@import "annotator.min"; @import "annotator.min";

View File

@@ -1,5 +1,4 @@
@charset "UTF-8"; @charset "UTF-8";
@font-face { @font-face {
font-family: 'icons'; font-family: 'icons';
src: font-url('icons.eot'); src: font-url('icons.eot');
@@ -10,7 +9,6 @@
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
[data-icon]:before { [data-icon]:before {
font-family: "icons" !important; font-family: "icons" !important;
content: attr(data-icon); content: attr(data-icon);
@@ -23,7 +21,6 @@
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
[class^="icon-"]:before, [class^="icon-"]:before,
[class*=" icon-"]:before { [class*=" icon-"]:before {
font-family: "icons" !important; font-family: "icons" !important;
@@ -36,7 +33,6 @@
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-angle-down:before { .icon-angle-down:before {
content: "\61"; content: "\61";
} }
@@ -184,12 +180,18 @@
.icon-arrow-top:before { .icon-arrow-top:before {
content: "\57"; content: "\57";
} }
.icon-help-1:before {
content: "\58";
}
.icon-checkmark-circle:before { .icon-checkmark-circle:before {
content: "\59"; content: "\59";
} }
.icon-minus-square:before {
content: "\58";
}
.icon-plus-square:before {
content: "\5a";
}
.icon-expand:before {
content: "\30";
}
.icon-telegram:before { .icon-telegram:before {
content: "\31"; content: "\31";
} }

View File

@@ -0,0 +1,131 @@
// Table of Contents
//
// 01. Hero
// 02. Sidebar menu
// 03. Legislation cards
//
// 01. Hero
// -----------------
.brand-heading {
background: $brand;
margin-bottom: 5rem;
.column {
padding-top: 10rem;
padding-bottom: 10rem;
h4 {
font-weight: 400;
text-align: center;
color: white;
}
}
}
// 02. Sidebar menu
// -----------------
.legislation-categories {
.menu.simple {
border-bottom: none;
list-style: none;
padding-left: 0;
margin-left: 0;
margin-top: 0;
@include breakpoint(medium) {
margin: 1.5rem 0;
}
li {
display: block;
cursor: pointer;
margin-bottom: 1rem;
@include breakpoint(medium) {
margin-bottom: 2rem;
max-width: 80%;
}
}
li.active {
font-weight: 700;
}
}
}
// 03. Legislation cards
// -----------------
.legislation {
margin: 0 0 5rem 0;
background: white;
border: 1px solid;
border-color: #e5e6e9 #dfe0e4 #d0d1d5;
border-radius: 0;
box-shadow: 0px 1px 3px 0 #DEE0E3;
min-height: 12rem;
padding: 2rem 0 0 0;
}
.button-legislation {
background: white;
border: 1px solid #2C9BE5;
color: #2C9BE5;
display: inline-block;
font-weight: 700;
margin-top: rem-calc(12);
.icon-comments {
margin-right: 0.5rem;
color: $text-medium;
transition: color 0.25s ease-out, color 0.25s ease-out;
}
&:hover, &:active {
border: 1px solid lighten(#2C9BE5, 25%);
cursor: pointer;
}
&:hover .icon-comments, &:active .icon-comments {
color: white;
}
}
.legislation-text {
margin-bottom: 1rem;
h3 a {
color: $black;
}
}
.legislation-calendar-info p {
font-size: $small-font-size;
color: $text-medium;
margin-bottom: 0;
}
.legislation-calendar {
background: #E5ECF2;
padding-top: 1rem;
h5 {
margin-left: 0.25rem;
margin-bottom: 0;
color: #61686E;
@include breakpoint(medium) {
margin-left: 0;
}
}
p {
margin-left: 0.25rem;
font-size: $small-font-size;
@include breakpoint(medium) {
margin-left: 0;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -299,7 +299,10 @@
.proposal-show, .proposal-show,
.investment-project-show, .investment-project-show,
.budget-investment-show, .budget-investment-show,
.polls-show { .polls-show,
.debate-quiz,
.budget-investment-show,
.draft-panels {
p { p {
word-wrap: break-word; word-wrap: break-word;
@@ -493,7 +496,7 @@
} }
} }
.debate, .proposal, .investment-project, .budget-investment { .debate, .proposal, .investment-project, .budget-investment, .legislation {
margin: $line-height/4 0; margin: $line-height/4 0;
.panel { .panel {

View File

@@ -0,0 +1,14 @@
class Admin::Legislation::BaseController < Admin::BaseController
include FeatureFlags
feature_flag :legislation
helper_method :namespace
private
def namespace
"admin"
end
end

View File

@@ -0,0 +1,44 @@
class Admin::Legislation::DraftVersionsController < Admin::Legislation::BaseController
load_and_authorize_resource :process, class: "Legislation::Process"
load_and_authorize_resource :draft_version, class: "Legislation::DraftVersion", through: :process
def index
@draft_versions = @process.draft_versions
end
def create
if @draft_version.save
redirect_to admin_legislation_process_draft_versions_path, notice: t('admin.legislation.draft_versions.create.notice', link: legislation_process_draft_version_path(@process, @draft_version).html_safe)
else
flash.now[:error] = t('admin.legislation.draft_versions.create.error')
render :new
end
end
def update
if @draft_version.update(draft_version_params)
redirect_to edit_admin_legislation_process_draft_version_path(@process, @draft_version), notice: t('admin.legislation.draft_versions.update.notice', link: legislation_process_draft_version_path(@process, @draft_version).html_safe)
else
flash.now[:error] = t('admin.legislation.draft_versions.update.error')
render :edit
end
end
def destroy
@draft_version.destroy
redirect_to admin_legislation_process_draft_versions_path, notice: t('admin.legislation.draft_versions.destroy.notice')
end
private
def draft_version_params
params.require(:legislation_draft_version).permit(
:title,
:changelog,
:status,
:final_version,
:body,
:body_html
)
end
end

View File

@@ -0,0 +1,54 @@
class Admin::Legislation::ProcessesController < Admin::Legislation::BaseController
has_filters %w{open next past 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])
end
def create
if @process.save
redirect_to edit_admin_legislation_process_path(@process), notice: t('admin.legislation.processes.create.notice', link: legislation_process_path(@process).html_safe)
else
flash.now[:error] = t('admin.legislation.processes.create.error')
render :new
end
end
def update
if @process.update(process_params)
redirect_to edit_admin_legislation_process_path(@process), notice: t('admin.legislation.processes.update.notice', link: legislation_process_path(@process).html_safe)
else
flash.now[:error] = t('admin.legislation.processes.update.error')
render :edit
end
end
def destroy
@process.destroy
redirect_to admin_legislation_processes_path, notice: t('admin.legislation.processes.destroy.notice')
end
private
def process_params
params.require(:legislation_process).permit(
:title,
:description_summary,
:target_summary,
:description,
:target,
:how_to_participate,
:additional_info,
:start_date,
:end_date,
:debate_start_date,
:debate_end_date,
:draft_publication_date,
:allegations_start_date,
:allegations_end_date,
:final_publication_date
)
end
end

View File

@@ -0,0 +1,45 @@
class Admin::Legislation::QuestionsController < Admin::Legislation::BaseController
load_and_authorize_resource :process, class: "Legislation::Process"
load_and_authorize_resource :question, class: "Legislation::Question", through: :process
def index
@questions = @process.questions
end
def new
@question.question_options.build
end
def create
@question.author = current_user
if @question.save
redirect_to admin_legislation_process_questions_path, notice: t('admin.legislation.questions.create.notice', link: legislation_process_question_path(@process, @question).html_safe)
else
flash.now[:error] = t('admin.legislation.questions.create.error')
render :new
end
end
def update
if @question.update(question_params)
redirect_to edit_admin_legislation_process_question_path(@process, @question), notice: t('admin.legislation.questions.update.notice', link: legislation_process_question_path(@process, @question).html_safe)
else
flash.now[:error] = t('admin.legislation.questions.update.error')
render :edit
end
end
def destroy
@question.destroy
redirect_to admin_legislation_process_questions_path, notice: t('admin.legislation.questions.destroy.notice')
end
private
def question_params
params.require(:legislation_question).permit(
:title,
question_options_attributes: [:id, :value, :_destroy]
)
end
end

View File

@@ -24,7 +24,7 @@ class AnnotationsController < ApplicationController
end end
def search def search
@annotations = Annotation.where(legislation_id: params[:legislation_id]) @annotations = Annotation.where(legacy_legislation_id: params[:legacy_legislation_id])
annotations_hash = { total: @annotations.size, rows: @annotations } annotations_hash = { total: @annotations.size, rows: @annotations }
render json: annotations_hash.to_json(methods: :permissions) render json: annotations_hash.to_json(methods: :permissions)
end end
@@ -35,6 +35,6 @@ class AnnotationsController < ApplicationController
params params
.require(:annotation) .require(:annotation)
.permit(:quote, :text, ranges: [:start, :startOffset, :end, :endOffset]) .permit(:quote, :text, ranges: [:start, :startOffset, :end, :endOffset])
.merge(legislation_id: params[:legislation_id]) .merge(legacy_legislation_id: params[:legacy_legislation_id])
end end
end end

View File

@@ -1,6 +1,10 @@
class CommentsController < ApplicationController class CommentsController < ApplicationController
include CustomUrlsHelper
before_action :authenticate_user!, only: :create before_action :authenticate_user!, only: :create
before_action :load_commentable, only: :create before_action :load_commentable, only: :create
before_action :verify_resident_for_commentable!, only: :create
before_action :verify_comments_open!, only: [:create, :vote]
before_action :build_comment, only: :create before_action :build_comment, only: :create
load_and_authorize_resource load_and_authorize_resource
@@ -75,6 +79,22 @@ class CommentsController < ApplicationController
notifiable = comment.commentable notifiable = comment.commentable
end end
Notification.add(notifiable.author_id, notifiable) unless comment.author_id == notifiable.author_id Notification.add(notifiable.author_id, notifiable) unless comment.author_id == notifiable.author_id
end end
def verify_resident_for_commentable!
return if current_user.administrator? || current_user.moderator?
if @commentable.respond_to?(:comments_for_verified_residents_only?) && @commentable.comments_for_verified_residents_only?
verify_resident!
end
end
def verify_comments_open!
return if current_user.administrator? || current_user.moderator?
if @commentable.respond_to?(:comments_closed?) && @commentable.comments_closed?
redirect_to @commentable, alert: t('comments.comments_closed')
end
end
end end

View File

@@ -0,0 +1,8 @@
class LegacyLegislationsController < ApplicationController
load_and_authorize_resource
def show
@legacy_legislation = LegacyLegislation.find(params[:id])
end
end

View File

@@ -0,0 +1,101 @@
class Legislation::AnnotationsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authenticate_user!, only: [:create, :new_comment]
before_action :convert_ranges_parameters, only: [:create]
load_and_authorize_resource :process
load_and_authorize_resource :draft_version, through: :process
load_and_authorize_resource
has_orders %w{most_voted newest oldest}, only: :show
def index
@annotations = @draft_version.annotations
end
def show
@commentable = @annotation
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
set_comment_flags(@comment_tree.comments)
end
def create
if !@process.open_phase?(:allegations) || @draft_version.final_version?
render json: {}, status: :not_found and return
end
existing_annotation = @draft_version.annotations.where(
range_start: annotation_params[:ranges].first[:start], range_start_offset: annotation_params[:ranges].first[:startOffset].to_i,
range_end: annotation_params[:ranges].first[:end], range_end_offset: annotation_params[:ranges].first[:endOffset].to_i).first
if @annotation = existing_annotation
if comment = @annotation.comments.create(body: annotation_params[:text], user: current_user)
render json: @annotation.to_json
else
render json: comment.errors.full_messages, status: :unprocessable_entity
end
else
@annotation = @draft_version.annotations.new(annotation_params)
@annotation.author = current_user
if @annotation.save
track_event
render json: @annotation.to_json
else
render json: @annotation.errors.full_messages, status: :unprocessable_entity
end
end
end
def search
@annotations = @draft_version.annotations.order("LENGTH(quote) DESC")
annotations_hash = { total: @annotations.size, rows: @annotations }
render json: annotations_hash.to_json(methods: :weight)
end
def comments
@annotation = Legislation::Annotation.find(params[:annotation_id])
@comment = @annotation.comments.new
end
def new
respond_to do |format|
format.js
end
end
def new_comment
@draft_version = Legislation::DraftVersion.find(params[:draft_version_id])
@annotation = @draft_version.annotations.find(params[:annotation_id])
@comment = @annotation.comments.new(body: params[:comment][:body], user: current_user)
if @comment.save
@comment = @annotation.comments.new
end
respond_to do |format|
format.js { render :new_comment }
end
end
private
def annotation_params
params
.require(:legislation_annotation)
.permit(:quote, :text, ranges: [:start, :startOffset, :end, :endOffset])
end
def track_event
ahoy.track "legislation_annotation_created".to_sym,
"legislation_annotation_id": @annotation.id,
"legislation_draft_version_id": @draft_version.id
end
def convert_ranges_parameters
if params[:legislation_annotation] && params[:legislation_annotation][:ranges] && params[:legislation_annotation][:ranges].is_a?(String)
params[:legislation_annotation][:ranges] = JSON.parse(params[:legislation_annotation][:ranges])
end
rescue JSON::ParserError
end
end

View File

@@ -0,0 +1,41 @@
class Legislation::AnswersController < Legislation::BaseController
before_action :authenticate_user!
before_action :verify_resident!
load_and_authorize_resource :process
load_and_authorize_resource :question, through: :process
load_and_authorize_resource :answer, through: :question
respond_to :html, :js
def create
if @process.open_phase?(:debate)
@answer.user = current_user
@answer.save
track_event
respond_to do |format|
format.js
format.html { redirect_to legislation_process_question_path(@process, @question) }
end
else
respond_to do |format|
format.js { render json: {} , status: :not_found }
format.html { redirect_to legislation_process_question_path(@process, @question), alert: t('legislation.questions.participation.phase_not_open') }
end
end
end
private
def answer_params
params.require(:legislation_answer).permit(
:legislation_question_option_id,
)
end
def track_event
ahoy.track "legislation_answer_created".to_sym,
"legislation_answer_id": @answer.id,
"legislation_question_option_id": @answer.legislation_question_option_id,
"legislation_question_id": @answer.legislation_question_id
end
end

View File

@@ -0,0 +1,5 @@
class Legislation::BaseController < ApplicationController
include FeatureFlags
feature_flag :legislation
end

View File

@@ -0,0 +1,40 @@
class Legislation::DraftVersionsController < Legislation::BaseController
load_and_authorize_resource :process
load_and_authorize_resource :draft_version, through: :process
def index
end
def show
@draft_versions_list = visible_draft_versions
@draft_version = @draft_versions_list.find(params[:id])
end
def changes
@draft_versions_list = visible_draft_versions
@draft_version = @draft_versions_list.find(params[:draft_version_id])
end
def go_to_version
version = visible_draft_versions.find(params[:draft_version_id])
if params[:redirect_action] == 'changes'
redirect_to legislation_process_draft_version_changes_path(@process, version)
elsif params[:redirect_action] == 'annotations'
redirect_to legislation_process_draft_version_annotations_path(@process, version)
else
redirect_to legislation_process_draft_version_path(@process, version)
end
end
private
def visible_draft_versions
if current_user && current_user.administrator?
@process.draft_versions
else
@process.draft_versions.published
end
end
end

View File

@@ -0,0 +1,78 @@
class Legislation::ProcessesController < Legislation::BaseController
has_filters %w{open next past}, only: :index
load_and_authorize_resource
def index
@current_filter ||= 'open'
@processes = ::Legislation::Process.send(@current_filter).page(params[:page])
end
def show
if @process.active_phase?(:allegations) && @process.show_phase?(:allegations) && draft_version = @process.draft_versions.published.last
redirect_to legislation_process_draft_version_path(@process, draft_version)
elsif @process.active_phase?(:debate)
redirect_to legislation_process_debate_path(@process)
else
redirect_to legislation_process_allegations_path(@process)
end
end
def debate
phase :debate
if @process.show_phase?(:debate)
render :debate
else
render :phase_not_open
end
end
def draft_publication
phase :draft_publication
if @process.show_phase?(@phase)
if draft_version = @process.draft_versions.published.last
redirect_to legislation_process_draft_version_path(@process, draft_version)
else
render :phase_empty
end
else
render :phase_not_open
end
end
def allegations
phase :allegations
if @process.show_phase?(@phase)
if draft_version = @process.draft_versions.published.last
redirect_to legislation_process_draft_version_path(@process, draft_version)
else
render :phase_empty
end
else
render :phase_not_open
end
end
def final_version_publication
phase :final_version_publication
if @process.show_phase?(@phase)
if final_version = @process.final_draft_version
redirect_to legislation_process_draft_version_path(@process, final_version)
else
render :phase_empty
end
else
render :phase_not_open
end
end
private
def phase(phase)
@process = ::Legislation::Process.find(params[:process_id])
@phase = phase
end
end

View File

@@ -0,0 +1,13 @@
class Legislation::QuestionsController < Legislation::BaseController
load_and_authorize_resource :process
load_and_authorize_resource :question, through: :process
has_orders %w{most_voted newest oldest}, only: :show
def show
@commentable = @question
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
set_comment_flags(@comment_tree.comments)
@answer = @question.answer_for_user(current_user) || Legislation::Answer.new
end
end

View File

@@ -1,8 +0,0 @@
class LegislationsController < ApplicationController
load_and_authorize_resource
def show
@legislation = Legislation.find(params[:id])
end
end

View File

@@ -1,4 +1,6 @@
class NotificationsController < ApplicationController class NotificationsController < ApplicationController
include CustomUrlsHelper
before_action :authenticate_user! before_action :authenticate_user!
after_action :mark_as_read, only: :show after_action :mark_as_read, only: :show
skip_authorization_check skip_authorization_check

View File

@@ -0,0 +1,45 @@
class SandboxController < ApplicationController
skip_authorization_check
layout :set_layout
helper_method(:namespace)
def index
@templates = Dir.glob(Rails.root.join('app/views/sandbox/*.html.erb').to_s).map do |filename|
filename = File.basename(filename, File.extname(filename))
filename unless filename.starts_with?('_') || filename == 'index.html'
end.compact
end
def show
if params[:template].index('.') # CVE-2014-0130
render :action => "index"
elsif lookup_context.exists?("sandbox/#{params[:template]}")
if params[:template] == "index"
render :action => "index"
else
render "sandbox/#{params[:template]}"
end
elsif lookup_context.exists?("sandbox/#{params[:template]}/index")
render "sandbox/#{params[:template]}/index"
else
render :action => "index"
end
end
private
def set_layout
if params[:template] && params[:template].split("_").first == "admin"
"admin"
else
"application"
end
end
def namespace
"admin"
end
end

View File

@@ -18,6 +18,8 @@ module ApplicationHelper
end end
def markdown(text) def markdown(text)
return text if text.blank?
# See https://github.com/vmg/redcarpet for options # See https://github.com/vmg/redcarpet for options
render_options = { render_options = {
filter_html: false, filter_html: false,

View File

@@ -1,11 +1,31 @@
module CommentsHelper module CommentsHelper
def comment_tree_title_text(commentable)
if commentable.class == Legislation::Question
t("legislation.questions.comments.comments_title")
else
t("comments_helper.comments_title")
end
end
def leave_comment_text(commentable)
if commentable.class == Legislation::Question
t("legislation.questions.comments.form.leave_comment")
else
t("comments.form.leave_comment")
end
end
def comment_link_text(parent_id) def comment_link_text(parent_id)
parent_id.present? ? t("comments_helper.reply_link") : t("comments_helper.comment_link") parent_id.present? ? t("comments_helper.reply_link") : t("comments_helper.comment_link")
end end
def comment_button_text(parent_id) def comment_button_text(parent_id, commentable)
parent_id.present? ? t("comments_helper.reply_button") : t("comments_helper.comment_button") if commentable.class == Legislation::Question
parent_id.present? ? t("comments_helper.reply_button") : t("legislation.questions.comments.comment_button")
else
parent_id.present? ? t("comments_helper.reply_button") : t("comments_helper.comment_button")
end
end end
def parent_or_commentable_dom_id(parent_id, commentable) def parent_or_commentable_dom_id(parent_id, commentable)
@@ -21,12 +41,17 @@ module CommentsHelper
end end
def commentable_path(comment) def commentable_path(comment)
if comment.commentable_type == "Budget::Investment" commentable = comment.commentable
budget_investment_path(comment.commentable.budget_id, comment.commentable)
elsif comment.commentable_type == "Poll::Question" case comment.commentable_type
question_path(comment.commentable) when "Budget::Investment"
budget_investment_path(commentable.budget_id, commentable)
when "Legislation::Question"
legislation_process_question_path(commentable.process, commentable)
when "Legislation::Annotation"
legislation_process_draft_version_annotation_path(commentable.draft_version.process, commentable.draft_version, commentable)
else else
comment.commentable commentable
end end
end end
@@ -50,4 +75,22 @@ module CommentsHelper
end end
end end
def require_verified_resident_for_commentable?(commentable, current_user)
return false if current_user.administrator? || current_user.moderator?
commentable.respond_to?(:comments_for_verified_residents_only?) && commentable.comments_for_verified_residents_only? && !current_user.residence_verified?
end
def comments_closed_for_commentable?(commentable)
commentable.respond_to?(:comments_closed?) && commentable.comments_closed?
end
def comments_closed_text(commentable)
if commentable.class == Legislation::Question
t("legislation.questions.comments.comments_closed")
else
t("comments.comments_closed")
end
end
end end

View File

@@ -0,0 +1,9 @@
module CustomUrlsHelper
def legislation_question_url(question)
legislation_process_question_url(question.process, question)
end
def legislation_annotation_url(annotation)
legislation_process_question_url(annotation.draft_version.process, annotation.draft_version, annotation)
end
end

View File

@@ -0,0 +1,9 @@
module LegislationHelper
def format_date(date)
l(date, format: "%d %b %Y") if date
end
def format_date_for_calendar_form(date)
l(date, format: "%d/%m/%Y") if date
end
end

View File

@@ -0,0 +1,9 @@
module TextHelper
def first_paragraph(text)
if text.blank?
""
else
text.strip.split("\n").first
end
end
end

View File

@@ -32,7 +32,7 @@ module Abilities
can :mark_featured, Debate can :mark_featured, Debate
can :unmark_featured, Debate can :unmark_featured, Debate
can :comment_as_administrator, [Debate, Comment, Proposal, Poll::Question, Budget::Investment] can :comment_as_administrator, [Debate, Comment, Proposal, Poll::Question, Budget::Investment, Legislation::Question, Legislation::Annotation]
can [:search, :create, :index, :destroy], ::Moderator can [:search, :create, :index, :destroy], ::Moderator
can [:search, :create, :index, :summary], ::Valuator can [:search, :create, :index, :summary], ::Valuator
@@ -64,6 +64,12 @@ module Abilities
can :manage, SiteCustomization::Page can :manage, SiteCustomization::Page
can :manage, SiteCustomization::Image can :manage, SiteCustomization::Image
can :manage, SiteCustomization::ContentBlock can :manage, SiteCustomization::ContentBlock
can [:manage], ::Legislation::Process
can [:manage], ::Legislation::DraftVersion
can [:manage], ::Legislation::Question
cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation]
end end
end end
end end

View File

@@ -11,13 +11,18 @@ module Abilities
can [:read, :welcome], Budget can [:read, :welcome], Budget
can :read, Budget::Investment can :read, Budget::Investment
can :read, SpendingProposal can :read, SpendingProposal
can :read, Legislation can :read, LegacyLegislation
can :read, User can :read, User
can [:search, :read], Annotation can [:search, :read], Annotation
can [:read], Budget can [:read], Budget
can [:read], Budget::Group can [:read], Budget::Group
can [:read, :print], Budget::Investment can [:read, :print], Budget::Investment
can :new, DirectMessage can :new, DirectMessage
can [:read, :debate, :draft_publication, :allegations, :final_version_publication], Legislation::Process
can [:read, :changes, :go_to_version], Legislation::DraftVersion
can [:read], Legislation::Question
can [:create], Legislation::Answer
can [:search, :comments, :read, :create, :new_comment], Legislation::Annotation
end end
end end
end end

View File

@@ -5,7 +5,7 @@ module Abilities
def initialize(user) def initialize(user)
self.merge Abilities::Moderation.new(user) self.merge Abilities::Moderation.new(user)
can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll::Question] can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll::Question, Legislation::Question, Legislation::Annotation]
end end
end end
end end

View File

@@ -1,7 +1,7 @@
class Annotation < ActiveRecord::Base class Annotation < ActiveRecord::Base
serialize :ranges, Array serialize :ranges, Array
belongs_to :legislation belongs_to :legacy_legislation
belongs_to :user belongs_to :user
def permissions def permissions

View File

@@ -11,7 +11,7 @@ class Comment < ActiveRecord::Base
validates :body, presence: true validates :body, presence: true
validates :user, presence: true validates :user, presence: true
validates_inclusion_of :commentable_type, in: ["Debate", "Proposal", "Budget::Investment", "Poll::Question"] validates_inclusion_of :commentable_type, in: ["Debate", "Proposal", "Budget::Investment", "Poll::Question", "Legislation::Question", "Legislation::Annotation"]
validate :validate_body_length validate :validate_body_length

View File

@@ -12,7 +12,9 @@ class CommentNotifier
private private
def send_comment_email def send_comment_email
Mailer.comment(@comment).deliver_later if email_on_comment? unless @comment.commentable.is_a?(Legislation::Annotation)
Mailer.comment(@comment).deliver_later if email_on_comment?
end
end end
def send_reply_email def send_reply_email

View File

@@ -0,0 +1,3 @@
class LegacyLegislation < ActiveRecord::Base
has_many :annotations
end

View File

@@ -1,3 +1,5 @@
class Legislation < ActiveRecord::Base module Legislation
has_many :annotations def self.table_name_prefix
'legislation_'
end
end end

View File

@@ -0,0 +1,58 @@
class Legislation::Annotation < ActiveRecord::Base
COMMENTS_PAGE_SIZE = 5
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
serialize :ranges, Array
belongs_to :draft_version, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_draft_version_id'
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
has_many :comments, as: :commentable, dependent: :destroy
validates :text, presence: true
validates :quote, presence: true
validates :draft_version, presence: true
validates :author, presence: true
before_save :store_range, :store_context
after_create :create_first_comment
def store_range
self.range_start = ranges.first["start"]
self.range_start_offset = ranges.first["startOffset"]
self.range_end = ranges.first["end"]
self.range_end_offset = ranges.first["endOffset"]
end
def store_context
begin
html = draft_version.body_html
doc = Nokogiri::HTML(html)
selector_start = "/html/body/#{range_start}"
el_start = doc.at_xpath(selector_start)
selector_end = "/html/body/#{range_end}"
el_end = doc.at_xpath(selector_end)
remainder_el_start = el_start.text[0 .. range_start_offset-1] unless range_start_offset.zero?
remainder_el_end = el_end.text[range_end_offset .. -1]
self.context = "#{remainder_el_start}<span class=annotator-hl>#{quote}</span>#{remainder_el_end}"
rescue
"<span class=annotator-hl>#{quote}</span>"
end
end
def create_first_comment
comments.create(body: self.text, user: self.author)
end
def title
text[0..50]
end
def weight
comments_count + comments.sum(:cached_votes_total)
end
end

View File

@@ -0,0 +1,12 @@
class Legislation::Answer < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', inverse_of: :answers, counter_cache: true
belongs_to :question_option, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_option_id', inverse_of: :answers, counter_cache: true
belongs_to :user, dependent: :destroy, inverse_of: :legislation_answers
validates :question, presence: true, uniqueness: { scope: :user_id}
validates :question_option, presence: true
validates :user, presence: true
end

View File

@@ -0,0 +1,33 @@
class Legislation::DraftVersion < ActiveRecord::Base
VALID_STATUSES = %w(draft published)
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id'
has_many :annotations, class_name: 'Legislation::Annotation', foreign_key: 'legislation_draft_version_id', dependent: :destroy
validates :title, presence: true
validates :body, presence: true
validates :status, presence: true, inclusion: { in: VALID_STATUSES }
scope :published, -> { where(status: 'published').order('id DESC') }
before_save :render_html
def render_html
renderer = Redcarpet::Render::HTML.new(with_toc_data: true)
toc_renderer = Redcarpet::Render::HTML_TOC.new(with_toc_data: true)
self.body_html = Redcarpet::Markdown.new(renderer).render(body)
self.toc_html = Redcarpet::Markdown.new(toc_renderer).render(body)
end
def display_title
status == 'draft' ? "#{title} *" : title
end
def total_comments
annotations.sum(:comments_count)
end
end

View File

@@ -0,0 +1,90 @@
class Legislation::Process < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id', dependent: :destroy
has_one :final_draft_version, -> { where final_version: true, status: 'published' }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id'
has_many :questions, -> { order(:id) }, class_name: 'Legislation::Question', foreign_key: 'legislation_process_id', dependent: :destroy
validates :title, presence: true
validates :start_date, presence: true
validates :end_date, presence: true
validates :debate_start_date, presence: true, if: :debate_end_date?
validates :debate_end_date, presence: true, if: :debate_start_date?
validates :allegations_start_date, presence: true, if: :allegations_end_date?
validates :allegations_end_date, presence: true, if: :allegations_start_date?
validate :valid_date_ranges
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') }
def open_phase?(phase)
today = Date.current
case phase
when :debate
active_phase?(:debate) && today >= debate_start_date && today <= debate_end_date
when :draft_publication
active_phase?(:draft_publication) && today >= draft_publication_date
when :allegations
active_phase?(:allegations) && today >= allegations_start_date && today <= allegations_end_date
when :final_version_publication
active_phase?(:final_version_publication) && today >= final_publication_date
end
end
def show_phase?(phase)
# show past phases even if they're finished
today = Date.current
case phase
when :debate
active_phase?(:debate) && today >= debate_start_date
when :draft_publication
active_phase?(:draft_publication) && today >= draft_publication_date
when :allegations
active_phase?(:allegations) && today >= allegations_start_date
when :final_version_publication
active_phase?(:final_version_publication) && today >= final_publication_date
end
end
def active_phase?(phase)
case phase
when :debate
debate_start_date.present? && debate_end_date.present?
when :draft_publication
draft_publication_date.present?
when :allegations
allegations_start_date.present? && allegations_end_date.present?
when :final_version_publication
final_publication_date.present?
end
end
def total_comments
questions.sum(:comments_count) + draft_versions.map(&:total_comments).sum
end
def status
today = Date.current
if today < start_date
:planned
elsif end_date < today
:closed
else
:open
end
end
private
def valid_date_ranges
errors.add(:end_date, :invalid_date_range) if end_date && start_date && end_date < start_date
errors.add(:debate_end_date, :invalid_date_range) if debate_end_date && debate_start_date && debate_end_date < debate_start_date
errors.add(:allegations_end_date, :invalid_date_range) if allegations_end_date && allegations_start_date && allegations_end_date < allegations_start_date
end
end

View File

@@ -0,0 +1,42 @@
class Legislation::Question < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id'
has_many :question_options, -> { order(:id) }, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
has_many :comments, as: :commentable, dependent: :destroy
accepts_nested_attributes_for :question_options, :reject_if => proc { |attributes| attributes[:value].blank? }, allow_destroy: true
validates :process, presence: true
validates :title, presence: true
scope :sorted, -> { order('id ASC') }
def next_question_id
@next_question_id ||= process.questions.where("id > ?", id).sorted.limit(1).pluck(:id).first
end
def first_question_id
@first_question_id ||= process.questions.sorted.limit(1).pluck(:id).first
end
def answer_for_user(user)
answers.where(user: user).first
end
def comments_for_verified_residents_only?
true
end
def comments_closed?
!comments_open?
end
def comments_open?
process.open_phase?(:debate)
end
end

View File

@@ -0,0 +1,10 @@
class Legislation::QuestionOption < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', inverse_of: :question_options
has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
validates :question, presence: true
validates :value, presence: true, uniqueness: { scope: :legislation_question_id }
end

View File

@@ -27,6 +27,7 @@ class User < ActiveRecord::Base
has_many :notifications has_many :notifications
has_many :direct_messages_sent, class_name: 'DirectMessage', foreign_key: :sender_id has_many :direct_messages_sent, class_name: 'DirectMessage', foreign_key: :sender_id
has_many :direct_messages_received, class_name: 'DirectMessage', foreign_key: :receiver_id has_many :direct_messages_received, class_name: 'DirectMessage', foreign_key: :receiver_id
has_many :legislation_answers, class_name: 'Legislation::Answer', dependent: :destroy, inverse_of: :user
belongs_to :geozone belongs_to :geozone
validates :username, presence: true, if: :username_required? validates :username, presence: true, if: :username_required?

View File

@@ -117,6 +117,26 @@
</ul> </ul>
</li> </li>
<% if feature?(:legislation) %>
<li <%= "class=active" if controller.class.parent == Admin::Legislation %>>
<%= link_to admin_legislation_processes_path do %>
<span class="icon-budget"></span><%= t("admin.menu.legislation") %>
<% end %>
</li>
<% end %>
<li <%= "class=active" if controller_name == "banners" %>>
<%= link_to admin_banners_path do %>
<span class="icon-eye"></span><%= t("admin.menu.banner") %>
<% end %>
</li>
<li <%= "class=active" if controller_name == "users" %>>
<%= link_to admin_users_path do %>
<span class="icon-eye"></span><%= t("admin.menu.hidden_users") %>
<% end %>
</li>
<li class="section-title"> <li class="section-title">
<a href="#"> <a href="#">
<span class="icon-banner"></span> <span class="icon-banner"></span>

View File

@@ -0,0 +1,94 @@
<%= form_for [:admin, @process, @draft_version], url: url, html: {data: {watch_changes: true}} do |f| %>
<% if @draft_version.errors.any? %>
<div id="error_explanation" data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<strong>
<%= @draft_version.errors.count %>
<%= t("admin.legislation.draft_versions.errors.form.error", count: @draft_version.errors.count) %>
</strong>
</div>
<% end %>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :title %>
</div>
<div class="small-12 medium-8 column">
<%= f.text_field :title, label: false, placeholder: t('admin.legislation.draft_versions.form.title_placeholder') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :changelog %>
<small><%= t('admin.legislation.draft_versions.form.use_markdown') %></small>
</div>
<div class="small-12 medium-8 column">
<%= f.text_area :changelog, label: false, rows: 5, placeholder: t('admin.legislation.draft_versions.form.changelog_placeholder') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :status %>
</div>
<div class="small-12 medium-8 column">
<% ::Legislation::DraftVersion::VALID_STATUSES.each do |status| %>
<%= f.radio_button :status, status, label: false %>
<%= f.label "status_#{status}", t("admin.legislation.draft_versions.statuses.#{status}") %>
<small><%= t("admin.legislation.draft_versions.form.hints.status.#{status}") %></small>
<br/>
<% end %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :final_version %>
</div>
<div class="small-12 medium-8 column">
<%= f.check_box :final_version, label: false %>
<small><%= t("admin.legislation.draft_versions.form.hints.final_version") %></small>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :body %>
<small><%= t('admin.legislation.draft_versions.form.use_markdown') %></small>
</div>
<div class="markdown-editor">
<div class="small-12 medium-8 column fullscreen-container">
<div class="markdown-editor-header truncate"><%= t('admin.legislation.draft_versions.form.title_html', draft_version_title: @draft_version.title, process_title: @process.title ) %></div>
<div class="markdown-editor-buttons">
<%= f.submit(class: "button", value: t("admin.legislation.draft_versions.#{admin_submit_action(@draft_version)}.submit_button")) %>
</div>
<%= link_to "#", class: 'fullscreen-toggle' do %>
<span data-closed-text="<%= t("admin.legislation.draft_versions.form.launch_text_editor")%>"
data-open-text="<%= t("admin.legislation.draft_versions.form.close_text_editor")%>">
<%= t("admin.legislation.draft_versions.form.launch_text_editor")%>
</span>
<% end %>
</div>
<div class="small-12 medium-6 column markdown-area">
<%= f.text_area :body, label: false, placeholder: t('admin.legislation.draft_versions.form.body_placeholder') %>
</div>
<div id="markdown-preview" class="small-12 medium-6 column">
</div>
</div>
</div>
<div class="row primary-buttons">
<div class="actions small-12 medium-3 column legislation-process-save">
<%= f.submit(class: "button expanded", value: t("admin.legislation.draft_versions.#{admin_submit_action(@draft_version)}.submit_button")) %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,36 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %> - <%= t("admin.legislation.draft_versions.index.title") %> - <%= @draft_version.title %>
<% end %>
<div class="legislation-admin legislation-draft-versions-edit legislation-draft-versions-form row">
<div class="small-12 column">
<%= link_to admin_legislation_process_draft_versions_path(@process), class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.draft_versions.edit.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'admin/legislation/processes/subnav', process: @process, active: 'draft_versions' %>
<div class="row">
<div class="small-12 column">
<div class="callout warning" style="display: none;">
<%= t("admin.legislation.draft_versions.edit.warning") %>
</div>
</div>
<div class="small-12 medium-9 column">
<h3><%= @draft_version.title %></h3>
</div>
<div class="small-12 medium-3 column legislation-question-delete">
<%= link_to t("admin.legislation.draft_versions.index.delete"),
admin_legislation_process_draft_version_path(@process, @draft_version),
method: :delete,
class: 'button hollow alert' %>
</div>
</div>
<%= render 'form', url: admin_legislation_process_draft_version_path(@process, @draft_version) %>
</div>
</div>

View File

@@ -0,0 +1,51 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %> - <%= t("admin.legislation.draft_versions.index.title") %>
<% end %>
<div class="legislation-admin legislation-draft-versions-index row">
<div class="small-12 column">
<%= link_to admin_legislation_processes_path, class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.processes.edit.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'admin/legislation/processes/subnav', process: @process, active: 'draft_versions' %>
<div class="row">
<div class="small-12 medium-9 column">
<h4><%= t("admin.legislation.draft_versions.index.title") %></h4>
</div>
<div class="small-12 medium-3 column legislation-process-version">
<%= link_to t("admin.legislation.draft_versions.index.create"), new_admin_legislation_process_draft_version_path, class: "button" %>
</div>
</div>
<table class="stack">
<thead>
<tr>
<th><%= t("admin.legislation.draft_versions.table.title") %></th>
<th><%= t("admin.legislation.draft_versions.table.created_at") %></th>
<th><%= t("admin.legislation.draft_versions.table.status") %></th>
<th><%= t("admin.legislation.draft_versions.table.comments") %></th>
<th><%= t("admin.legislation.draft_versions.table.final_version") %></th>
</tr>
</thead>
<tbody>
<% @process.draft_versions.each do |draft_version| %>
<tr id="<%= dom_id(draft_version) %>">
<td>
<%= link_to draft_version.title, edit_admin_legislation_process_draft_version_path(@process, draft_version) %>
</td>
<td><%= draft_version.created_at.to_date %></td>
<td><%= draft_version.status %> <%= link_to "(#{t('.preview')})", legislation_process_draft_version_path(@process, draft_version) if draft_version.status == 'draft' %></td>
<td><%= draft_version.total_comments %></td>
<td><%= draft_version.final_version %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %> - <%= t("admin.legislation.draft_versions.index.title") %> - <%= t("admin.legislation.draft_versions.new.title") %>
<% end %>
<div class="legislation-admin legislation-draft-versions-new legislation-draft-versions-form row">
<div class="small-12 column">
<%= link_to admin_legislation_process_draft_versions_path(@process), class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.draft_versions.new.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'admin/legislation/processes/subnav', process: @process, active: 'draft_versions' %>
<div class="row">
<div class="small-12 medium-9 column">
<h3><%= t("admin.legislation.draft_versions.new.title") %></h3>
</div>
</div>
<%= render 'form', url: admin_legislation_process_draft_versions_path(@process) %>
</div>
</div>

View File

@@ -0,0 +1,202 @@
<%= form_for [:admin, @process], html: {data: {watch_changes: true}} do |f| %>
<% if @process.errors.any? %>
<div id="error_explanation" data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<strong>
<%= @process.errors.count %>
<%= t("admin.legislation.processes.errors.form.error", count: @process.errors.count) %>
</strong>
</div>
<% end %>
<div class="row">
<div class="small-12 medium-4 column">
<label><%= t('admin.legislation.processes.form.process') %></label>
</div>
<div class="small-12 medium-1 column legislation-process-start">
<%= t('admin.legislation.processes.form.start') %>
</div>
<div class="small-12 medium-2 column">
<%= f.text_field :start_date,
label: false,
value: format_date_for_calendar_form(@process.start_date),
class: "js-calendar-full",
id: "start_date" %>
</div>
<div class="small-12 medium-1 column legislation-process-end">
<%= t('admin.legislation.processes.form.end') %>
</div>
<div class="small-12 medium-2 column">
<%= f.text_field :end_date,
label: false,
value: format_date_for_calendar_form(@process.end_date),
class: "js-calendar-full",
id: "end_date" %>
</div>
<div class="small-12 medium-4 column">
<label><%= t('admin.legislation.processes.form.debate_phase') %></label>
</div>
<div class="small-12 medium-1 column legislation-process-start">
<%= t('admin.legislation.processes.form.start') %>
</div>
<div class="small-12 medium-2 column">
<%= f.text_field :debate_start_date,
label: false,
value: format_date_for_calendar_form(@process.debate_start_date),
class: "js-calendar-full",
id: "debate_start_date" %>
</div>
<div class="small-12 medium-1 column legislation-process-end">
<%= t('admin.legislation.processes.form.end') %>
</div>
<div class="small-12 medium-2 column">
<%= f.text_field :debate_end_date,
label: false,
value: format_date_for_calendar_form(@process.debate_end_date),
class: "js-calendar-full",
id: "debate_end_date" %>
</div>
<div class="small-12 medium-2 column">
<%= check_box_tag :debate_phase_active, @process.active_phase?(:debate), @process.new_record? || @process.active_phase?(:debate), data: {disable_date: "debate"} %>
<%= label_tag :debate_phase_active, t('admin.legislation.processes.form.active') %>
</div>
<div class="small-12 medium-4 column">
<label><%= t('admin.legislation.processes.form.allegations_phase') %></label>
</div>
<div class="small-12 medium-1 column legislation-process-start">
<%= t('admin.legislation.processes.form.start') %>
</div>
<div class="small-12 medium-2 column">
<%= f.text_field :allegations_start_date,
label: false,
value: format_date_for_calendar_form(@process.allegations_start_date),
class: "js-calendar-full",
id: "allegations_start_date" %>
</div>
<div class="small-12 medium-1 column legislation-process-end">
<%= t('admin.legislation.processes.form.end') %>
</div>
<div class="small-12 medium-2 column">
<%= f.text_field :allegations_end_date,
label: false,
value: format_date_for_calendar_form(@process.allegations_end_date),
class: "js-calendar-full",
id: "allegations_end_date" %>
</div>
<div class="small-12 medium-2 column">
<%= check_box_tag :allegations_phase_active, @process.active_phase?(:allegations), @process.new_record? || @process.active_phase?(:allegations), data: {disable_date: "allegations"} %>
<%= label_tag :allegations_phase_active, t('admin.legislation.processes.form.active') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :draft_publication_date %>
</div>
<div class="small-12 medium-2 column end">
<%= f.text_field :draft_publication_date,
label: false,
value: format_date_for_calendar_form(@process.draft_publication_date),
class: "js-calendar-full",
id: "draft_publication_date" %>
</div>
<div class="small-12 medium-2 column">
<%= check_box_tag :draft_publication_phase_active, @process.active_phase?(:draft_publication), @process.new_record? || @process.active_phase?(:draft_publication), data: {disable_date: "draft_publication"} %>
<%= label_tag :draft_publication_phase_active, t('admin.legislation.processes.form.active') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :final_publication_date %>
</div>
<div class="small-12 medium-2 column end">
<%= f.text_field :final_publication_date,
label: false,
value: format_date_for_calendar_form(@process.final_publication_date),
class: "js-calendar-full",
id: "final_publication_date" %>
</div>
<div class="small-12 medium-2 column">
<%= check_box_tag :final_version_publication_phase_active, @process.active_phase?(:final_version_publication), @process.new_record? || @process.active_phase?(:final_version_publication), data: {disable_date: "final_publication"} %>
<%= label_tag :final_version_publication_phase_active, t('admin.legislation.processes.form.active') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :title %>
</div>
<div class="small-12 medium-8 column">
<%= f.text_field :title,
label: false,
placeholder: t('admin.legislation.processes.form.title_placeholder') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :description %>
<small><%= t('admin.legislation.processes.form.use_markdown') %></small>
</div>
<div class="small-12 medium-8 column">
<%= f.text_area :description,
label: false,
rows: 5,
placeholder: t('admin.legislation.processes.form.description_placeholder') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :target %>
<small><%= t('admin.legislation.processes.form.use_markdown') %></small>
</div>
<div class="small-12 medium-8 column">
<%= f.text_area :target,
label: false,
rows: 5,
placeholder: t('admin.legislation.processes.form.target_placeholder') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :how_to_participate %>
<small><%= t('admin.legislation.processes.form.use_markdown') %></small>
</div>
<div class="small-12 medium-8 column">
<%= f.text_area :how_to_participate,
label: false,
rows: 5,
placeholder: t('admin.legislation.processes.form.how_to_participate_placeholder') %>
</div>
</div>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :additional_info %>
<small><%= t('admin.legislation.processes.form.use_markdown') %></small>
</div>
<div class="small-12 medium-8 column">
<%= f.text_area :additional_info,
label: false,
rows: 10,
placeholder: t('admin.legislation.processes.form.additional_info_placeholder') %>
</div>
</div>
<div class="row">
<div class="actions small-12 medium-3 column legislation-process-save">
<%= f.submit(class: "button expanded", value: t("admin.legislation.processes.#{admin_submit_action(@process)}.submit_button")) %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,11 @@
<ul class="menu simple clear">
<li <%= "class=active" if active == 'info' %>>
<%= link_to t("admin.legislation.processes.subnav.info"), edit_admin_legislation_process_path(process) %>
</li>
<li <%= "class=active" if active == 'questions' %>>
<%= link_to t("admin.legislation.processes.subnav.questions"), admin_legislation_process_questions_path(process) %>
</li>
<li <%= "class=active" if active == 'draft_versions' %>>
<%= link_to t("admin.legislation.processes.subnav.draft_texts"), admin_legislation_process_draft_versions_path(process) %>
</li>
</ul>

View File

@@ -0,0 +1,19 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %>
<% end %>
<div class="legislation-admin legislation-process-edit row">
<div class="small-12 column">
<%= link_to admin_legislation_processes_path, class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.processes.edit.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'subnav', process: @process, active: 'info' %>
<%= render "form" %>
</div>
</div>

View File

@@ -0,0 +1,50 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= t("admin.legislation.processes.index.filters.#{@current_filter}") %>
<% end %>
<div class="legislation-admin legislation-process-index">
<div class="row">
<div class="small-12 medium-9 column">
<h2 class="inline-block"><%= t("admin.legislation.processes.index.title") %></h2>
</div>
<div class="small-12 medium-3 column legislation-process-new">
<%= link_to t("admin.legislation.processes.index.create"), new_admin_legislation_process_path, class: "button" %>
</div>
</div>
<%= render 'shared/filter_subnav', i18n_namespace: "admin.legislation.processes.index" %>
<h3><%= page_entries_info @processes %></h3>
<table class="stack">
<thead>
<tr>
<th><%= t("admin.legislation.processes.process.title") %></th>
<th><%= t("admin.legislation.processes.process.status") %></th>
<th><%= t("admin.legislation.processes.process.creation_date") %></th>
<th><%= t("admin.legislation.processes.process.comments") %></th>
<th></th>
</tr>
</thead>
<tbody>
<% @processes.each do |process| %>
<tr id="<%= dom_id(process) %>">
<td class="small-12 medium-8">
<%= link_to process.title, edit_admin_legislation_process_path(process) %>
</td>
<td><%= t("admin.legislation.processes.process.status_#{process.status}") %></td>
<td><%= I18n.l process.created_at.to_date %></td>
<td><%= process.total_comments %></td>
<td>
<%= link_to t("admin.legislation.processes.index.delete"), admin_legislation_process_path(process),
method: :delete,
class: 'button hollow alert' %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate @processes %>
</div>

View File

@@ -0,0 +1,17 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= t("admin.legislation.processes.new.title") %>
<% end %>
<div class="legislation-admin legislation-process-new row">
<div class="small-12 column">
<%= link_to admin_legislation_processes_path, class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.processes.new.back") %>
<% end %>
<h1><%= t("admin.legislation.processes.new.title") %></h1>
<%= render "form" %>
</div>
</div>

View File

@@ -0,0 +1,44 @@
<%= form_for [:admin, @process, @question], url: url, html: {data: {watch_changes: true}} do |f| %>
<% if @question.errors.any? %>
<div id="error_explanation" data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<strong>
<%= @question.errors.count %>
<%= t("admin.legislation.questions.errors.form.error", count: @question.errors.count) %>
</strong>
</div>
<% end %>
<div class="small-12 medium-4 column">
<%= f.label :title %>
</div>
<div class="small-12 medium-8 column">
<%= f.text_area :title, rows: 5, label: false, placeholder: t('admin.legislation.questions.form.title_placeholder') %>
</div>
<div class="small-12 medium-4 column">
<%= f.label :question_options %>
</div>
<div class="small-12 medium-8 column">
<%= f.fields_for :question_options do |ff| %>
<%= render 'question_option_fields', f: ff %>
<% end %>
</div>
<div class="small-12 medium-8 column">
<%= link_to_add_association t('.add_option'), f, :question_options %>
</div>
<div class="row">
<div class="actions small-12 medium-3 column legislation-process-save">
<%= f.submit(class: "button expanded", value: t("admin.legislation.questions.#{admin_submit_action(@question)}.submit_button")) %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,11 @@
<div class="nested-fields">
<div class="field">
<div class="row">
<div class="small-12 medium-9 column">
<%= f.text_field :value, label: false, placeholder: t('admin.legislation.questions.form.value_placeholder') %>
</div>
<div class="small-12 medium-3 column">
<%= link_to_remove_association "<span class=\"icon-x\" aria-hidden=\"true\"></span> <span>#{t('.remove_option')}</span>".html_safe, f %>
</div>
</div>
</div>

View File

@@ -0,0 +1,29 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %> - <%= t("admin.legislation.questions.index.title") %> - <%= @question.title %>
<% end %>
<div class="legislation-admin legislation-questions-edit legislation-questions-form row">
<div class="small-12 column">
<%= link_to admin_legislation_process_questions_path(@process), class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.questions.edit.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'admin/legislation/processes/subnav', process: @process, active: 'questions' %>
<div class="row">
<div class="small-12 medium-9 column">
<h3><%= t("admin.legislation.questions.edit.title", question_title: @question.title) %></h3>
</div>
<div class="small-12 medium-3 column legislation-question-delete">
<%= link_to t("admin.legislation.questions.index.delete"), admin_legislation_process_question_path(@process, @question),
method: :delete,
class: 'button hollow alert' %>
</div>
</div>
<%= render 'form', url: admin_legislation_process_question_path(@process, @question) %>
</div>
</div>

View File

@@ -0,0 +1,57 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %> - <%= t("admin.legislation.questions.index.title") %>
<% end %>
<div class="legislation-admin legislation-draft-versions-index row">
<div class="small-12 column">
<%= link_to admin_legislation_processes_path, class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.questions.index.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'admin/legislation/processes/subnav', process: @process, active: 'questions' %>
<div class="row">
<div class="small-12 medium-9 column">
<h4><%= t("admin.legislation.questions.index.title") %></h4>
</div>
<div class="small-12 medium-3 column legislation-process-question">
<%= link_to t("admin.legislation.questions.index.create"), new_admin_legislation_process_question_path, class: "button" %>
</div>
</div>
<table class="stack">
<thead>
<tr>
<th><%= t("admin.legislation.questions.table.title") %></th>
<th><%= t("admin.legislation.questions.table.question_options") %></th>
<th><%= t("admin.legislation.questions.table.answers_count") %></th>
<th><%= t("admin.legislation.questions.table.comments_count") %></th>
</tr>
</thead>
<tbody>
<% @process.questions.each do |question| %>
<tr id="<%= dom_id(question) %>">
<td>
<%= link_to question.title, edit_admin_legislation_process_question_path(@process, question) %>
</td>
<td>
<%= content_tag :ul do %>
<% question.question_options.each do |question_option| %>
<%= content_tag :li do %>
<%= question_option.value %> (<%= question_option.answers_count %>)
<% end %>
<% end %>
<% end %>
</td>
<td><%= question.answers_count %></td>
<td><%= link_to question.comments.count, legislation_process_question_path(@process, question, anchor: 'comments') %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<% provide :title do %>
Admin - <%= t("admin.menu.legislation") %> - <%= @process.title %> - <%= t("admin.legislation.questions.index.title") %> - <%= t("admin.legislation.questions.new.title") %>
<% end %>
<div class="legislation-admin legislation-questions-new legislation-questions-form row">
<div class="small-12 column">
<%= link_to admin_legislation_process_questions_path(@process), class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.legislation.questions.new.back") %>
<% end %>
<h1><%= @process.title %></h1>
<%= render 'admin/legislation/processes/subnav', process: @process, active: 'questions' %>
<div class="row">
<div class="small-12 medium-9 column">
<h3><%= t("admin.legislation.questions.new.title") %></h3>
</div>
</div>
<%= render 'form', url: admin_legislation_process_questions_path(@process) %>
</div>
</div>

View File

@@ -81,7 +81,7 @@
<%= t("comments.comment.responses", count: 0) %> <%= t("comments.comment.responses", count: 0) %>
<% end %> <% end %>
<% if user_signed_in? %> <% if user_signed_in? && !comments_closed_for_commentable?(comment.commentable) && !require_verified_resident_for_commentable?(comment.commentable, current_user) %>
<span class="divider">&nbsp;|&nbsp;</span> <span class="divider">&nbsp;|&nbsp;</span>
<%= link_to(comment_link_text(comment), "", <%= link_to(comment_link_text(comment), "",
class: "js-add-comment-link", data: {'id': dom_id(comment)}) %> class: "js-add-comment-link", data: {'id': dom_id(comment)}) %>

View File

@@ -6,21 +6,32 @@
<div class="row"> <div class="row">
<div id="comments" class="small-12 column"> <div id="comments" class="small-12 column">
<h2> <h2>
<%= t("debates.show.comments_title") %> <%= comment_tree_title_text(commentable) %>
<span class="js-comments-count">(<%= commentable.comments_count %>)</span> <span class="js-comments-count">(<%= commentable.comments_count %>)</span>
</h2> </h2>
<%= render 'shared/wide_order_selector', i18n_namespace: "comments" %> <%= render 'shared/wide_order_selector', i18n_namespace: "comments" %>
<% if user_signed_in? %> <% if user_signed_in? %>
<%= render 'comments/form', {commentable: commentable, parent_id: nil, toggeable: false} %> <% if comments_closed_for_commentable?(commentable) %>
<br>
<div data-alert class="callout primary">
<%= comments_closed_text(commentable) %>
</div>
<% elsif require_verified_resident_for_commentable?(commentable, current_user) %>
<br>
<div data-alert class="callout primary">
<%= t("comments.verified_only", verify_account: link_to(t("comments.verify_account"), verification_path )).html_safe %>
</div>
<% else %>
<%= render 'comments/form', {commentable: commentable, parent_id: nil, toggeable: false} %>
<% end %>
<% else %> <% else %>
<br> <br>
<div data-alert class="callout primary">
<div data-alert class="callout primary"> <%= t("debates.show.login_to_comment",
<%= t("debates.show.login_to_comment", signin: link_to(t("votes.signin"), new_user_session_path),
signin: link_to(t("votes.signin"), new_user_session_path), signup: link_to(t("votes.signup"), new_user_registration_path)).html_safe %>
signup: link_to(t("votes.signup"), new_user_registration_path)).html_safe %>
</div> </div>
<% end %> <% end %>

View File

@@ -2,13 +2,13 @@
<% css_id = parent_or_commentable_dom_id(parent_id, commentable) %> <% css_id = parent_or_commentable_dom_id(parent_id, commentable) %>
<div id="js-comment-form-<%= css_id %>" <%= "style='display:none'".html_safe if toggeable %> class="comment-form"> <div id="js-comment-form-<%= css_id %>" <%= "style='display:none'".html_safe if toggeable %> class="comment-form">
<%= form_for Comment.new, remote: true do |f| %> <%= form_for Comment.new, remote: true do |f| %>
<%= label_tag "comment-body-#{css_id}", t("comments.form.leave_comment") %> <%= label_tag "comment-body-#{css_id}", leave_comment_text(commentable) %>
<%= f.text_area :body, id: "comment-body-#{css_id}", maxlength: Comment.body_max_length, label: false %> <%= f.text_area :body, id: "comment-body-#{css_id}", maxlength: Comment.body_max_length, label: false %>
<%= f.hidden_field :commentable_type, value: commentable.class.name %> <%= f.hidden_field :commentable_type, value: commentable.class.name %>
<%= f.hidden_field :commentable_id, value: commentable.id %> <%= f.hidden_field :commentable_id, value: commentable.id %>
<%= f.hidden_field :parent_id, value: parent_id %> <%= f.hidden_field :parent_id, value: parent_id %>
<%= f.submit comment_button_text(parent_id), class: "button" %> <%= f.submit comment_button_text(parent_id, commentable), class: "button" %>
<% if can? :comment_as_moderator, commentable %> <% if can? :comment_as_moderator, commentable %>
<div class="float-right"> <div class="float-right">

View File

@@ -5,7 +5,7 @@
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
<div class="notice-text"> <div class="notice-text">
<%= flash_message %> <%= flash_message.try(:html_safe) %>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -13,7 +13,7 @@
<%= favicon_link_tag "favicon.ico" %> <%= favicon_link_tag "favicon.ico" %>
</head> </head>
<body class="admin"> <body class="admin" data-watch-form-message="<%= I18n.t('layouts.admin.watch_form_message') %>">
<div class="off-canvas-wrapper"> <div class="off-canvas-wrapper">
<div class="off-canvas-wrapper-inner" data-off-canvas-wrapper> <div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
<div class="off-canvas position-left" id="offCanvas" data-off-canvas> <div class="off-canvas position-left" id="offCanvas" data-off-canvas>

View File

@@ -0,0 +1,29 @@
<div class="row margin-top">
<div class="small-12 column">
<div class="float-right">
<a class="button warning" type="button" data-toggle="help-legacy-legislation">
<sub><span class="icon-edit"></span></sub>&nbsp;
<%= t("legacy_legislation.help.title") %>
</a>
<div class="dropdown-pane" id="help-legacy-legislation" data-dropdown data-auto-focus="true">
<p>
<%= t("legacy_legislation.help.text",
sign_in: link_to(t("legacy_legislation.help.text_sign_in"), new_user_session_path),
sign_up: link_to(t("legacy_legislation.help.text_sign_up"), new_user_registration_path)).html_safe %>
<%= image_tag ("annotator_help.gif"), alt: t("legacy_legislation.help.alt") %>
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="small-12 medium-9 small-centered column">
<section data-annotatable-type="legacy_legislation"
data-annotatable-id="<%= @legacy_legislation.id %>">
<h1 class="text-center"><%= @legacy_legislation.title %></h1>
<div id="legacy_legislation_body"><%= @legacy_legislation.body %></div>
</section>
</div>
</div>

View File

@@ -0,0 +1,76 @@
<div class="comment-box" id="comments-box-<%= annotation.id %>">
<div class="comment-header">
<span class="icon-comment" aria-hidden="true"></span>
<div class="comment-number"><%= t('legislation.annotations.comments.comments_count', count: annotation.comments.roots.count) %></div>
<%= link_to legislation_process_draft_version_annotation_path(annotation.draft_version.process, annotation.draft_version, annotation) do %>
<span class="icon-expand" aria-hidden="true"></span>
<% end %>
</div>
<div class="comments-wrapper">
<% annotation.comments.roots.sort_by_most_voted.limit(Legislation::Annotation::COMMENTS_PAGE_SIZE).each do |comment| %>
<div class="comment">
<div class="comment-text">
<p><%= truncate comment.body, length: 250 %></p>
</div>
<div class="comment-meta">
<div class="comment-more-info">
<% if comment.body.length > 250 %>
<div class="comment-expand">
<%= link_to legislation_process_draft_version_annotation_path(annotation.draft_version.process, annotation.draft_version, annotation) do %>
<%= t('legislation.annotations.comments.see_complete') %>
<% end %>
</div>
<% end %>
<div class="comment-replies">
<%= link_to legislation_process_draft_version_annotation_path(annotation.draft_version.process, annotation.draft_version, annotation, anchor: "comment_#{comment.id}") do %>
<%= t('legislation.annotations.comments.replies_count', count: comment.children.size) %>
<% end %>
</div>
</div>
<div class="comment-votes">
<div id="<%= dom_id(comment) %>_votes" class="comment-votes float-right">
<%= render 'comments/votes', comment: comment %>
</div>
</div>
</div>
</div>
<% end %>
</div>
<div class="comment-footer">
<% if annotation.comments.roots.count > Legislation::Annotation::COMMENTS_PAGE_SIZE %>
<%= link_to legislation_process_draft_version_annotation_path(annotation.draft_version.process, annotation.draft_version, annotation), class: "button strong" do %>
<%= t('legislation.annotations.comments.see_all') %>
<% end %>
<% end %>
<% if @process.open_phase?(:allegations) %>
<a class="button strong publish-comment" href="#"><%= t('legislation.annotations.comments.publish_comment') %></a>
&nbsp;
<% end %>
<% if @process.open_phase?(:allegations) %>
<% if user_signed_in? %>
<% css_id = parent_or_commentable_dom_id(nil, annotation) %>
<div id="js-comment-form-annotation-<%= annotation.id %>" style="display:none" class="comment-form js-comment-form-annotation">
<%= form_for @comment, url: legislation_process_draft_version_annotation_new_comment_path(annotation.draft_version.process, annotation.draft_version, annotation), remote: true do |f| %>
<%= label_tag "comment-body-#{css_id}", leave_comment_text(annotation) %>
<%= f.text_area :body, id: "comment-body-#{css_id}", maxlength: Comment.body_max_length, label: false, rows: 8 %>
<%= f.submit comment_button_text(nil, annotation), class: "button" %>
<% end %>
</div>
<% else %>
<div>
<div class="participation-not-allowed" style="display: none;" aria-hidden="false">
<%= t("legislation.annotations.form.login_to_comment",
signin: link_to(t("legislation.annotations.form.signin"), new_user_session_path),
signup: link_to(t("legislation.annotations.form.signup"), new_user_registration_path)).html_safe %>
</div>
</div>
<% end %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,15 @@
$('#comments-box-<%= annotation.id %> a.publish-comment').on({
click: function(e) {
e.preventDefault();
$('a.publish-comment').hide();
$('#js-comment-form-annotation-<%= annotation.id %>').toggle();
$('#js-comment-form-annotation-<%= annotation.id %> textarea').focus();
return;
}
});
<% if comment.errors.any? %>
$('#comments-box-<%= @annotation.id %> a.publish-comment').hide();
$('#js-comment-form-annotation-<%= annotation.id %>').toggle();
$('#js-comment-form-annotation-<%= annotation.id %> textarea').focus();
<% end %>

View File

@@ -0,0 +1,35 @@
<div class="comment-box">
<div class="comment-header">
<span class="icon-comment" aria-hidden="true"></span>
<div class="comment-number"><%= t('legislation.annotations.comments.comments_count', count: 0) %></div>
</div>
<div class="comments-wrapper">
<div class="comment-input">
<% if !@process.open_phase?(:allegations) %>
<div data-alert class="callout primary">
<%= t("legislation.annotations.form.phase_not_open") %>
</div>
<% elsif user_signed_in? %>
<%= form_for Legislation::Annotation.new, url: legislation_process_draft_version_annotations_path(@process, @draft_version), remote: true do |f| %>
<%= f.text_area :text %>
<div class="comment-actions">
<a class="cancel-comment" href="#" data-cancel-annotation><%= t('legislation.annotations.comments.cancel') %></a>
<%= f.submit t('legislation.annotations.comments.publish_comment'), class: 'button strong publish-comment' %>
</div>
<%= f.hidden_field :quote %>
<%= f.hidden_field :ranges %>
<% end %>
<% else %>
<div data-alert class="callout primary">
<%= t("legislation.annotations.form.login_to_comment",
signin: link_to(t("legislation.annotations.form.signin"), new_user_session_path),
signup: link_to(t("legislation.annotations.form.signup"), new_user_registration_path)).html_safe %>
</div>
<% end %>
</div>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<div class="row draft-chooser">
<div class="small-12 medium-6 column">
<h3><%= t('legislation.annotations.version_chooser.seeing_version') %></h3>
<div class="select-box">
<%= form_tag go_to_version_legislation_process_draft_versions_path(process), method: :get, id: "draft_version_go_to_version" do %>
<%= select_tag "draft_version_id", options_from_collection_for_select(process.draft_versions.published, 'id', 'display_title', draft_version.id), "aria-label": t('legislation.draft_versions.show.select_draft_version') %>
<%= hidden_field_tag "redirect_action", "annotations" %>
<%= submit_tag t('legislation.draft_versions.show.select_version_submit'), class: "button" %>
<% end %>
</div>
<span><%= t('legislation.draft_versions.show.updated_at', date: format_date(@draft_version.updated_at)) %></span>
</div>
<div class="small-12 medium-3 column">
<%= link_to t('legislation.annotations.version_chooser.see_text'), legislation_process_draft_version_path(process, draft_version), title: t('legislation.annotations.version_chooser.see_text'), class: "button strong" %>
</div>
<aside class="small-12 medium-3 column">
<div class="sidebar-divider"></div>
<h2><%= t('legislation.shared.share') %></h2>
<%= render '/legislation/shared/share_buttons',
title: t('legislation.shared.share_comment', version_name: @draft_version.title.downcase, process_name: @process.title),
url: legislation_process_draft_version_path(process, draft_version)
%>
</aside>
</div>

View File

@@ -0,0 +1,16 @@
<div class="row draft-chooser">
<div class="small-12 medium-9 column">
<h3><%= t('.seeing_version') %></h3>
<div class="select-box">
<%= form_tag go_to_version_legislation_process_draft_versions_path(process), method: :get, id: "draft_version_go_to_version" do %>
<%= select_tag "draft_version_id", options_from_collection_for_select(process.draft_versions.published, 'id', 'display_title', draft_version.id), "aria-label": t('legislation.draft_versions.show.select_draft_version') %>
<%= hidden_field_tag "redirect_action", "annotations" %>
<%= submit_tag t('legislation.draft_versions.show.select_version_submit'), class: "button" %>
<% end %>
</div>
<span><%= t('legislation.draft_versions.show.updated_at', date: format_date(@draft_version.updated_at)) %></span>
</div>
<div class="small-12 medium-3 column">
<%= link_to t('.see_text'), legislation_process_draft_version_path(process, draft_version), title: t('.see_text'), class: "button strong" %>
</div>
</div>

View File

@@ -0,0 +1,3 @@
$("#comments-box").append("<%= j render('comments_box', annotation: @annotation) %>").show();
<%= render 'comments_box_form', comment: @comment, annotation: @annotation %>

View File

@@ -0,0 +1,32 @@
<% provide :title do %><%= "#{t('.title')} - #{@draft_version.title} - #{@process.title}" %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :small %>
<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %>
<div class="column row">
<div class="draft-panels small-12 column row">
<%= render 'slim_version_chooser', process: @process, draft_version: @draft_version %>
</div>
<div class="small-12 medium-8 column row legislation-comments end">
<% @annotations.each do |annotation| %>
<div class="comment">
<strong><%= t('.comments_about') %></strong>
<span class="pull-right">
<%= link_to legislation_process_draft_version_path(@process, @draft_version, anchor: "annotation-id-#{annotation.id}") do %>
<span><%= t('.see_in_context') %></span> <span class="icon-expand" aria-hidden="true"></span>
<% end %>
</span>
<div class="comment-section">
<%= annotation.context.try(:html_safe).presence || annotation.quote %>
</div>
<%= link_to legislation_process_draft_version_annotation_path(@process, @draft_version, annotation) do %>
<span class="icon-comments" aria-hidden="true"></span> <span><%= t('.comments_count', count: annotation.comments_count) %></span></a>
<% end %>
</div>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,2 @@
$("#comments-box").html("<%= j render('form') %>");

View File

@@ -0,0 +1,3 @@
$("#comments-box-<%= @annotation.id %>").replaceWith("<%= j render('comments_box', annotation: @annotation) %>").show();
<%= render 'comments_box_form', comment: @comment, annotation: @annotation %>

View File

@@ -0,0 +1,46 @@
<% provide :title do %><%= "#{t('.title')} - #{@draft_version.title} - #{@process.title}" %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :small %>
<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %>
<div class="column row">
<div class="draft-panels small-12 column row">
<%= render 'version_chooser', process: @process, draft_version: @draft_version %>
<div class="legislation-comment">
<div class="annotation-comment">
<div class="row annotation-share-comment">
<div class="small-12 medium-9 column">
<strong><%= t('legislation.annotations.index.comments_about') %></strong>
<div class="comment-section">
<div class="row">
<div class="small-12 medium-9 column legislation-comment">
<%= @annotation.context.try(:html_safe).presence || @annotation.quote %>
</div>
<div class="small-12 medium-3 column legislation-comment">
<span class="pull-right">
<%= link_to legislation_process_draft_version_path(@process, @draft_version, anchor: "annotation-id-#{@annotation.id}") do %>
<span><%= t('legislation.annotations.index.see_in_context') %></span> <span class="icon-expand" aria-hidden="true"></span>
<% end %>
</span>
</div>
</div>
</div>
</div>
<aside class="small-12 medium-3 column">
<div class="sidebar-divider"></div>
<h2><%= t('legislation.shared.share') %></h2>
<%= render '/legislation/shared/share_buttons',
title: t('legislation.shared.share_comment', version_name: @draft_version.title.downcase, process_name: @process.title),
url: legislation_process_draft_version_annotations_path(@process, @draft_version)
%>
</aside>
</div>
<%= render partial: '/comments/comment_tree', locals: { comment_tree: @comment_tree, comment_flags: @comment_flags } %>
</div>
</div>
</div>

View File

@@ -0,0 +1 @@
$("#legislation-answer-form").html('<%= j render("legislation/questions/answer_form", process: @process, question: @question, answer: @answer) %>');

View File

@@ -0,0 +1,20 @@
<div class="small-12 calc-comments end column js-toggle-allegations">
<div class="draft-panel">
<div>
<span class="icon-comments" aria-hidden="true"></span> <span class="panel-title"><%= t('legislation.draft_versions.show.text_comments') %></span>
</div>
</div>
<div class="draft-comments-rotated center">
<span class="panel-title"><%= t('legislation.draft_versions.show.text_comments') %></span>
</div>
<div id="comments-box" style="display: none;">
<div class="comment-box">
<div class="comment-header">
<span class="icon-comment" aria-hidden="true"></span>
<div class="comment-number"><%= t('legislation.draft_versions.show.loading_comments') %></div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,32 @@
<% provide :title do %><%= "#{@draft_version.title} - #{t('.title')} - #{@process.title}" %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :small %>
<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %>
<div class="column row">
<div class="draft-panels small-12 column row">
<div class="row draft-chooser">
<div class="small-12 medium-9 column">
<h3><%= t('.seeing_changelog_version') %></h3>
<div class="select-box">
<%= form_tag go_to_version_legislation_process_draft_versions_path(@process), method: :get, id: "draft_version_go_to_version" do %>
<%= select_tag "draft_version_id", options_from_collection_for_select(@draft_versions_list, 'id', 'display_title', @draft_version.id), "aria-label": t('legislation.draft_versions.show.select_draft_version') %>
<%= hidden_field_tag "redirect_action", "changes" %>
<%= submit_tag t('legislation.draft_versions.show.select_version_submit'), class: "button" %>
<% end %>
</div>
<span><%= t('legislation.draft_versions.show.updated_at', date: format_date(@draft_version.updated_at)) %></span>
</div>
<div class="small-12 medium-3 column">
<%= link_to t('.see_text'), legislation_process_draft_version_path(@process, @draft_version), title: t('.see_text'), class: "button strong" %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column legislation-changes">
<%= markdown @draft_version.changelog %>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,78 @@
<% provide :title do %><%= "#{@draft_version.title} - #{@process.title}" %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :small %>
<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %>
<div class="column row">
<div class="draft-panels small-12 column row">
<div class="row draft-chooser">
<div class="small-12 medium-9 column">
<h3><%= t('.seeing_version') %></h3>
<div class="select-box">
<%= form_tag go_to_version_legislation_process_draft_versions_path(@process), method: :get, id: "draft_version_go_to_version" do %>
<%= select_tag "draft_version_id", options_from_collection_for_select(@draft_versions_list, 'id', 'display_title', @draft_version.id), "aria-label": t('.select_draft_version') %>
<%= submit_tag t('.select_version_submit'), class: "button" %>
<% end %>
<% if @draft_version.changelog.present? %>
<span><%= link_to t('.see_changes'), legislation_process_draft_version_changes_path(@process, @draft_version) %></span>
<% end %>
</div>
<span><%= t('.updated_at', date: format_date(@draft_version.updated_at)) %></span>
</div>
<% unless @draft_version.final_version? %>
<div class="small-12 medium-3 column">
<%= link_to t('.see_comments'), legislation_process_draft_version_annotations_path(@process, @draft_version), title: t('.see_comments'), class: "button strong" %>
</div>
<% end %>
</div>
<div class="row draft-allegation medium-collapse">
<div class="small-12 calc-index column <%= "js-toggle-allegations" unless @draft_version.final_version? %>">
<div class="draft-panel">
<div>
<span class="icon-banner" aria-hidden="true"></span> <span class="panel-title"><%= t('.text_toc') %></span>
</div>
</div>
<div class="draft-index-rotated center">
<span class="panel-title"><%= t('.text_toc') %></span>
</div>
<div data-sticky-container>
<div data-sticky data-anchor="sticky-panel" class="draft-index sticky" data-tree-navigator>
<%= @draft_version.toc_html.html_safe %>
</div>
</div>
</div>
<div class="small-12 calc-text column border-right border-left">
<div class="draft-panel">
<div><span class="panel-title"><%= t('.text_body') %></span></div>
</div>
<div id="sticky-panel" class="draft-text">
<% if @draft_version.final_version? %>
<section>
<% else %>
<section class="legislation-annotatable"
data-legislation-draft-version-id="<%= @draft_version.id %>"
data-legislation-annotatable-base-url="<%= legislation_process_draft_version_path(@process, @draft_version) %>"
data-legislation-open-phase="<%= @process.open_phase?(:allegations) %>"
>
<% end %>
<%= @draft_version.body_html.html_safe %>
</section>
</div>
</div>
<% if @draft_version.final_version? %>
<div class="small-12 calc-comments end column"></div>
<% else %>
<%= render 'comments_panel', draft_version: @draft_version %>
<% end %>
</div>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<div class="small-12 medium-9 column">
<div class="debate-list">
<% if process.questions.empty? %>
<p><%= t('.empty_questions') %></p>
<% else %>
<%= render process.questions %>
<% end %>
</div>
</div>
<div class="small-12 medium-3 column">
<div class="debate-info"><%= t('.participate') %></div>
</div>

View File

@@ -0,0 +1,51 @@
<% if header == :small %>
<div class="legislation-hero legislation-allegation no-margin-top grey-heading" data-target="legislation-header-small">
<div class="row headline">
<div class="small-12 medium-7 column">
<h3 class="headline-small"><%= process.title %></h3>
</div>
<div class="small-12 medium-4 column right">
</div>
</div>
<div id="debate-show" class="row description">
<div class="small-12 medium-4 column">
<% if process.description.present? %>
<h4><%= t('legislation.processes.header_full.description') %></h4>
<%= markdown process.description %>
<% end %>
</div>
<div class="small-12 medium-4 column">
<% if process.target.present? %>
<h4><%= t('legislation.processes.header_full.target') %></h4>
<%= markdown process.target %>
<% end %>
</div>
<div class="small-12 medium-4 column">
<% if process.how_to_participate.present? %>
<h4><%= t('legislation.processes.header_full.how_to_participate') %></h4>
<%= markdown process.how_to_participate %>
<% end %>
</div>
<% if process.additional_info.present? %>
<div class="small-12 column debate-add-info">
<div class="debate-info-wrapper">
<%= markdown process.additional_info if process.additional_info %>
</div>
</div>
<% end %>
</div>
<% if process.description.present? || process.target.present? || process.how_to_participate.present? || process.additional_info.present? %>
<div class="center half-gradient">
<a class="button big center button-circle" title="<%= t('.view_process_information') %>" id="js-toggle-small-debate">
<span class="icon-angle-down" aria-hidden="true"></span>
</a>
</div>
<% end %>
</div>
<%= render 'legislation/processes/header_full', process: @process, hidden: true %>
<% else %>
<%= render 'legislation/processes/header_full', process: @process, hidden: false %>
<% end %>

View File

@@ -0,0 +1,48 @@
<div class="legislation-hero no-margin-top grey-heading" style="display:<%= hidden ? 'none' : 'block' %>" data-target="legislation-header-full">
<div class="row headline">
<div class="small-12 medium-7 column">
<p class="grey"><%= t('.title') %></p>
<h2>
<%= process.title %>
</h2>
</div>
<div class="small-12 medium-4 column right">
</div>
</div>
<div class="row description">
<div class="small-12 medium-4 column">
<% if process.description.present? %>
<h4><%= t('.description') %></h4>
<%= markdown process.description %>
<% end %>
</div>
<div class="small-12 medium-4 column">
<% if process.target.present? %>
<h4><%= t('.target') %></h4>
<%= markdown process.target %>
<% end %>
</div>
<div class="small-12 medium-4 column">
<% if process.how_to_participate.present? %>
<h4><%= t('.how_to_participate') %></h4>
<%= markdown process.how_to_participate %>
<% end %>
</div>
<% if process.additional_info.present? %>
<div id="debate-show" class="small-12 column debate-add-info">
<div class="debate-info-wrapper">
<%= markdown process.additional_info if process.additional_info %>
</div>
</div>
<% end %>
</div>
<% if process.additional_info.present? %>
<div class="center half-gradient">
<a id="js-toggle-debate" class="button big center strong" title="Más información y contexto">
<%= t('.more_info') %>
</a>
</div>
<% end %>
</div>

View File

@@ -0,0 +1,43 @@
<nav class="legislation-process-categories">
<div class="legislation-process-list">
<ul>
<%= render 'legislation/processes/key_dates_svg' %>
<% if process.active_phase?(:debate) %>
<li <%= "class=active" if phase == :debate %>>
<%= link_to legislation_process_debate_path(process) do %>
<h4><%= t('legislation.processes.shared.debate_dates') %></h4>
<p><%= format_date(process.debate_start_date) %> - <%= format_date(process.debate_end_date) %></p>
<% end %>
</li>
<% end %>
<% if process.active_phase?(:draft_publication) %>
<li <%= "class=active" if phase == :draft_publication %>>
<%= link_to legislation_process_draft_publication_path(process) do %>
<h4><%= t('legislation.processes.shared.draft_publication_date') %></h4>
<p><%= format_date(process.draft_publication_date) %></p>
<% end %>
</li>
<% end %>
<% if process.active_phase?(:allegations) %>
<li <%= "class=active" if phase == :allegations %>>
<%= link_to legislation_process_allegations_path(process) do %>
<h4><%= t('legislation.processes.shared.allegations_dates') %></h4>
<p><%= format_date(process.allegations_start_date) %> - <%= format_date(process.allegations_end_date) %></p>
<% end %>
</li>
<% end %>
<% if process.active_phase?(:final_version_publication) %>
<li <%= "class=active" if phase == :final_version_publication %>>
<%= link_to legislation_process_final_version_publication_path(process) do %>
<h4><%= t('legislation.processes.shared.final_publication_date') %></h4>
<p><%= format_date(process.final_publication_date) %></p>
<% end %>
</li>
<% end %>
</ul>
</div>
</nav>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -0,0 +1,44 @@
<div id="<%= dom_id(process) %>" class="legislation clear">
<div class="column row legislation-text">
<div class="small-12 medium-8 column">
<div class="legislation-text">
<h3><%= link_to process.title, process %></h3>
</div>
</div>
<div class="small-12 medium-4 column">
<%= link_to process, class: "button button-legislation big expanded", title: t('.see_latest_comments_title') do %>
<span class="icon-comments"></span>&nbsp; <%= t('.see_latest_comments') %>
<% end %>
</div>
<div class="small-12 medium-11 column end">
<%= markdown(first_paragraph(process.description)) %>
</div>
</div>
<div class="column row">
<div class="small-12 column legislation-calendar-info">
<p><%= t('legislation.processes.shared.key_dates') %></p>
</div>
</div>
<div class="column row small-collapse medium-uncollapse legislation-calendar">
<div class="small-6 medium-3 column">
<h5><%= t('legislation.processes.shared.debate_dates') %></h5>
<p><%= format_date(process.debate_start_date) %> - <%= format_date(process.debate_end_date) %></p>
</div>
<div class="small-6 medium-3 column">
<h5><%= t('legislation.processes.shared.draft_publication_date') %></h5>
<p><%= format_date(process.draft_publication_date) %></p>
</div>
<div class="small-6 medium-3 column">
<h5><%= t('legislation.processes.shared.allegations_dates') %></h5>
<p><%= format_date(process.allegations_start_date) %> - <%= format_date(process.allegations_end_date) %></p>
</div>
<div class="small-6 medium-3 column">
<h5><%= t('legislation.processes.shared.final_publication_date') %></h5>
<p><%= format_date(process.final_publication_date) %></p>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<% provide :title do %><%= @process.title %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :full %>
<%= render 'key_dates', process: @process, phase: :debate %>
<div class="row">
<div class="debate-chooser">
<div class="row">
<div class="small-12 medium-9 column">
<div class="debate-list">
<% if @process.questions.empty? %>
<p><%= t('.empty_questions') %></p>
<% else %>
<%= render @process.questions %>
<% end %>
</div>
</div>
<div class="small-12 medium-3 column">
<div class="debate-info"><%= t('.participate') %></div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,20 @@
<% provide :title do %>
<%= t("layouts.header.collaborative_legislation") %> - <%= t("legislation.processes.index.filters.#{@current_filter}") %>
<% end %>
<div class="row">
<div class="legislation-categories small-12 medium-3 column">
<%= render 'shared/filter_subnav', i18n_namespace: "legislation.processes.index" %>
</div>
<div id="legislation" class="legislation-list small-12 medium-9 column">
<div id="legislation-list">
<% if @processes.any? %>
<%= render @processes %>
<%= paginate @processes %>
<% else %>
<%= t(".no_#{@current_filter}_processes") %>
<% end %>
</div>
</div>
</div>

View File

@@ -0,0 +1,13 @@
<% provide :title do %><%= @process.title %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :full %>
<%= render 'legislation/processes/key_dates', process: @process, phase: @phase %>
<div class="row">
<div class="debate-chooser">
<div class="row">
<p><%= t(".empty") %></p>
</div>
</div>
</div>

View File

@@ -0,0 +1,20 @@
<% provide :title do %><%= @process.title %><% end %>
<%= render 'legislation/processes/header', process: @process, header: :full %>
<%= render 'legislation/processes/key_dates', process: @process, phase: @phase %>
<div class="row">
<div class="debate-chooser">
<div class="row">
<div class="debate-draft">
<div class="small-12 medium-7 column">
<h3><%= t('.not_open') %></h3>
</div>
<div class="small-12 medium-5 column">
</div>
</div>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More