Merge branch 'master' into poll-shifts
@@ -1,22 +1,46 @@
|
||||
# Código de conducta
|
||||
# Código de Conducta convenido para Contribuyentes
|
||||
|
||||
Como las personas encargadas de contribuir código y responsables de mantener este proyecto, y con la intención de crear una comunidad abierta en la que sentirse bienvenido acordamos respetar a toda persona que contribuya al proyecto reportando incidencias, creando peticiones de funcionalidades, actualizando la documentación, enviando parches de código o de alguna otra manera.
|
||||
## Nuestro compromiso
|
||||
|
||||
Estamos comprometidos a hacer de la participación en este proyecto una experiencia libre de acoso para todo el mundo, independientemente del nivel de experiencia, género, identidad y expresión de género, orientación sexual, discapacidad, apariencia personal, raza, etnia, edad, religión o nacionalidad.
|
||||
En el interés de fomentar una comunidad abierta y acogedora, nosotros como contribuyentes y administradores nos comprometemos a hacer de la participación en nuestro proyecto y nuestra comunidad una experiencia libre de acoso para todos, independientemente de la edad, dimensión corporal, discapacidad, etnia, identidad y expresión de género, nivel de experiencia, nacionalidad, apariencia física, raza, religión, identidad u orientación sexual.
|
||||
|
||||
Ejemplos de comportamiento inaceptable por parte de los participantes incluyen:
|
||||
## Nuestros estándares
|
||||
|
||||
* El uso de imágenes o lenguaje sexual
|
||||
* Ataques personales
|
||||
* Comentarios insultantes/despectivos
|
||||
Ejemplos de comportamiento que contribuyen a crear un ambiente positivo:
|
||||
|
||||
* Uso de lenguaje amable e inclusivo
|
||||
* Respeto a diferentes puntos de vista y experiencias
|
||||
* Aceptación de críticas constructivas
|
||||
* Enfocarse en lo que es mejor para la comunidad
|
||||
* Mostrar empatía a otros miembros de la comunidad
|
||||
|
||||
Ejemplos de comportamiento inaceptable por participantes:
|
||||
|
||||
* Uso de lenguaje o imágenes sexuales y atención sexual no deseada
|
||||
* Comentarios insultantes o despectivos (*trolling*) y ataques personales o políticos
|
||||
* Acoso público o privado
|
||||
* Publicación de información privada de terceros, como la dirección física o electrónica, sin permiso explícito
|
||||
* Otras conductas poco éticas o no profesionales
|
||||
* Publicación de información privada de terceros sin su consentimiento, como direcciones físicas o electrónicas
|
||||
* Otros tipos de conducta que pudieran considerarse inapropiadas en un entorno profesional.
|
||||
|
||||
Los administradores del proyecto tienen el derecho y la responsabilidad de eliminar, editar o rechazar comentarios, commits, código, ediciones de wikis, incidencias y otro tipo de aportaciones que no estén en línea con este Código de Conducta. Por el hecho de adoptar este Código de Conducta, los responsables del proyecto se comprometen a aplicar sus principios de manera justa y consistente en todos los aspectos relacionados con el desarrollo del proyecto. Los responsables del proyecto que no sigan ni obliguen a cumplir este código de conducta pueden ser apartados del equipo del proyecto.
|
||||
## Nuestras responsabilidades
|
||||
|
||||
Este código de conducta tiene validez tanto en el proyecto como en espacios públicos en los que un individuo esté representando al proyecto o a su comunidad.
|
||||
Los administradores del proyecto son responsables de clarificar los estándares de comportamiento aceptable y se espera que tomen medidas correctivas y apropiadas en respuesta a situaciones de conducta inaceptable.
|
||||
|
||||
Las ocurrencias de abuso, acoso u otro comportamiento inaceptable se puede reportar abriendo una incidencia o contactando a uno o más de los miembros del equipo responsable del proyecto.
|
||||
Los administradores del proyecto tienen el derecho y la responsabilidad de eliminar, editar o rechazar comentarios, *commits*, código, ediciones de documentación, *issues*, y otras contribuciones que no estén alineadas con este Código de Conducta, o de prohibir temporal o permanentemente a cualquier colaborador cuyo comportamiento sea inapropiado, amenazante, ofensivo o perjudicial.
|
||||
|
||||
Este Código de Conducta es una adaptación del [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, disponible en [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
||||
## Alcance
|
||||
|
||||
Este código de conducta aplica tanto a espacios del proyecto como a espacios públicos donde un individuo esté en representación del proyecto o comunidad. Ejemplos de esto incluye el uso de la cuenta oficial de correo electrónico, publicaciones a través de las redes sociales oficiales, o presentaciones con personas designadas en eventos *online* u *offline*. La representación del proyecto puede ser clarificada explicitamente por los administradores del proyecto.
|
||||
|
||||
## Aplicación
|
||||
|
||||
Ejemplos de abuso, acoso u otro tipo de comportamiento inaceptable puede ser reportado al equipo del proyecto en consul@madrid.es. Todas las quejas serán revisadas e investigadas, generando un resultado apropiado a las circunstancias. El equipo del proyecto está obligado a mantener confidencialidad de la persona que reportó el incidente. Detalles específicos acerca de las políticas de aplicación pueden ser publicadas por separado.
|
||||
|
||||
Administradores que no sigan o que no hagan cumplir este Código de Conducta pueden ser eliminados de forma temporal o permanente del equipo administrador.
|
||||
|
||||
## Atribución
|
||||
|
||||
Este Código de Conducta es una adaptación del [Contributor Covenant][homepage], versión 1.4, disponible en [http://contributor-covenant.org/version/1/4/es/][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/es/
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Customization
|
||||
|
||||
You can modify your own Consul to have your custom visual style, but first you'll have to create a fork from [https://github.com/consul/consul](https://github.com/consul/consul) using Github's "fork" button on top right corner. You can use any other service like Gitlab, but don't forget to put a reference link back to Consul on the footer to comply with project's license (GPL Affero 3).
|
||||
You can modify your own CONSUL to have your custom visual style, but first you'll have to create a fork from [https://github.com/consul/consul](https://github.com/consul/consul) using Github's "fork" button on top right corner. You can use any other service like Gitlab, but don't forget to put a reference link back to CONSUL on the footer to comply with project's license (GPL Affero 3).
|
||||
|
||||
We've created an specific structure where you can overwrite and customize the application in a way that will let you keep updating it from Consul's main repository, without having conflicts on code merging or risking loosing your customization changes. We try to make Consul as vanilla as possible to help other developers onboard the codebase.
|
||||
We've created an specific structure where you can overwrite and customize the application in a way that will let you keep updating it from CONSUL's main repository, without having conflicts on code merging or risking loosing your customization changes. We try to make CONSUL as vanilla as possible to help other developers onboard the codebase.
|
||||
|
||||
## Special Folders and Files
|
||||
|
||||
In order to customize your Consul fork, you'll make use of some `custom` folders on the following paths:
|
||||
In order to customize your CONSUL fork, you'll make use of some `custom` folders on the following paths:
|
||||
|
||||
* `config/locales/custom/`
|
||||
* `app/assets/images/custom/`
|
||||
@@ -207,7 +207,7 @@ TODO
|
||||
|
||||
## Updating
|
||||
|
||||
We recommend you to add consul as remote:
|
||||
We recommend you to add CONSUL as remote:
|
||||
|
||||
```
|
||||
git remote add consul https://github.com/consul/consul
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Personalización
|
||||
|
||||
Puedes modificar consul y ponerle tu propia imagen, para esto debes primero hacer un fork de [https://github.com/consul/consul](https://github.com/consul/consul) creando un repositorio nuevo en Github. Puedes usar otro servicio como Gitlab, pero no te olvides de poner el enlace en el footer a tu repositorio en cumplimiento con la licencia de este proyecto (GPL Affero 3).
|
||||
Puedes modificar CONSUL y ponerle tu propia imagen, para esto debes primero hacer un fork de [https://github.com/consul/consul](https://github.com/consul/consul) creando un repositorio nuevo en Github. Puedes usar otro servicio como Gitlab, pero no te olvides de poner el enlace en el footer a tu repositorio en cumplimiento con la licencia de este proyecto (GPL Affero 3).
|
||||
|
||||
Hemos creado una estructura específica donde puedes sobreescribir y personalizar la aplicación para que puedas actualizar sin que tengas problemas al hacer merge y se sobreescriban por error tus cambios. Intentamos que Consul sea una aplicación Ruby on Rails lo más plain vanilla posible para facilitar el acceso de nuevas desarrolladoras.
|
||||
Hemos creado una estructura específica donde puedes sobreescribir y personalizar la aplicación para que puedas actualizar sin que tengas problemas al hacer merge y se sobreescriban por error tus cambios. Intentamos que CONSUL sea una aplicación Ruby on Rails lo más plain vanilla posible para facilitar el acceso de nuevas desarrolladoras.
|
||||
|
||||
## Ficheros y directorios especiales
|
||||
|
||||
Para adaptarlo puedes hacerlo a través de los directorios que están en custom dentro de:
|
||||
Para adaptar tu fork de CONSUL puedes utilizar alguno de los directorios `custom` que están en las rutas:
|
||||
|
||||
* `config/locales/custom/`
|
||||
* `app/assets/images/custom/`
|
||||
@@ -207,7 +207,7 @@ TODO
|
||||
|
||||
## Actualizar
|
||||
|
||||
Te recomendamos que agregues el remote de consul para facilitar este proceso de merge:
|
||||
Te recomendamos que agregues el remote de CONSUL para facilitar este proceso de merge:
|
||||
|
||||
```
|
||||
git remote add consul https://github.com/consul/consul
|
||||
|
||||
1
Gemfile
@@ -33,6 +33,7 @@ gem 'omniauth-facebook', '~> 4.0.0'
|
||||
gem 'omniauth-google-oauth2', '~> 0.4.0'
|
||||
gem 'omniauth-twitter', '~> 1.4.0'
|
||||
gem 'paperclip', '~> 5.1.0'
|
||||
gem 'jquery-fileupload-rails'
|
||||
gem 'paranoia', '~> 2.3.1'
|
||||
gem 'pg', '~> 0.20.0'
|
||||
gem 'pg_search', '~> 2.0.1'
|
||||
|
||||
95
Gemfile.lock
@@ -52,7 +52,7 @@ GEM
|
||||
safely_block (>= 0.1.1)
|
||||
user_agent_parser
|
||||
uuidtools
|
||||
airbrussh (1.2.0)
|
||||
airbrussh (1.3.0)
|
||||
sshkit (>= 1.6.1, != 1.7.0)
|
||||
akami (1.3.1)
|
||||
gyoku (>= 0.4.0)
|
||||
@@ -73,7 +73,7 @@ GEM
|
||||
uniform_notifier (~> 1.10.0)
|
||||
byebug (9.0.6)
|
||||
cancancan (1.16.0)
|
||||
capistrano (3.8.1)
|
||||
capistrano (3.8.2)
|
||||
airbrussh (>= 1.0.0)
|
||||
i18n
|
||||
rake (>= 10.0.0)
|
||||
@@ -87,7 +87,7 @@ GEM
|
||||
capistrano3-delayed-job (1.7.3)
|
||||
capistrano (~> 3.0, >= 3.0.0)
|
||||
daemons (~> 1.2.4)
|
||||
capybara (2.14.0)
|
||||
capybara (2.14.4)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
@@ -95,17 +95,17 @@ GEM
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
chronic (0.10.2)
|
||||
ckeditor (4.2.3)
|
||||
ckeditor (4.2.4)
|
||||
cocaine
|
||||
orm_adapter (~> 0.5.0)
|
||||
climate_control (0.1.0)
|
||||
climate_control (0.2.0)
|
||||
cliver (0.3.2)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
cocoon (1.2.9)
|
||||
coffee-rails (4.2.1)
|
||||
cocoon (1.2.10)
|
||||
coffee-rails (4.2.2)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (>= 4.0.0, < 5.2.x)
|
||||
railties (>= 4.0.0)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
@@ -120,11 +120,11 @@ GEM
|
||||
daemons (1.2.4)
|
||||
dalli (2.7.6)
|
||||
database_cleaner (1.5.3)
|
||||
debug_inspector (0.0.2)
|
||||
delayed_job (4.1.2)
|
||||
activesupport (>= 3.0, < 5.1)
|
||||
delayed_job_active_record (4.1.1)
|
||||
activerecord (>= 3.0, < 5.1)
|
||||
debug_inspector (0.0.3)
|
||||
delayed_job (4.1.3)
|
||||
activesupport (>= 3.0, < 5.2)
|
||||
delayed_job_active_record (4.1.2)
|
||||
activerecord (>= 3.0, < 5.2)
|
||||
delayed_job (>= 3.0, < 5)
|
||||
devise (3.5.10)
|
||||
bcrypt (~> 3.0)
|
||||
@@ -144,10 +144,10 @@ GEM
|
||||
json
|
||||
thread
|
||||
thread_safe
|
||||
email_spec (2.1.0)
|
||||
email_spec (2.1.1)
|
||||
htmlentities (~> 4.3.3)
|
||||
launchy (~> 2.1)
|
||||
mail (~> 2.6.3)
|
||||
mail (~> 2.6)
|
||||
errbase (0.0.3)
|
||||
erubis (2.7.0)
|
||||
execjs (2.7.0)
|
||||
@@ -158,7 +158,7 @@ GEM
|
||||
railties (>= 3.0.0)
|
||||
faker (1.7.3)
|
||||
i18n (~> 0.5)
|
||||
faraday (0.11.0)
|
||||
faraday (0.12.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
foundation-rails (6.2.4.0)
|
||||
railties (>= 3.1.0)
|
||||
@@ -170,12 +170,12 @@ GEM
|
||||
activesupport (>= 4.1)
|
||||
railties (>= 4.1)
|
||||
tzinfo (~> 1.2, >= 1.2.2)
|
||||
geocoder (1.4.3)
|
||||
geocoder (1.4.4)
|
||||
globalid (0.4.0)
|
||||
activesupport (>= 4.2.0)
|
||||
graphiql-rails (1.4.1)
|
||||
graphiql-rails (1.4.2)
|
||||
rails
|
||||
graphql (1.6.3)
|
||||
graphql (1.6.4)
|
||||
groupdate (3.2.0)
|
||||
activesupport (>= 3)
|
||||
gyoku (1.3.1)
|
||||
@@ -183,9 +183,10 @@ GEM
|
||||
hashie (3.5.5)
|
||||
highline (1.7.8)
|
||||
htmlentities (4.3.4)
|
||||
httpi (2.4.1)
|
||||
httpi (2.4.2)
|
||||
rack
|
||||
i18n (0.8.4)
|
||||
socksify
|
||||
i18n (0.8.6)
|
||||
i18n-tasks (0.9.15)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
@@ -198,8 +199,12 @@ GEM
|
||||
terminal-table (>= 1.5.1)
|
||||
initialjs-rails (0.2.0.5)
|
||||
railties (>= 3.1, < 6.0)
|
||||
invisible_captcha (0.9.2)
|
||||
invisible_captcha (0.9.3)
|
||||
rails (>= 3.2.0)
|
||||
jquery-fileupload-rails (0.4.7)
|
||||
actionpack (>= 3.1)
|
||||
railties (>= 3.1)
|
||||
sass (>= 3.2)
|
||||
jquery-rails (4.3.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
@@ -224,7 +229,7 @@ GEM
|
||||
knapsack (1.13.3)
|
||||
rake
|
||||
timecop (>= 0.1.0)
|
||||
kramdown (1.13.2)
|
||||
kramdown (1.14.0)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.4.1)
|
||||
@@ -246,7 +251,7 @@ GEM
|
||||
mime-types-data (3.2016.0521)
|
||||
mimemagic (0.3.2)
|
||||
mini_portile2 (2.2.0)
|
||||
minitest (5.10.2)
|
||||
minitest (5.10.3)
|
||||
mixlib-cli (1.7.0)
|
||||
mixlib-config (2.2.4)
|
||||
multi_json (1.12.1)
|
||||
@@ -259,9 +264,9 @@ GEM
|
||||
nokogiri (1.8.0)
|
||||
mini_portile2 (~> 2.2.0)
|
||||
nori (2.6.0)
|
||||
oauth (0.5.1)
|
||||
oauth2 (1.3.1)
|
||||
faraday (>= 0.8, < 0.12)
|
||||
oauth (0.5.3)
|
||||
oauth2 (1.4.0)
|
||||
faraday (>= 0.8, < 0.13)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
@@ -328,7 +333,7 @@ GEM
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.9)
|
||||
sprockets-rails
|
||||
rails-assets-markdown-it (8.2.1)
|
||||
rails-assets-markdown-it (8.2.2)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.8)
|
||||
@@ -363,7 +368,7 @@ GEM
|
||||
rspec-mocks (3.6.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-rails (3.6.0)
|
||||
rspec-rails (3.6.1)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
@@ -386,14 +391,14 @@ GEM
|
||||
sshkit (>= 1.2)
|
||||
safely_block (0.2.0)
|
||||
errbase
|
||||
sass (3.4.23)
|
||||
sass (3.4.25)
|
||||
sass-rails (5.0.6)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
savon (2.11.1)
|
||||
savon (2.11.2)
|
||||
akami (~> 1.2)
|
||||
builder (>= 2.1.2)
|
||||
gyoku (~> 1.2)
|
||||
@@ -408,12 +413,13 @@ GEM
|
||||
docile (~> 1.1.0)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
simplecov-html (0.10.1)
|
||||
sitemap_generator (5.3.1)
|
||||
builder (~> 3.0)
|
||||
social-share-button (0.10.0)
|
||||
coffee-rails
|
||||
spring (2.0.1)
|
||||
socksify (1.7.1)
|
||||
spring (2.0.2)
|
||||
activesupport (>= 4.2)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
@@ -424,23 +430,23 @@ GEM
|
||||
babel-source (>= 5.8.11)
|
||||
babel-transpiler
|
||||
sprockets (>= 3.0.0)
|
||||
sprockets-rails (3.2.0)
|
||||
sprockets-rails (3.2.1)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
sshkit (1.13.1)
|
||||
sshkit (1.14.0)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
term-ansicolor (1.6.0)
|
||||
tins (~> 1.0)
|
||||
terminal-table (1.7.3)
|
||||
unicode-display_width (~> 1.1.1)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thor (0.19.4)
|
||||
thread (0.2.2)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.7)
|
||||
timecop (0.8.1)
|
||||
tins (1.13.2)
|
||||
timecop (0.9.1)
|
||||
tins (1.15.0)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
turnout (2.4.0)
|
||||
@@ -452,14 +458,14 @@ GEM
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (3.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (1.1.3)
|
||||
unicode-display_width (1.3.0)
|
||||
unicorn (5.3.0)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
uniform_notifier (1.10.0)
|
||||
user_agent_parser (2.3.0)
|
||||
user_agent_parser (2.3.1)
|
||||
uuidtools (2.1.5)
|
||||
warden (1.2.6)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
wasabi (3.5.0)
|
||||
httpi (~> 2.0)
|
||||
@@ -473,7 +479,7 @@ GEM
|
||||
websocket-extensions (0.1.2)
|
||||
whenever (0.9.7)
|
||||
chronic (>= 0.6.3)
|
||||
xpath (2.0.0)
|
||||
xpath (2.1.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
@@ -515,6 +521,7 @@ DEPENDENCIES
|
||||
i18n-tasks (~> 0.9.15)
|
||||
initialjs-rails (~> 0.2.0.5)
|
||||
invisible_captcha (~> 0.9.2)
|
||||
jquery-fileupload-rails
|
||||
jquery-rails (~> 4.3.1)
|
||||
jquery-ui-rails (~> 6.0.1)
|
||||
kaminari (~> 1.0.1)
|
||||
@@ -559,4 +566,4 @@ DEPENDENCIES
|
||||
whenever (~> 0.9.7)
|
||||
|
||||
BUNDLED WITH
|
||||
1.15.1
|
||||
1.15.3
|
||||
|
||||
12
README.md
@@ -1,6 +1,6 @@
|
||||

|
||||

|
||||
|
||||
# Consul
|
||||
# CONSUL
|
||||
|
||||
Citizen Participation and Open Government Application
|
||||
|
||||
@@ -17,7 +17,7 @@ Citizen Participation and Open Government Application
|
||||
[](https://gitter.im/consul/consul?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://github.com/consul/consul/issues?q=is%3Aissue+is%3Aopen+label%3APRs-welcome)
|
||||
|
||||
This is the opensource code repository of the eParticipation website originally developed for the Madrid City government eParticipation website
|
||||
This is the opensource code repository of the eParticipation website CONSUL, originally developed for the Madrid City government eParticipation website
|
||||
|
||||
## Current state
|
||||
|
||||
@@ -33,7 +33,7 @@ Frontend tools used include [SCSS](http://sass-lang.com/) over [Foundation](http
|
||||
|
||||
**NOTE**: For more detailed instructions check the [docs](https://github.com/consul/consul/tree/master/doc/en/dev_test_setup.md)
|
||||
|
||||
Prerequisites: install git, Ruby 2.3.2, bundler gem, ghostscript and PostgreSQL (>=9.4).
|
||||
Prerequisites: install git, Ruby 2.3.2, bundler gem, and PostgreSQL (>=9.4).
|
||||
|
||||
```
|
||||
git clone https://github.com/consul/consul.git
|
||||
@@ -104,3 +104,7 @@ Code published under AFFERO GPL v3 (see [LICENSE-AGPLv3.txt](LICENSE-AGPLv3.txt)
|
||||
## Contributions
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
## Brand guidelines
|
||||
|
||||
If you want to use CONSUL logo you can [download the guidelines](https://raw.githubusercontent.com/consul/consul/master/public/consul_brand.zip) which contains a use guide and different versions and sizes of the logo.
|
||||
12
README_ES.md
@@ -1,6 +1,6 @@
|
||||

|
||||

|
||||
|
||||
# Consul
|
||||
# CONSUL
|
||||
|
||||
Aplicación de Participación Ciudadana y Gobierno Abierto
|
||||
|
||||
@@ -17,7 +17,7 @@ Aplicación de Participación Ciudadana y Gobierno Abierto
|
||||
[](https://gitter.im/consul/consul?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://github.com/consul/consul/issues?q=is%3Aissue+is%3Aopen+label%3APRs-welcome)
|
||||
|
||||
Este es el repositorio de código abierto de la Aplicación de Participación Ciudadana Consul, creada originariamente por el Ayuntamiento de Madrid.
|
||||
Este es el repositorio de código abierto de la Aplicación de Participación Ciudadana CONSUL, creada originariamente por el Ayuntamiento de Madrid.
|
||||
|
||||
## Estado del proyecto
|
||||
|
||||
@@ -32,7 +32,7 @@ Las herramientas utilizadas para el frontend no están cerradas aún. Los estilo
|
||||
|
||||
**NOTA**: para unas instrucciones más detalladas consulta la [documentación](https://github.com/consul/consul/tree/master/doc/es/dev_test_setup.md)
|
||||
|
||||
Prerequisitos: tener instalado git, Ruby 2.3.2, la gema `bundler`, ghostscript y PostgreSQL (9.4 o superior).
|
||||
Prerequisitos: tener instalado git, Ruby 2.3.2, la gema `bundler` y PostgreSQL (9.4 o superior).
|
||||
|
||||
```
|
||||
|
||||
@@ -101,3 +101,7 @@ El código de este proyecto está publicado bajo la licencia AFFERO GPL v3 (ver
|
||||
## Contribuciones
|
||||
|
||||
Ver fichero [CONTRIBUTING_ES.md](CONTRIBUTING_ES.md)
|
||||
|
||||
## Guía de estilo
|
||||
|
||||
Si quieres usar el logo de CONSUL puedes [descargar la guía de estilo](https://raw.githubusercontent.com/consul/consul/master/public/consul_brand.zip) que contiene una guía de uso y diferentes versiones y tamaños del logo.
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
app/assets/images/help/help_icon_budgets.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/assets/images/help/help_icon_debates.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/assets/images/help/help_icon_legislation_processes.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
app/assets/images/help/help_icon_polls.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/assets/images/help/help_icon_proposals.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -14,6 +14,7 @@
|
||||
//= require jquery_ujs
|
||||
//= require jquery-ui/widgets/datepicker
|
||||
//= require jquery-ui/i18n/datepicker-es
|
||||
//= require jquery-fileupload/basic
|
||||
//= require foundation
|
||||
//= require turbolinks
|
||||
//= require ckeditor/loader
|
||||
@@ -59,6 +60,7 @@
|
||||
//= require legislation_annotatable
|
||||
//= require watch_form_changes
|
||||
//= require followable
|
||||
//= require documentable
|
||||
//= require tree_navigator
|
||||
//= require custom
|
||||
|
||||
@@ -94,6 +96,7 @@ var initialize_modules = function() {
|
||||
App.LegislationAnnotatable.initialize();
|
||||
App.WatchFormChanges.initialize();
|
||||
App.TreeNavigator.initialize();
|
||||
App.Documentable.initialize();
|
||||
};
|
||||
|
||||
$(function(){
|
||||
|
||||
101
app/assets/javascripts/documentable.js.coffee
Normal file
@@ -0,0 +1,101 @@
|
||||
App.Documentable =
|
||||
|
||||
initialize: ->
|
||||
@initializeDirectUploads()
|
||||
@initializeInterface()
|
||||
|
||||
initializeDirectUploads: ->
|
||||
|
||||
$('input.document_ajax_attachment[type=file]').fileupload
|
||||
|
||||
paramName: "document[attachment]"
|
||||
|
||||
formData: null
|
||||
|
||||
add: (e, data) ->
|
||||
wrapper = $(e.target).closest('.document')
|
||||
index = $(e.target).data('index')
|
||||
is_nested_document = $(e.target).data('nested-document')
|
||||
$(wrapper).find('.progress-bar-placeholder').empty()
|
||||
data.progressBar = $(wrapper).find('.progress-bar-placeholder').html('<div class="progress-bar"><div class="loading-bar uploading"></div></div>')
|
||||
$(wrapper).find('.progress-bar-placeholder').css('display','block')
|
||||
data.formData = {
|
||||
"document[title]": $(wrapper).find('input.document-title').val() || data.files[0].name
|
||||
"index": index,
|
||||
"nested_document": is_nested_document
|
||||
}
|
||||
data.submit()
|
||||
|
||||
change: (e, data) ->
|
||||
wrapper = $(e.target).parent()
|
||||
$.each(data.files, (index, file)->
|
||||
$(wrapper).find('.file-name').text(file.name)
|
||||
)
|
||||
|
||||
progress: (e, data) ->
|
||||
progress = parseInt(data.loaded / data.total * 100, 10)
|
||||
$(data.progressBar).find('.loading-bar').css 'width', progress + '%'
|
||||
return
|
||||
|
||||
initializeInterface: ->
|
||||
input_files = $('input.document_ajax_attachment[type=file]')
|
||||
|
||||
$.each input_files, (index, file) ->
|
||||
wrapper = $(file).parent()
|
||||
App.Documentable.watchRemoveDocumentbutton(wrapper)
|
||||
|
||||
watchRemoveDocumentbutton: (wrapper) ->
|
||||
remove_document_button = $(wrapper).find('.remove-document')
|
||||
$(remove_document_button).on 'click', (e) ->
|
||||
e.preventDefault()
|
||||
$(wrapper).remove()
|
||||
$('#new_document_link').show()
|
||||
$('.max-documents-notice').hide()
|
||||
|
||||
uploadNestedDocument: (id, nested_document, result) ->
|
||||
$('#' + id).replaceWith(nested_document)
|
||||
@updateLoadingBar(id, result)
|
||||
@initialize()
|
||||
|
||||
uploadPlainDocument: (id, nested_document, result) ->
|
||||
$('#' + id).replaceWith(nested_document)
|
||||
@updateLoadingBar(id, result)
|
||||
@initialize()
|
||||
|
||||
updateLoadingBar: (id, result) ->
|
||||
if result
|
||||
$('#' + id).find('.loading-bar').addClass 'complete'
|
||||
else
|
||||
$('#' + id).find('.loading-bar').addClass 'errors'
|
||||
$('#' + id).find('.progress-bar-placeholder').css('display','block')
|
||||
|
||||
new: (nested_fields) ->
|
||||
$(".documents-list").append(nested_fields)
|
||||
@initialize()
|
||||
|
||||
destroyNestedDocument: (id, notice) ->
|
||||
$('#' + id).remove()
|
||||
@updateNotice(notice)
|
||||
|
||||
replacePlainDocument: (id, notice, plain_document) ->
|
||||
$('#' + id).replaceWith(plain_document)
|
||||
@updateNotice(notice)
|
||||
@initialize()
|
||||
|
||||
updateNotice: (notice) ->
|
||||
if $('[data-alert]').length > 0
|
||||
$('[data-alert]').replaceWith(notice)
|
||||
else
|
||||
$("body").append(notice)
|
||||
|
||||
updateNewDocumentButton: (link) ->
|
||||
if $('.document').length >= $('.documents').data('max-documents')
|
||||
$('#new_document_link').hide()
|
||||
$('.max-documents-notice').removeClass('hide')
|
||||
$('.max-documents-notice').show()
|
||||
else if $('#new_document_link').length > 0
|
||||
$('#new_document_link').replaceWith(link)
|
||||
$('.max-documents-notice').hide()
|
||||
else
|
||||
$('.max-documents-notice').hide()
|
||||
$(link).insertBefore('.documents hr:last')
|
||||
@@ -43,6 +43,7 @@ $budget: #7e328a;
|
||||
$budget-hover: #7571bf;
|
||||
|
||||
$highlight: #e7f2fc;
|
||||
$highlight-soft: #f3f8fd;
|
||||
$light: #f5f7fa;
|
||||
$featured: #ffdc5c;
|
||||
|
||||
|
||||
@@ -15,3 +15,4 @@
|
||||
@import 'annotator_overrides';
|
||||
@import 'jquery-ui/datepicker';
|
||||
@import 'datepicker_overrides';
|
||||
@import 'documentable';
|
||||
|
||||
59
app/assets/stylesheets/documentable.scss
Normal file
@@ -0,0 +1,59 @@
|
||||
.progress-bar-placeholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.document-form {
|
||||
.document .file-name {
|
||||
margin-top: 0;
|
||||
}
|
||||
.progress-bar-placeholder {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.document .loading-bar.errors {
|
||||
margin-top: $line-height * 2;
|
||||
}
|
||||
}
|
||||
|
||||
.document {
|
||||
.button {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
background-color: $light-gray;
|
||||
}
|
||||
|
||||
input.document_ajax_attachment[type=file]{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
margin-top: $line-height / 2;
|
||||
}
|
||||
|
||||
.loading-bar {
|
||||
height: 5px;
|
||||
width: 0;
|
||||
transition: width 500ms ease-out;
|
||||
|
||||
&.uploading {
|
||||
background-color: $dark-gray;
|
||||
}
|
||||
|
||||
&.complete {
|
||||
background-color: $success-color;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.errors {
|
||||
background-color: $alert-color;
|
||||
width: 100%;
|
||||
margin-top: $line-height / 2;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-bar.no-transition {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,10 @@
|
||||
content: '\72';
|
||||
}
|
||||
|
||||
.icon-documents::before {
|
||||
content: '\68';
|
||||
}
|
||||
|
||||
.icon-proposals::before {
|
||||
content: '\68';
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
// 16. Flags
|
||||
// 17. Activity
|
||||
// 18. Banners
|
||||
// 19. Documents
|
||||
//
|
||||
|
||||
// 01. Global styles
|
||||
@@ -91,6 +92,11 @@ a {
|
||||
color: $link;
|
||||
}
|
||||
|
||||
.button.hollow.error {
|
||||
border-color: $alert-border;
|
||||
color: $color-alert;
|
||||
}
|
||||
|
||||
.postfix.button {
|
||||
padding: 0;
|
||||
}
|
||||
@@ -216,9 +222,8 @@ a {
|
||||
}
|
||||
|
||||
.menu.vertical {
|
||||
background: #fff;
|
||||
margin: $line-height 0;
|
||||
padding: $line-height;
|
||||
padding: $line-height 0;
|
||||
|
||||
li {
|
||||
margin-bottom: $line-height;
|
||||
@@ -319,6 +324,10 @@ a {
|
||||
background: $brand;
|
||||
}
|
||||
|
||||
.align-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
// 02. Header
|
||||
// ----------
|
||||
|
||||
@@ -416,6 +425,7 @@ header {
|
||||
.menu {
|
||||
|
||||
&.is-dropdown-submenu {
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
margin-top: rem-calc(-24);
|
||||
padding: 0;
|
||||
@@ -1821,6 +1831,7 @@ table {
|
||||
|
||||
.divider {
|
||||
color: $text-light;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form {
|
||||
@@ -2128,3 +2139,125 @@ table {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 19. Documents
|
||||
.document-form form {
|
||||
|
||||
.radio-buttons {
|
||||
label {
|
||||
margin-right: $line-height;
|
||||
}
|
||||
}
|
||||
|
||||
.source-option-link {
|
||||
input {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.error {
|
||||
margin-bottom: $line-height;
|
||||
}
|
||||
|
||||
label {
|
||||
&.error {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.source-option-file {
|
||||
.file-name {
|
||||
label {
|
||||
|
||||
@include breakpoint(small medium) {
|
||||
float: none;
|
||||
}
|
||||
|
||||
@include breakpoint(large) {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
@include breakpoint(small medium) {
|
||||
float: none;
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@include breakpoint(large) {
|
||||
float: left;
|
||||
margin-bottom: 0;
|
||||
margin-top: $line-height / 2;
|
||||
margin-left: $line-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attachment-errors {
|
||||
margin-bottom: $line-height;
|
||||
}
|
||||
}
|
||||
|
||||
.documents-list {
|
||||
|
||||
table {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
td {
|
||||
position: relative;
|
||||
|
||||
@include breakpoint(small) {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@include breakpoint(medium) {
|
||||
float: none;
|
||||
}
|
||||
|
||||
a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
padding-left: $line-height * 1.5;
|
||||
|
||||
@include breakpoint(small) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@include breakpoint(medium) {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
@include breakpoint(large) {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child::before {
|
||||
color: #007bb7;
|
||||
content: 'G';
|
||||
font-family: "icons" !important;
|
||||
font-size: rem-calc(24);
|
||||
left: rem-calc(6);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
@include breakpoint(small) {
|
||||
padding-top: rem-calc(12);
|
||||
}
|
||||
|
||||
@include breakpoint(medium) {
|
||||
padding-top: rem-calc(22);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,11 +248,13 @@
|
||||
.debate-form,
|
||||
.proposal-form,
|
||||
.budget-investment-form,
|
||||
.spending-proposal-form {
|
||||
.spending-proposal-form,
|
||||
.document-form {
|
||||
|
||||
.icon-debates,
|
||||
.icon-proposals,
|
||||
.icon-budget {
|
||||
.icon-budget,
|
||||
.icon-documents {
|
||||
font-size: rem-calc(50);
|
||||
line-height: $line-height;
|
||||
opacity: 0.5;
|
||||
@@ -262,7 +264,8 @@
|
||||
color: $debates;
|
||||
}
|
||||
|
||||
.icon-proposals {
|
||||
.icon-proposals,
|
||||
.icon-documents {
|
||||
color: $proposals;
|
||||
}
|
||||
|
||||
@@ -294,7 +297,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.proposal-form {
|
||||
.proposal-form,
|
||||
.document-form {
|
||||
|
||||
.recommendations li::before {
|
||||
color: $proposals;
|
||||
@@ -311,7 +315,8 @@
|
||||
.polls-show,
|
||||
.debate-quiz,
|
||||
.budget-investment-show,
|
||||
.draft-panels {
|
||||
.draft-panels,
|
||||
.debate-questions {
|
||||
|
||||
p {
|
||||
word-wrap: break-word;
|
||||
@@ -328,10 +333,13 @@
|
||||
.whatsapp::before {
|
||||
background-color: #43d854;
|
||||
color: #fff;
|
||||
font-size: 1.7em;
|
||||
margin-left: rem-calc(0.5);
|
||||
padding: rem-calc(9.5) rem-calc(9.8);
|
||||
vertical-align: rem-calc(10);
|
||||
display: inline-block;
|
||||
font-size: rem-calc(30);
|
||||
height: rem-calc(48);
|
||||
padding-top: rem-calc(9);
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
width: rem-calc(48);
|
||||
}
|
||||
|
||||
.edit-debate,
|
||||
@@ -424,33 +432,30 @@
|
||||
|
||||
.document-link,
|
||||
.video-link {
|
||||
border: 1px solid $border;
|
||||
background: $highlight-soft;
|
||||
border: 1px solid $highlight;
|
||||
display: block;
|
||||
margin: $line-height / 2 0;
|
||||
padding: $line-height / 2;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
padding-left: rem-calc(24);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
::before {
|
||||
color: #007bb7;
|
||||
content: 'G';
|
||||
font-family: "icons" !important;
|
||||
[class^="icon-"] {
|
||||
display: inline-block;
|
||||
font-size: rem-calc(24);
|
||||
left: rem-calc(6);
|
||||
padding-top: rem-calc(3);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
line-height: $line-height;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.video-link {
|
||||
.icon-document {
|
||||
color: #007bb7;
|
||||
}
|
||||
|
||||
::before {
|
||||
.icon-video {
|
||||
color: #cc181e;
|
||||
content: 'D';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,6 +750,12 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.document-form{
|
||||
max-width: 75rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.more-info {
|
||||
clear: both;
|
||||
color: $text-medium;
|
||||
@@ -874,6 +885,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.help-link {
|
||||
margin-left: $line-height;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
color: $link;
|
||||
content: '\4e';
|
||||
font-family: 'icons';
|
||||
position: absolute;
|
||||
left: -24px;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
// 05. Featured
|
||||
// ------------
|
||||
|
||||
@@ -1480,13 +1505,9 @@
|
||||
|
||||
.poll,
|
||||
.poll-question {
|
||||
background: #fff;
|
||||
border-radius: rem-calc(6);
|
||||
border: 1px solid $border;
|
||||
margin-bottom: $line-height / 2;
|
||||
}
|
||||
|
||||
.poll {
|
||||
padding: $line-height;
|
||||
padding: $line-height / 2;
|
||||
position: relative;
|
||||
|
||||
.icon-poll-answer {
|
||||
|
||||
@@ -44,10 +44,12 @@ module Budgets
|
||||
set_comment_flags(@comment_tree.comments)
|
||||
load_investment_votes(@investment)
|
||||
@investment_ids = [@investment.id]
|
||||
@document = Document.new(documentable: @investment)
|
||||
end
|
||||
|
||||
def create
|
||||
@investment.author = current_user
|
||||
recover_documents_from_cache(@investment)
|
||||
|
||||
if @investment.save
|
||||
Mailer.budget_investment_created(@investment).deliver_later
|
||||
@@ -104,7 +106,8 @@ module Budgets
|
||||
|
||||
def investment_params
|
||||
params.require(:budget_investment).permit(:title, :description, :external_url, :heading_id, :tag_list,
|
||||
:organization_name, :location, :terms_of_service)
|
||||
:organization_name, :location, :terms_of_service,
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id])
|
||||
end
|
||||
|
||||
def load_ballot
|
||||
|
||||
@@ -58,6 +58,8 @@ module CommentableActions
|
||||
|
||||
def update
|
||||
resource.assign_attributes(strong_params)
|
||||
recover_documents_from_cache(resource)
|
||||
|
||||
if resource.save
|
||||
redirect_to resource, notice: t("flash.actions.update.#{resource_name.underscore}")
|
||||
else
|
||||
@@ -110,4 +112,11 @@ module CommentableActions
|
||||
nil
|
||||
end
|
||||
|
||||
def recover_documents_from_cache(resource)
|
||||
return false unless resource.try(:documents)
|
||||
resource.documents = resource.documents.each do |document|
|
||||
document.set_attachment_from_cached_attachment if document.cached_attachment.present?
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
100
app/controllers/documents_controller.rb
Normal file
@@ -0,0 +1,100 @@
|
||||
class DocumentsController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_filter :find_documentable, except: :destroy
|
||||
before_filter :prepare_new_document, only: [:new, :new_nested]
|
||||
before_filter :prepare_document_for_creation, only: :create
|
||||
|
||||
load_and_authorize_resource except: :upload
|
||||
skip_authorization_check only: :upload
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def new_nested
|
||||
end
|
||||
|
||||
def create
|
||||
recover_attachments_from_cache
|
||||
|
||||
if @document.save
|
||||
flash[:notice] = t "documents.actions.create.notice"
|
||||
redirect_to params[:from]
|
||||
else
|
||||
flash[:alert] = t "documents.actions.create.alert"
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if @document.destroy
|
||||
flash[:notice] = t "documents.actions.destroy.notice"
|
||||
else
|
||||
flash[:alert] = t "documents.actions.destroy.alert"
|
||||
end
|
||||
redirect_to params[:from]
|
||||
end
|
||||
format.js do
|
||||
if @document.destroy
|
||||
flash.now[:notice] = t "documents.actions.destroy.notice"
|
||||
else
|
||||
flash.now[:alert] = t "documents.actions.destroy.alert"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_upload
|
||||
@document = Document.new(cached_attachment: params[:path])
|
||||
@document.set_attachment_from_cached_attachment
|
||||
@document.documentable = @documentable
|
||||
|
||||
if @document.attachment.destroy
|
||||
flash.now[:notice] = t "documents.actions.destroy.notice"
|
||||
else
|
||||
flash.now[:alert] = t "documents.actions.destroy.alert"
|
||||
end
|
||||
render :destroy
|
||||
end
|
||||
|
||||
def upload
|
||||
@document = Document.new(document_params.merge(user: current_user))
|
||||
@document.documentable = @documentable
|
||||
|
||||
if @document.valid?
|
||||
@document.attachment.save
|
||||
@document.set_cached_attachment_from_attachment(URI(request.url))
|
||||
else
|
||||
@document.attachment.destroy
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def document_params
|
||||
params.require(:document).permit(:title, :documentable_type, :documentable_id,
|
||||
:attachment, :cached_attachment, :user_id)
|
||||
end
|
||||
|
||||
def find_documentable
|
||||
@documentable = params[:documentable_type].constantize.find_or_initialize_by(id: params[:documentable_id])
|
||||
end
|
||||
|
||||
def prepare_new_document
|
||||
@document = Document.new(documentable: @documentable, user_id: current_user.id)
|
||||
end
|
||||
|
||||
def prepare_document_for_creation
|
||||
@document = Document.new(document_params)
|
||||
@document.documentable = @documentable
|
||||
@document.user = current_user
|
||||
end
|
||||
|
||||
def recover_attachments_from_cache
|
||||
if @document.attachment.blank? && @document.cached_attachment.present?
|
||||
@document.set_attachment_from_cached_attachment
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -19,11 +19,13 @@ class ProposalsController < ApplicationController
|
||||
def show
|
||||
super
|
||||
@notifications = @proposal.notifications
|
||||
@document = Document.new(documentable: @proposal)
|
||||
redirect_to proposal_path(@proposal), status: :moved_permanently if request.path != proposal_path(@proposal)
|
||||
end
|
||||
|
||||
def create
|
||||
@proposal = Proposal.new(proposal_params.merge(author: current_user))
|
||||
recover_documents_from_cache(@proposal)
|
||||
|
||||
if @proposal.save
|
||||
redirect_to share_proposal_path(@proposal), notice: I18n.t('flash.actions.create.proposal')
|
||||
@@ -75,7 +77,8 @@ class ProposalsController < ApplicationController
|
||||
|
||||
def proposal_params
|
||||
params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url,
|
||||
:responsible_name, :tag_list, :terms_of_service, :geozone_id)
|
||||
:responsible_name, :tag_list, :terms_of_service, :geozone_id,
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id] )
|
||||
end
|
||||
|
||||
def retired_params
|
||||
@@ -121,4 +124,5 @@ class ProposalsController < ApplicationController
|
||||
def load_successful_proposals
|
||||
@proposal_successful_exists = Proposal.successful.exists?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
41
app/helpers/documentables_helper.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
module DocumentablesHelper
|
||||
|
||||
def documentable_class(documentable)
|
||||
documentable.class.name.parameterize('_')
|
||||
end
|
||||
|
||||
def max_documents_allowed(documentable)
|
||||
documentable.class.max_documents_allowed
|
||||
end
|
||||
|
||||
def max_file_size(documentable)
|
||||
bytesToMeg(documentable.class.max_file_size)
|
||||
end
|
||||
|
||||
def accepted_content_types(documentable)
|
||||
documentable.class.accepted_content_types
|
||||
end
|
||||
|
||||
def accepted_content_types_extensions(documentable_class)
|
||||
documentable_class.accepted_content_types
|
||||
.collect{ |content_type| ".#{content_type.split("/").last}" }
|
||||
.join(",")
|
||||
end
|
||||
|
||||
def humanized_accepted_content_types(documentable)
|
||||
documentable.class.accepted_content_types
|
||||
.collect{ |content_type| content_type.split("/").last }
|
||||
.join(", ")
|
||||
end
|
||||
|
||||
def documentables_note(documentable)
|
||||
t "documents.form.note", max_documents_allowed: max_documents_allowed(documentable),
|
||||
accepted_content_types: humanized_accepted_content_types(documentable),
|
||||
max_file_size: max_file_size(documentable)
|
||||
end
|
||||
|
||||
def max_documents_allowed?(documentable)
|
||||
documentable.documents.count >= documentable.class.max_documents_allowed
|
||||
end
|
||||
|
||||
end
|
||||
89
app/helpers/documents_helper.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
module DocumentsHelper
|
||||
|
||||
def document_attachment_file_name(document)
|
||||
document.attachment_file_name
|
||||
end
|
||||
|
||||
def errors_on_attachment(document)
|
||||
document.errors[:attachment].join(', ') if document.errors.key?(:attachment)
|
||||
end
|
||||
|
||||
def bytesToMeg(bytes)
|
||||
bytes / Numeric::MEGABYTE
|
||||
end
|
||||
|
||||
def document_nested_field_name(document, index, field)
|
||||
parent = document.documentable_type.parameterize.underscore
|
||||
"#{parent.parameterize}[documents_attributes][#{index}][#{field}]"
|
||||
end
|
||||
|
||||
def document_nested_field_id(document, index, field)
|
||||
parent = document.documentable_type.parameterize.underscore
|
||||
"#{parent.parameterize}_documents_attributes_#{index}_#{field}"
|
||||
end
|
||||
|
||||
def document_nested_field_wrapper_id(index)
|
||||
"document_#{index}"
|
||||
end
|
||||
|
||||
def render_destroy_document_link(document, index)
|
||||
if document.persisted?
|
||||
link_to t('documents.form.delete_button'),
|
||||
document_path(document, index: index, nested_document: true),
|
||||
method: :delete,
|
||||
remote: true,
|
||||
data: { confirm: t('documents.actions.destroy.confirm') },
|
||||
class: "delete float-right"
|
||||
elsif !document.persisted? && document.cached_attachment.present?
|
||||
link_to t('documents.form.delete_button'),
|
||||
destroy_upload_documents_path(path: document.cached_attachment,
|
||||
nested_document: true,
|
||||
index: index,
|
||||
documentable_type: document.documentable_type,
|
||||
documentable_id: document.documentable_id),
|
||||
method: :delete,
|
||||
remote: true,
|
||||
class: "delete float-right"
|
||||
else
|
||||
link_to t('documents.form.delete_button'),
|
||||
"#",
|
||||
class: "delete float-right remove-document"
|
||||
end
|
||||
end
|
||||
|
||||
def render_attachment(document, index)
|
||||
html = file_field_tag :attachment,
|
||||
accept: accepted_content_types_extensions(document.documentable_type.constantize),
|
||||
class: 'document_ajax_attachment',
|
||||
data: {
|
||||
url: document_direct_upload_url(document),
|
||||
cached_attachment_input_field: document_nested_field_id(document, index, :cached_attachment),
|
||||
multiple: false,
|
||||
index: index,
|
||||
nested_document: true
|
||||
},
|
||||
name: document_nested_field_name(document, index, :attachment),
|
||||
id: document_nested_field_id(document, index, :attachment)
|
||||
if document.attachment.blank? && document.cached_attachment.blank?
|
||||
klass = document.errors[:attachment].any? ? "error" : ""
|
||||
html += label_tag document_nested_field_id(document, index, :attachment),
|
||||
t("documents.form.attachment_label"),
|
||||
class: "button hollow #{klass}"
|
||||
if document.errors[:attachment].any?
|
||||
html += content_tag :small, class: "error" do
|
||||
errors_on_attachment(document)
|
||||
end
|
||||
end
|
||||
end
|
||||
html
|
||||
end
|
||||
|
||||
def document_direct_upload_url(document)
|
||||
upload_documents_url(
|
||||
documentable_type: document.documentable_type,
|
||||
documentable_id: document.documentable_id,
|
||||
format: :js
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -40,6 +40,26 @@ module UsersHelper
|
||||
current_user && current_user.administrator?
|
||||
end
|
||||
|
||||
def current_moderator?
|
||||
current_user && current_user.moderator?
|
||||
end
|
||||
|
||||
def current_valuator?
|
||||
current_user && current_user.valuator?
|
||||
end
|
||||
|
||||
def current_manager?
|
||||
current_user && current_user.manager?
|
||||
end
|
||||
|
||||
def current_poll_officer?
|
||||
current_user && current_user.poll_officer?
|
||||
end
|
||||
|
||||
def show_admin_menu?
|
||||
current_administrator? || current_moderator? || current_valuator? || current_manager? || current_poll_officer?
|
||||
end
|
||||
|
||||
def interests_title_text(user)
|
||||
if current_user == user
|
||||
t('account.show.public_interests_my_title_list')
|
||||
|
||||
@@ -73,6 +73,7 @@ module Abilities
|
||||
can [:manage], ::Legislation::Question
|
||||
cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation]
|
||||
|
||||
can [:create, :destroy], Document
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,6 +36,9 @@ module Abilities
|
||||
|
||||
can [:create, :destroy], Follow
|
||||
|
||||
can [:create, :destroy, :new], Document, documentable: { author_id: user.id }
|
||||
can [:new_nested, :upload, :destroy_upload], Document
|
||||
|
||||
unless user.organization?
|
||||
can :vote, Debate
|
||||
can :vote, Comment
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
class Budget
|
||||
class Investment < ActiveRecord::Base
|
||||
|
||||
include Measurable
|
||||
include Sanitizable
|
||||
include Taggable
|
||||
include Searchable
|
||||
include Reclassification
|
||||
include Followable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
acts_as_votable
|
||||
acts_as_paranoid column: :hidden_at
|
||||
|
||||
20
app/models/concerns/documentable.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
module Documentable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
has_many :documents, as: :documentable, dependent: :destroy
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
attr_reader :max_documents_allowed, :max_file_size, :accepted_content_types
|
||||
|
||||
private
|
||||
|
||||
def documentable(options= {})
|
||||
@max_documents_allowed = options[:max_documents_allowed]
|
||||
@max_file_size = options[:max_file_size]
|
||||
@accepted_content_types = options[:accepted_content_types]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
81
app/models/document.rb
Normal file
@@ -0,0 +1,81 @@
|
||||
class Document < ActiveRecord::Base
|
||||
include DocumentsHelper
|
||||
include DocumentablesHelper
|
||||
has_attached_file :attachment, path: ":rails_root/public/system/:class/:prefix/:style/:filename"
|
||||
attr_accessor :cached_attachment
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :documentable, polymorphic: true
|
||||
|
||||
# Disable paperclip security validation due to polymorphic configuration
|
||||
# Paperclip do not allow to user Procs on valiations definition
|
||||
do_not_validate_attachment_file_type :attachment
|
||||
validate :attachment_presence
|
||||
validate :validate_attachment_content_type, if: -> { attachment.present? }
|
||||
validate :validate_attachment_size, if: -> { attachment.present? }
|
||||
validates :title, presence: true
|
||||
validates :user_id, presence: true
|
||||
validates :documentable_id, presence: true, if: -> { persisted? }
|
||||
validates :documentable_type, presence: true, if: -> { persisted? }
|
||||
|
||||
after_save :remove_cached_document, if: -> { valid? && persisted? && cached_attachment.present? }
|
||||
|
||||
def set_cached_attachment_from_attachment(prefix)
|
||||
self.cached_attachment = if Paperclip::Attachment.default_options[:storage] == :filesystem
|
||||
attachment.path
|
||||
else
|
||||
prefix + attachment.url
|
||||
end
|
||||
end
|
||||
|
||||
def set_attachment_from_cached_attachment
|
||||
self.attachment = if Paperclip::Attachment.default_options[:storage] == :filesystem
|
||||
File.open(cached_attachment)
|
||||
else
|
||||
URI.parse(cached_attachment)
|
||||
end
|
||||
end
|
||||
|
||||
Paperclip.interpolates :prefix do |attachment, style|
|
||||
attachment.instance.prefix(attachment, style)
|
||||
end
|
||||
|
||||
def prefix(attachment, style)
|
||||
if !attachment.instance.persisted?
|
||||
"cached_attachments/user/#{attachment.instance.user_id}"
|
||||
else
|
||||
":attachment/:id_partition"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_attachment_size
|
||||
if documentable.present? &&
|
||||
attachment_file_size > documentable.class.max_file_size
|
||||
errors[:attachment] = I18n.t("documents.errors.messages.in_between",
|
||||
min: "0 Bytes",
|
||||
max: "#{max_file_size(documentable)} MB")
|
||||
end
|
||||
end
|
||||
|
||||
def validate_attachment_content_type
|
||||
if documentable.present? &&
|
||||
!accepted_content_types(documentable).include?(attachment_content_type)
|
||||
errors[:attachment] = I18n.t("documents.errors.messages.wrong_content_type",
|
||||
content_type: attachment_content_type,
|
||||
accepted_content_types: humanized_accepted_content_types(documentable))
|
||||
end
|
||||
end
|
||||
|
||||
def attachment_presence
|
||||
if attachment.blank? && cached_attachment.blank?
|
||||
errors[:attachment] = I18n.t("errors.messages.blank")
|
||||
end
|
||||
end
|
||||
|
||||
def remove_cached_document
|
||||
File.delete(cached_attachment) if File.exists?(cached_attachment)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -9,6 +9,11 @@ class Proposal < ActiveRecord::Base
|
||||
include HasPublicAuthor
|
||||
include Graphqlable
|
||||
include Followable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
acts_as_votable
|
||||
acts_as_paranoid column: :hidden_at
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
<% provide :title do %><%= t('budgets.index.title') %><% end %>
|
||||
<% content_for :canonical do %>
|
||||
<%= render "shared/canonical", href: budgets_url %>
|
||||
<% end %>
|
||||
|
||||
<div class="expanded budget no-margin-top padding">
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<h1><%= t('budgets.index.title') %></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "shared/section_header", i18n_namespace: "budgets.index.section_header", image: "budgets" %>
|
||||
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 medium-9 column">
|
||||
@@ -32,5 +27,16 @@
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="section_help" class="margin" data-magellan-target="section_help">
|
||||
<p class="lead">
|
||||
<strong><%= t("budgets.index.section_footer.title") %></strong>
|
||||
</p>
|
||||
<p><%= t("budgets.index.section_footer.help_text_1") %></p>
|
||||
<p><%= t("budgets.index.section_footer.help_text_2") %></p>
|
||||
<p><%= t("budgets.index.section_footer.help_text_3",
|
||||
org: link_to(setting['org_name'], new_user_registration_path)).html_safe %></p>
|
||||
<p><%= t("budgets.index.section_footer.help_text_4") %></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
</h3>
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="tabs-title">
|
||||
<%= link_to "#tab-documents" do %>
|
||||
<h3>
|
||||
<%= t("documents.tab") %>
|
||||
(<%= @investment.documents.count %>)
|
||||
</h3>
|
||||
<% end %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
<%= f.text_field :external_url %>
|
||||
</div>
|
||||
|
||||
<div class="documents small-12 column" data-max-documents="<%= Budget::Investment.max_documents_allowed %>">
|
||||
<%= render 'documents/nested_documents', documentable: @investment %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 column">
|
||||
<%= f.text_field :location %>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= back_link_to budget_investments_path(investment.budget, heading_id: investment.heading) %>
|
||||
|
||||
<% if can?(:create, @document) && investment.documents.size < Budget::Investment.max_documents_allowed %>
|
||||
<%= link_to t("documents.upload_document"),
|
||||
new_document_path(documentable_id:investment, documentable_type: investment.class.name, from: request.url),
|
||||
class: 'button hollow float-right' %>
|
||||
<% end %>
|
||||
|
||||
<h1><%= investment.title %></h1>
|
||||
|
||||
<div class="budget-investment-info">
|
||||
@@ -14,7 +20,6 @@
|
||||
<span class="bullet"> • </span>
|
||||
<%= investment.heading.name %>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<p id="investment_code">
|
||||
<%= t("budgets.investments.show.code_html", code: investment.id) %>
|
||||
@@ -51,6 +56,7 @@
|
||||
<h2><%= t('budgets.investments.show.price_explanation') %></h2>
|
||||
<p><%= investment.price_explanation %></p>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
<aside class="small-12 medium-3 column">
|
||||
|
||||
@@ -19,4 +19,11 @@
|
||||
comment_flags: @comment_flags,
|
||||
display_comments_count: false } %>
|
||||
</div>
|
||||
|
||||
<div class="tabs-panel" id="tab-documents">
|
||||
<%= render 'documents/documents',
|
||||
documents: @investment.documents,
|
||||
max_documents_allowed: Budget::Investment.max_documents_allowed %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
style="<%= results_type != :compatible ? 'display: none' : '' %>"
|
||||
id="<%= results_type %>-container">
|
||||
|
||||
<h3 class="inline-block">
|
||||
<h4 class="inline-block">
|
||||
<%= title %>
|
||||
</h3>
|
||||
</h4>
|
||||
|
||||
<table id="budget-investments-<%= results_type %>" class="table-for-mobile">
|
||||
<thead>
|
||||
|
||||
@@ -37,21 +37,20 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-3 large-2 column">
|
||||
<div class="row">
|
||||
<ul class="menu vertical no-margin-top no-padding-top">
|
||||
<h3>
|
||||
<%= t("budgets.results.heading_selection_title") %>
|
||||
</h3>
|
||||
<h3 class="margin-bottom">
|
||||
<%= t("budgets.results.heading_selection_title") %>
|
||||
</h3>
|
||||
<ul class="menu vertical no-margin-top no-padding-top">
|
||||
|
||||
<% @budget.headings.order('id ASC').each do |heading| %>
|
||||
<li>
|
||||
<%= link_to heading.name,
|
||||
budget_results_path(@budget, heading_id: heading.to_param),
|
||||
class: heading.to_param == @heading.to_param ? 'active' : '' %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<% @budget.headings.order('id ASC').each do |heading| %>
|
||||
<li>
|
||||
<%= link_to heading.name,
|
||||
budget_results_path(@budget, heading_id: heading.to_param),
|
||||
class: heading.to_param == @heading.to_param ? 'active' : '' %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<span class="float-right"><%= link_to t("budgets.results.show_all_link"), "#", class: "js-toggle-link button hollow margin-bottom", data: {'toggle-selector' => '.js-discarded', 'toggle-text' => t("budgets.results.hide_discarded_link")} %></span>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
title="<%= t('shared.flag') %>">
|
||||
<span class="icon-flag flag-disable"></span>
|
||||
</a>
|
||||
<div id="flag-drop-comment-<%= comment.id %>"
|
||||
<span id="flag-drop-comment-<%= comment.id %>"
|
||||
class="dropdown-pane"
|
||||
data-dropdown
|
||||
data-auto-focus="true">
|
||||
<%= link_to t("shared.flag"), flag_comment_path(comment), method: :put,
|
||||
remote: true, id: "flag-comment-#{comment.id}" %>
|
||||
</div>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% if show_unflag_action? comment %>
|
||||
@@ -22,9 +22,9 @@
|
||||
title="<%= t('shared.unflag') %>">
|
||||
<span class="icon-flag flag-active"></span>
|
||||
</a>
|
||||
<div class="dropdown-pane" id="unflag-drop-comment-<%= comment.id %>" data-dropdown data-auto-focus="true">
|
||||
<span class="dropdown-pane" id="unflag-drop-comment-<%= comment.id %>" data-dropdown data-auto-focus="true">
|
||||
<%= link_to t("shared.unflag"), unflag_comment_path(comment), method: :put,
|
||||
remote: true, id: "unflag-comment-#{comment.id}" %>
|
||||
</div>
|
||||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
<a id="flag-expand-debate-<%= debate.id %>" data-toggle="flag-drop-debate-<%= debate.id %>" title="<%= t('shared.flag') %>">
|
||||
<span class="icon-flag flag-disable"></span>
|
||||
</a>
|
||||
<div class="dropdown-pane" id="flag-drop-debate-<%= debate.id %>" data-dropdown data-auto-focus="true">
|
||||
<span class="dropdown-pane" id="flag-drop-debate-<%= debate.id %>" data-dropdown data-auto-focus="true">
|
||||
<%= link_to t('shared.flag'), flag_debate_path(debate), method: :put, remote: true, id: "flag-debate-#{ debate.id }" %>
|
||||
</div>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% if show_unflag_action? debate %>
|
||||
<a id="unflag-expand-debate-<%= debate.id %>" data-toggle="unflag-drop-debate-<%= debate.id %>" title="<%= t('shared.unflag') %>">
|
||||
<span class="icon-flag flag-active"></span>
|
||||
</a>
|
||||
<div class="dropdown-pane" id="unflag-drop-debate-<%= debate.id %>" data-dropdown data-auto-focus="true">
|
||||
<span class="dropdown-pane" id="unflag-drop-debate-<%= debate.id %>" data-dropdown data-auto-focus="true">
|
||||
<%= link_to t('shared.unflag'), unflag_debate_path(debate), method: :put, remote: true, id: "unflag-debate-#{ debate.id }" %>
|
||||
</div>
|
||||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
<% end %>
|
||||
|
||||
<main>
|
||||
<h1 class="show-for-sr"><%= t("shared.outline.debates") %></h1>
|
||||
|
||||
<% if @search_terms || @advanced_search_terms || @tag_filter %>
|
||||
<div class="highlight no-margin-top padding margin-bottom">
|
||||
<div class="row">
|
||||
@@ -33,6 +31,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "shared/section_header", i18n_namespace: "debates.index.section_header", image: "debates" %>
|
||||
<% end %>
|
||||
|
||||
<div class="row">
|
||||
@@ -56,6 +56,21 @@
|
||||
|
||||
<%= render @debates %>
|
||||
<%= paginate @debates %>
|
||||
|
||||
<% unless @search_terms || @advanced_search_terms || @tag_filter %>
|
||||
<div id="section_help" class="margin" data-magellan-target="section_help">
|
||||
<p class="lead">
|
||||
<strong><%= t("debates.index.section_footer.title") %></strong>
|
||||
</p>
|
||||
<p><%= t("debates.index.section_footer.help_text_1") %></p>
|
||||
<p><%= t("debates.index.section_footer.help_text_2",
|
||||
org: link_to(setting['org_name'], new_user_registration_path)).html_safe %></p>
|
||||
<p><%= t("debates.index.section_footer.help_text_3",
|
||||
proposal: link_to(t("debates.index.section_footer.proposals_link"), proposals_path),
|
||||
budget: link_to(t("debates.index.section_footer.budget_link"), budgets_path)).html_safe %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-3 column">
|
||||
|
||||
20
app/views/documents/_document.html.erb
Normal file
@@ -0,0 +1,20 @@
|
||||
<tr id="<%= dom_id(document)%>">
|
||||
<td class="document-link">
|
||||
<%= document.title %>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<%= link_to t('documents.buttons.download_document'),
|
||||
document.attachment.url,
|
||||
target: "_blank",
|
||||
rel: "nofollow",
|
||||
class: 'button hollow' %>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<% if can? :destroy, Document %>
|
||||
<%= link_to t('documents.buttons.destroy_document'),
|
||||
document_path(document, from: request.url), method: :delete,
|
||||
data: { confirm: t('documents.actions.destroy.confirm') },
|
||||
class: 'button hollow alert' %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
35
app/views/documents/_documents.html.erb
Normal file
@@ -0,0 +1,35 @@
|
||||
<% if documents.any? %>
|
||||
|
||||
<% if documents.size == max_documents_allowed && can?(:create, Document) %>
|
||||
<div class="row documents-list">
|
||||
<div class="small-12 column">
|
||||
<div class="callout warning text-center">
|
||||
<%= t "documents.max_documents_allowed_reached_html" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="row documents-list">
|
||||
<div class="small-12 column">
|
||||
<table>
|
||||
<tbody>
|
||||
<% documents.each do |document| %>
|
||||
<%= render "documents/document", document: document %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% else %>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<div class="callout primary text-center">
|
||||
<%= t('documents.no_documents') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% end %>
|
||||
20
app/views/documents/_form.html.erb
Normal file
@@ -0,0 +1,20 @@
|
||||
<%= form_for @document,
|
||||
url: documents_path(
|
||||
documentable_type: @document.documentable_type,
|
||||
documentable_id: @document.documentable_id,
|
||||
from: params[:from]
|
||||
),
|
||||
html: { multipart: true, class: "documentable"},
|
||||
data: { direct_upload_url: upload_documents_url(documentable_type: @document.documentable_type, documentable_id: @document.documentable_id) } do |f| %>
|
||||
|
||||
<%= render 'shared/errors', resource: @document %>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<%= render 'plain_fields', document: @document %>
|
||||
|
||||
<div class="actions small-12 medium-6 large-4 end column">
|
||||
<%= f.submit(t("documents.form.submit_button"), class: "button expanded") %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
22
app/views/documents/_nested_documents.html.erb
Normal file
@@ -0,0 +1,22 @@
|
||||
<div class="documents-list">
|
||||
<%= label_tag :documents, t("documents.form.title") %>
|
||||
<p class="help-text"><%= documentables_note(documentable) %></p>
|
||||
|
||||
<% documentable.documents.each_with_index do |document, index| %>
|
||||
<%= render 'documents/nested_fields', document: document, index: index, documentable: documentable %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% unless max_documents_allowed?(documentable) %>
|
||||
<%= link_to t("documents.form.add_new_document"),
|
||||
new_nested_documents_path(documentable_type: documentable.class.name, index: documentable.documents.size),
|
||||
remote: true,
|
||||
id: "new_document_link",
|
||||
class: "button hollow" %>
|
||||
<% end %>
|
||||
|
||||
<div class="max-documents-notice callout warning text-center <%= "hide" unless max_documents_allowed?(documentable) %>">
|
||||
<%= t "documents.max_documents_allowed_reached_html" %>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
31
app/views/documents/_nested_fields.html.erb
Normal file
@@ -0,0 +1,31 @@
|
||||
<div id="<%= document_nested_field_wrapper_id(index) %>" class="document">
|
||||
<%= hidden_field_tag :id,
|
||||
document.id,
|
||||
name: document_nested_field_name(document, index, :id),
|
||||
id: document_nested_field_id(document, index, :id) if document.persisted? %>
|
||||
<%= hidden_field_tag :user_id,
|
||||
current_user.id,
|
||||
name: document_nested_field_name(document, index, :user_id),
|
||||
id: document_nested_field_id(document, index, :user_id) %>
|
||||
<%= hidden_field_tag :cached_attachment,
|
||||
document.cached_attachment,
|
||||
name: document_nested_field_name(document, index, :cached_attachment),
|
||||
id: document_nested_field_id(document, index, :cached_attachment) %>
|
||||
|
||||
<%= label_tag :title, t("activerecord.attributes.document.title") %>
|
||||
<%= text_field_tag :title,
|
||||
document.title,
|
||||
name: document_nested_field_name(document, index, :title),
|
||||
id: document_nested_field_id(document, index, :title),
|
||||
class: "document-title" %>
|
||||
<% if document.errors[:title].any? %>
|
||||
<small class="error"><%= document.errors[:title].join(", ") %></small>
|
||||
<% end %>
|
||||
|
||||
<%= render_attachment(document, index) %>
|
||||
|
||||
<%= render_destroy_document_link(document, index) %>
|
||||
<p class="file-name"><%= document_attachment_file_name(document) %></p>
|
||||
<div class="progress-bar-placeholder"><div class="loading-bar"></div></div>
|
||||
<hr>
|
||||
</div>
|
||||
50
app/views/documents/_plain_fields.html.erb
Normal file
@@ -0,0 +1,50 @@
|
||||
<div id="plain_document_fields" class="document">
|
||||
|
||||
<div class="small-12 column">
|
||||
<%= label_tag :document_title, t("activerecord.attributes.document.title") %>
|
||||
<%= text_field_tag :document_title, document.title, name: "document[title]", class: "document-title" %>
|
||||
<% if document.errors.has_key?(:title) %>
|
||||
<small class="error"><%= document.errors[:title].join(", ") %></small>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 column">
|
||||
<%= hidden_field_tag :cached_attachment, document.cached_attachment, name: "document[cached_attachment]" %>
|
||||
<%= file_field_tag :attachment,
|
||||
accept: accepted_content_types_extensions(document.documentable.class),
|
||||
label: false,
|
||||
class: 'document_ajax_attachment',
|
||||
data: {
|
||||
url: upload_documents_url(documentable_type: document.documentable_type, documentable_id: document.documentable_id),
|
||||
cached_attachment_input_field: "document_cached_attachment",
|
||||
multiple: false,
|
||||
nested_document: false
|
||||
},
|
||||
id: "document_attachment",
|
||||
name: "document[attachment]" %>
|
||||
|
||||
<% if document.cached_attachment.blank? %>
|
||||
<%= label_tag :document_attachment, t("documents.form.attachment_label"), class: 'button hollow' %>
|
||||
<% else %>
|
||||
<%= link_to t('documents.form.delete_button'),
|
||||
destroy_upload_documents_path(path: document.cached_attachment,
|
||||
nested_document: false,
|
||||
documentable_type: document.documentable_type,
|
||||
documentable_id: document.documentable_id),
|
||||
method: :delete,
|
||||
remote: true,
|
||||
class: "delete float-right" %>
|
||||
<% end %>
|
||||
|
||||
<% if document.errors.has_key?(:attachment) %>
|
||||
<div class="small-12 column source-option-file">
|
||||
<div class="attachment-errors">
|
||||
<small class="error"><%= errors_on_attachment(document) %></small>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<p class="file-name"><%= document_attachment_file_name(document) %></p>
|
||||
<div class="progress-bar-placeholder"><div class="loading-bar"></div></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
17
app/views/documents/destroy.js.erb
Normal file
@@ -0,0 +1,17 @@
|
||||
<% if params[:nested_document] == "true" %>
|
||||
|
||||
App.Documentable.destroyNestedDocument("<%= document_nested_field_wrapper_id(params[:index]) %>", "<%= j render('layouts/flash') %>")
|
||||
<% new_document_link = link_to t("documents.form.add_new_document"),
|
||||
new_nested_documents_path(documentable_type: @document.documentable_type, index: params[:index]),
|
||||
remote: true,
|
||||
id: "new_document_link",
|
||||
class: "button hollow" %>
|
||||
App.Documentable.updateNewDocumentButton("<%= j new_document_link %>")
|
||||
|
||||
<% else %>
|
||||
|
||||
App.Documentable.replacePlainDocument("plain_document_fields",
|
||||
"<%= j render('layouts/flash') %>",
|
||||
"<%= j render('plain_fields', document: @document) %>")
|
||||
|
||||
<% end %>
|
||||
27
app/views/documents/new.html.erb
Normal file
@@ -0,0 +1,27 @@
|
||||
<div class="document-form <%= documentable_class(@document.documentable) %> row">
|
||||
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= back_link_to params[:from] %>
|
||||
<h1><%= t("documents.new.title") %></h1>
|
||||
<%= render "documents/form", form_url: documents_url %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-3 column">
|
||||
<span class="icon-documents float-right"></span>
|
||||
<h2><%= t("documents.recommendations_title") %></h2>
|
||||
<ul class="recommendations">
|
||||
<li>
|
||||
<%= t "documents.recommendation_one_html",
|
||||
max_documents_allowed: max_documents_allowed(@document.documentable) %>
|
||||
</li>
|
||||
<li>
|
||||
<%= t "documents.recommendation_two_html",
|
||||
accepted_content_types: humanized_accepted_content_types(@document.documentable) %>
|
||||
</li>
|
||||
<li>
|
||||
<%= t "documents.recommendation_three_html",
|
||||
max_file_size: max_file_size(@document.documentable) %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
9
app/views/documents/new_nested.js.erb
Normal file
@@ -0,0 +1,9 @@
|
||||
<%
|
||||
new_document_link = link_to t("documents.form.add_new_document"),
|
||||
new_nested_documents_path(documentable_type: params[:documentable_type], index: params[:index].to_i + 1),
|
||||
remote: true,
|
||||
id: "new_document_link",
|
||||
class: "button hollow"
|
||||
%>
|
||||
App.Documentable.new("<%= j render('documents/nested_fields', document: @document, index: params[:index]) %>")
|
||||
App.Documentable.updateNewDocumentButton("<%= j new_document_link %>")
|
||||
12
app/views/documents/upload.js.erb
Normal file
@@ -0,0 +1,12 @@
|
||||
<% if params[:nested_document] == "true" %>
|
||||
|
||||
App.Documentable.uploadNestedDocument("<%= document_nested_field_wrapper_id(params[:index]) %>",
|
||||
"<%= j render('documents/nested_fields', document: @document, index: params[:index]) %>",
|
||||
<%= @document.cached_attachment.present? %>)
|
||||
<% else %>
|
||||
|
||||
App.Documentable.uploadPlainDocument("plain_document_fields",
|
||||
"<%= j render('documents/plain_fields', document: @document) %>",
|
||||
<%= @document.cached_attachment.present? %>)
|
||||
|
||||
<% end %>
|
||||
@@ -18,7 +18,7 @@
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t('legislation.shared.share') %></h2>
|
||||
<%= render '/legislation/shared/share_buttons',
|
||||
<%= render '/shared/social_share',
|
||||
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)
|
||||
%>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t('legislation.shared.share') %></h2>
|
||||
<%= render '/legislation/shared/share_buttons',
|
||||
<%= render '/shared/social_share',
|
||||
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)
|
||||
%>
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
<%= 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>
|
||||
<%= render "shared/section_header", i18n_namespace: "legislation.processes.index.section_header", image: "legislation_processes" %>
|
||||
|
||||
<div class="row">
|
||||
<div id="legislation" class="legislation-list small-12 medium-9 column">
|
||||
|
||||
<%= render 'shared/filter_subnav', i18n_namespace: "legislation.processes.index" %>
|
||||
|
||||
<div id="legislation-list">
|
||||
<% if @processes.any? %>
|
||||
<%= render @processes %>
|
||||
@@ -17,6 +18,16 @@
|
||||
<%= t(".no_#{@current_filter}_processes") %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div id="section_help" class="margin" data-magellan-target="section_help">
|
||||
<p class="lead">
|
||||
<strong><%= t("legislation.processes.index.section_footer.title") %></strong>
|
||||
</p>
|
||||
<p><%= t("legislation.processes.index.section_footer.help_text_1") %></p>
|
||||
<p><%= t("legislation.processes.index.section_footer.help_text_2",
|
||||
org: setting['org_name']) %></p>
|
||||
<p><%= t("legislation.processes.index.section_footer.help_text_3") %></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div id="social-share" class="sidebar-divider"></div>
|
||||
<h3><%= t('.share') %></h3>
|
||||
<%= render '/legislation/shared/share_buttons', title: @question.title, url: legislation_process_question_url(@question.process, @question) %>
|
||||
<%= render '/shared/social_share', title: @question.title, url: legislation_process_question_url(@question.process, @question) %>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<div class="social-share-full">
|
||||
<%= social_share_button_tag("#{title} #{setting['twitter_hashtag']}") %>
|
||||
<% if browser.device.mobile? %>
|
||||
<a href="whatsapp://send?text=<%= title %> <%= url %>" data-action="share/whatsapp/share">
|
||||
<span class="icon-whatsapp whatsapp"></span>
|
||||
<span class="show-for-sr"><%= t("social.whatsapp") %></span>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -1,23 +1,14 @@
|
||||
<% provide :title do %><%= t("polls.index.title") %><% end %>
|
||||
<% content_for :wrapper_class, "light" %>
|
||||
<% content_for :canonical do %>
|
||||
<%= render "shared/canonical", href: polls_url %>
|
||||
<% end %>
|
||||
|
||||
<div class="expanded no-margin-top dark-heading">
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column padding">
|
||||
<h1><%= t("polls.index.title") %></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "shared/section_header", i18n_namespace: "polls.index.section_header", image: "polls" %>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-3 column">
|
||||
<%= render 'shared/filter_subnav_vertical', i18n_namespace: "polls.index" %>
|
||||
</div>
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= render 'shared/filter_subnav', i18n_namespace: "polls.index" %>
|
||||
|
||||
<div class="small-12 medium-9 column margin-top">
|
||||
<% polls_by_geozone_restriction = @polls.group_by(&:geozone_restricted) %>
|
||||
|
||||
<% if polls_by_geozone_restriction[false].present? %>
|
||||
@@ -31,5 +22,15 @@
|
||||
<% end %>
|
||||
|
||||
<%= paginate @polls %>
|
||||
|
||||
<div id="section_help" class="margin" data-magellan-target="section_help">
|
||||
<p class="lead">
|
||||
<strong><%= t("polls.index.section_footer.title") %></strong>
|
||||
</p>
|
||||
<p><%= t("polls.index.section_footer.help_text_1") %></p>
|
||||
<p><%= t("polls.index.section_footer.help_text_2",
|
||||
org: link_to(setting['org_name'], new_user_registration_path)).html_safe %></p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<% provide :title do %><%= @poll.name %><% end %>
|
||||
<% content_for :wrapper_class, "light" %>
|
||||
|
||||
<div class="polls-show">
|
||||
<div class="expanded no-margin-top dark-heading polls-show-header">
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
</h3>
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="tabs-title">
|
||||
<%= link_to "#tab-documents" do %>
|
||||
<h3>
|
||||
<%= t("documents.tab") %>
|
||||
(<%= @proposal.documents.count %>)
|
||||
</h3>
|
||||
<% end %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
<a id="flag-expand-proposal-<%= proposal.id %>" data-toggle="flag-drop-proposal-<%= proposal.id %>" title="<%= t('shared.flag') %>">
|
||||
<span class="icon-flag flag-disable"></span>
|
||||
</a>
|
||||
<div class="dropdown-pane" id="flag-drop-proposal-<%= proposal.id %>" data-dropdown data-auto-focus="true">
|
||||
<span class="dropdown-pane" id="flag-drop-proposal-<%= proposal.id %>" data-dropdown data-auto-focus="true">
|
||||
<%= link_to t('shared.flag'), flag_proposal_path(proposal), method: :put, remote: true, id: "flag-proposal-#{ proposal.id }" %>
|
||||
</div>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% if show_unflag_action? proposal %>
|
||||
<a id="unflag-expand-proposal-<%= proposal.id %>" data-toggle="unflag-drop-proposal-<%= proposal.id %>" title="<%= t('shared.unflag') %>">
|
||||
<span class="icon-flag flag-active"></span>
|
||||
</a>
|
||||
<div class="dropdown-pane" id="unflag-drop-proposal-<%= proposal.id %>" data-dropdown data-auto-focus="true">
|
||||
<span class="dropdown-pane" id="unflag-drop-proposal-<%= proposal.id %>" data-dropdown data-auto-focus="true">
|
||||
<%= link_to t('shared.unflag'), unflag_proposal_path(proposal), method: :put, remote: true, id: "unflag-proposal-#{ proposal.id }" %>
|
||||
</div>
|
||||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
<%= f.cktext_area :description, maxlength: Proposal.description_max_length, ckeditor: { language: I18n.locale }, label: false %>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="small-12 column">
|
||||
<%= f.label :video_url, t("proposals.form.proposal_video_url") %>
|
||||
<p class="help-text" id="video-url-help-text"><%= t("proposals.form.proposal_video_url_note") %></p>
|
||||
@@ -47,6 +46,10 @@
|
||||
<%= f.text_field :external_url, placeholder: t("proposals.form.proposal_external_url"), label: false %>
|
||||
</div>
|
||||
|
||||
<div class="documents small-12 column" data-max-documents="<%= Proposal.max_documents_allowed %>">
|
||||
<%= render 'documents/nested_documents', documentable: @proposal %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.label :geozone_id, t("proposals.form.geozone") %>
|
||||
<%= f.select :geozone_id, geozone_select_options, {include_blank: t("geozones.none"), label: false} %>
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
<% end %>
|
||||
|
||||
<main>
|
||||
<h1 class="show-for-sr"><%= t("shared.outline.proposals") %></h1>
|
||||
|
||||
<% if @search_terms || @advanced_search_terms || @tag_filter || params[:retired].present? %>
|
||||
<div class="highlight no-margin-top padding margin-bottom">
|
||||
<div class="row">
|
||||
@@ -35,6 +33,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "shared/section_header", i18n_namespace: "proposals.index.section_header", image: "proposals" %>
|
||||
<% end %>
|
||||
|
||||
<div class="row">
|
||||
@@ -61,13 +61,27 @@
|
||||
|
||||
<%= render 'shared/order_links', i18n_namespace: "proposals.index" %>
|
||||
|
||||
<div class="show-for-small-only">
|
||||
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button expanded' %>
|
||||
</div>
|
||||
<% if @proposals.any? %>
|
||||
<div class="show-for-small-only">
|
||||
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button expanded' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div id="proposals-list">
|
||||
<%= render partial: 'proposals/proposal', collection: @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
|
||||
<% unless @search_terms || @advanced_search_terms || @tag_filter %>
|
||||
<div id="section_help" class="margin" data-magellan-target="section_help">
|
||||
<p class="lead">
|
||||
<strong><%= t("proposals.index.section_footer.title") %></strong>
|
||||
</p>
|
||||
<p><%= t("proposals.index.section_footer.help_text_1") %></p>
|
||||
<p><%= t("proposals.index.section_footer.help_text_2",
|
||||
org: link_to(setting['org_name'], new_user_registration_path)).html_safe %></p>
|
||||
<p><%= t("proposals.index.section_footer.help_text_3") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= back_link_to %>
|
||||
|
||||
<% if can?(:create, @document) && @proposal.documents.size < Proposal.max_documents_allowed %>
|
||||
<%= link_to t("documents.upload_document"),
|
||||
new_document_path(documentable_id: @proposal, documentable_type: @proposal.class.name, from: request.url),
|
||||
class: 'button hollow float-right' %>
|
||||
<% end %>
|
||||
|
||||
<% if author_of?(@proposal, current_user) %>
|
||||
<%= link_to t("proposals.show.send_notification"), new_proposal_notification_path(proposal_id: @proposal.id),
|
||||
class: 'button hollow float-right' %>
|
||||
@@ -77,14 +83,23 @@
|
||||
|
||||
<% if @proposal.external_url.present? %>
|
||||
<div class="document-link">
|
||||
<%= text_with_links @proposal.external_url %>
|
||||
<p>
|
||||
<span class="icon-document"></span>
|
||||
<strong><%= t('proposals.show.title_external_url') %></strong>
|
||||
</p>
|
||||
<%= text_with_links @proposal.external_url %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @proposal.video_url.present? %>
|
||||
<div class="video-link">
|
||||
<p>
|
||||
<span class="icon-video"></span>
|
||||
<strong><%= t('proposals.show.title_video_url') %></strong>
|
||||
</p>
|
||||
<%= text_with_links @proposal.video_url %>
|
||||
</div>
|
||||
|
||||
<% end %>
|
||||
|
||||
<h4><%= @proposal.question %></h4>
|
||||
@@ -156,4 +171,10 @@
|
||||
<div class="tabs-panel is-active" id="tab-comments">
|
||||
<%= render "proposals/comments" %>
|
||||
</div>
|
||||
|
||||
<div class="tabs-panel" id="tab-documents">
|
||||
<%= render 'documents/documents',
|
||||
documents: @proposal.documents,
|
||||
max_documents_allowed: Proposal.max_documents_allowed %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<% if current_user %>
|
||||
<% if show_admin_menu? %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.administration_menu"), "#", rel: "nofollow" %>
|
||||
<ul class="menu">
|
||||
|
||||
10
app/views/shared/_section_header.html.erb
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="highlight jumbo">
|
||||
<div class="row">
|
||||
<div class="small-12 medium-9 column" data-magellan>
|
||||
<%= image_tag "help/help_icon_#{image}.png", alt: t("#{i18n_namespace}.icon_alt"), class: "align-top" %>
|
||||
<h1 class="inline-block"><%= t("#{i18n_namespace}.title") %></h1>
|
||||
<p class="lead"><%= t("#{i18n_namespace}.description") %></p>
|
||||
<%= link_to t("#{i18n_namespace}.help"), "#section_help", class: "help-link" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,7 +4,7 @@
|
||||
<% end %>
|
||||
<div class="social-share-full">
|
||||
<%= social_share_button_tag("#{title} #{setting['twitter_hashtag']}") %>
|
||||
<a href="whatsapp://send?text=<%= title.gsub(/\s/, '%20') %> <%= url %>"
|
||||
<a href="whatsapp://send?text=<%= CGI.escape(title) %> <%= url %>"
|
||||
class="show-for-small-only" data-action="share/whatsapp/share">
|
||||
<span class="icon-whatsapp whatsapp"></span>
|
||||
<span class="show-for-sr"><%= t("social.whatsapp") %></span>
|
||||
|
||||
@@ -7,28 +7,34 @@
|
||||
|
||||
<% if proposal.retired? %>
|
||||
|
||||
<td class="text-center">
|
||||
<td class="text-center" colspan="2">
|
||||
<span class="label alert"><%= t('users.proposals.retired') %></span>
|
||||
</td>
|
||||
|
||||
<% elsif author?(proposal) %>
|
||||
|
||||
<td class="text-center">
|
||||
<td>
|
||||
<%= link_to t("users.proposals.send_notification"),
|
||||
new_proposal_notification_path(proposal_id: proposal.id),
|
||||
class: 'button hollow' %>
|
||||
class: 'button hollow expanded' %>
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
<td>
|
||||
<% if proposal.retired? %>
|
||||
<span class="label alert"><%= t('users.proposals.retired') %></span>
|
||||
<% else %>
|
||||
<%= link_to t('users.proposals.retire'),
|
||||
retire_form_proposal_path(proposal),
|
||||
class: 'button hollow alert' %>
|
||||
class: 'button hollow alert expanded' %>
|
||||
<% end %>
|
||||
</td>
|
||||
|
||||
<% else %>
|
||||
|
||||
<td class="text-center" colspan="2">
|
||||
<%= link_to t('users.proposals.see'), proposal, class: 'button hollow' %>
|
||||
</td>
|
||||
|
||||
<% end %>
|
||||
|
||||
</tr>
|
||||
|
||||
@@ -2,45 +2,50 @@
|
||||
<%= render "shared/canonical", href: root_url %>
|
||||
<% end %>
|
||||
|
||||
<div class="expanded highlight padding no-margin-top">
|
||||
<div class="jumbo highlight">
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<div class="small-12 medium-9 small-centered column text-center">
|
||||
<h1><%= t("layouts.header.open_city_title") %></h1>
|
||||
<p>
|
||||
<%= t("layouts.header.open_city_slogan_html") %>
|
||||
<%= link_to t("layouts.header.more_info"), more_info_path %>
|
||||
<p class="lead">
|
||||
<%= t("layouts.header.open_city_slogan_html") %>
|
||||
</p>
|
||||
<div class="small-12 medium-6">
|
||||
<%= link_to t("layouts.header.see_all"), proposals_path, class: "button see-more expanded" %>
|
||||
<div class="small-12 medium-6 large-4 small-centered">
|
||||
<%= link_to t("layouts.header.more_info"), more_info_path, class: "button expanded large" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hide-for-small-only small-12 medium-5 column text-center">
|
||||
<%= image_tag(image_path_for("icon_home.png"), size: "330x240", alt:"") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% cache [locale_and_user_status, @featured_debates, @featured_proposals, 'featured'] do %>
|
||||
<main>
|
||||
<div class="row text-center margin">
|
||||
<div class="small-12 medium-3 column">
|
||||
<h2><%= t("welcome.debates.title") %></h2>
|
||||
<p><%= t("welcome.debates.description") %></p>
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<p>
|
||||
<span class="lead"><strong><%= t("welcome.debates.title") %></strong></span><br>
|
||||
<%= t("welcome.debates.description") %>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div class="small-12 medium-3 column">
|
||||
<h2><%= t("welcome.proposal.title") %></h2>
|
||||
<p><%= t("welcome.proposal.description") %></p>
|
||||
<div class="small-12 medium-6 column">
|
||||
<p>
|
||||
<span class="lead"><strong><%= t("welcome.proposal.title") %></strong></span><br>
|
||||
<%= t("welcome.proposal.description") %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-3 column">
|
||||
<h2><%= t("welcome.decide.title") %></h2>
|
||||
<p><%= t("welcome.decide.description") %></p>
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 medium-6 column">
|
||||
<p>
|
||||
<span class="lead"><strong><%= t("welcome.decide.title") %></strong></span><br>
|
||||
<%= t("welcome.decide.description") %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="small-12 medium-3 column">
|
||||
<h2><%= t("welcome.do.title") %></h2>
|
||||
<p><%= t("welcome.do.description") %></p>
|
||||
<div class="small-12 medium-6 column">
|
||||
<p>
|
||||
<span class="lead"><strong><%= t("welcome.do.title") %></strong></span><br>
|
||||
<%= t("welcome.do.description") %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -35,7 +35,7 @@ module Consul
|
||||
config.time_zone = 'Madrid'
|
||||
config.active_job.queue_adapter = :delayed_job
|
||||
|
||||
# Consul specific custom overrides
|
||||
# CONSUL specific custom overrides
|
||||
# Read more on documentation:
|
||||
# * English: https://github.com/consul/consul/blob/master/CUSTOMIZE_EN.md
|
||||
# * Spanish: https://github.com/consul/consul/blob/master/CUSTOMIZE_ES.md
|
||||
|
||||
@@ -46,7 +46,7 @@ Rails.application.configure do
|
||||
|
||||
# Use the lowest log level to ensure availability of diagnostic information
|
||||
# when problems arise.
|
||||
config.log_level = :debug
|
||||
config.log_level = :warn
|
||||
|
||||
# Prepend all log lines with the following tags.
|
||||
# config.log_tags = [ :subdomain, :uuid ]
|
||||
|
||||
@@ -37,6 +37,7 @@ data:
|
||||
- config/locales/%{locale}/officing.yml
|
||||
- config/locales/%{locale}/budgets.yml
|
||||
- config/locales/%{locale}/legislation.yml
|
||||
- config/locales/%{locale}/documents.yml
|
||||
|
||||
# Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
|
||||
# `i18n-tasks normalize -p` will force move the keys according to these rules
|
||||
@@ -114,6 +115,7 @@ ignore_missing:
|
||||
ignore_unused:
|
||||
- 'budgets.phase.*'
|
||||
- 'budgets.investments.index.orders.*'
|
||||
- 'budgets.index.section_header.*'
|
||||
- 'activerecord.*'
|
||||
- 'activemodel.*'
|
||||
- 'unauthorized.*'
|
||||
@@ -148,16 +150,20 @@ ignore_unused:
|
||||
- 'valuation.budget_investments.index.filter*'
|
||||
- 'users.show.filters.*'
|
||||
- 'polls.index.filters.*'
|
||||
- 'polls.index.section_header.*'
|
||||
- 'debates.index.select_order'
|
||||
- 'debates.index.orders.*'
|
||||
- 'debates.index.section_header.*'
|
||||
- 'proposals.index.select_order'
|
||||
- 'proposals.index.orders.*'
|
||||
- 'proposals.index.section_header.*'
|
||||
- 'spending_proposals.index.search_form.*'
|
||||
- '*.index.search_form.*'
|
||||
- 'notifications.index.comments_on*'
|
||||
- 'notifications.index.replies_to*'
|
||||
- 'notifications.index.proposal_notification*'
|
||||
- 'legislation.processes.index.filter*'
|
||||
- 'legislation.processes.index.section_header.*'
|
||||
- 'helpers.page_entries_info.*' # kaminari
|
||||
- 'views.pagination.*' # kaminari
|
||||
- 'shared.suggest.*'
|
||||
|
||||
@@ -76,6 +76,9 @@ en:
|
||||
legislation/answers:
|
||||
one: "Answer"
|
||||
other: "Answers"
|
||||
documents:
|
||||
one: "Document"
|
||||
other: "Documents"
|
||||
attributes:
|
||||
budget:
|
||||
name: "Name"
|
||||
@@ -197,6 +200,9 @@ en:
|
||||
value: Value
|
||||
legislation/annotation:
|
||||
text: Comment
|
||||
document:
|
||||
title: Title
|
||||
attachment: Attachment
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
|
||||
@@ -879,7 +879,7 @@ en:
|
||||
content_blocks:
|
||||
form:
|
||||
content_blocks_information: Information about content blocks
|
||||
content_block_about: You can create HTML content blocks to be inserted in the header or the footer of your Consul.
|
||||
content_block_about: You can create HTML content blocks to be inserted in the header or the footer of your CONSUL.
|
||||
content_block_top_links_html: "<strong>Header blocks (top_links)</strong> are blocks of links that must have this format:"
|
||||
content_block_footer_html: "<strong>Footer blocks</strong> can have any format and can be used to insert Javascript, CSS or custom HTML."
|
||||
create:
|
||||
|
||||
@@ -38,6 +38,17 @@ en:
|
||||
finished: Finished budget
|
||||
index:
|
||||
title: Participatory budgets
|
||||
section_header:
|
||||
icon_alt: Participatory budgets icon
|
||||
title: Participatory budgets
|
||||
description: With the participatory budgets the citizens decide to which projects presented by the neighbors is destined a part of the municipal budget.
|
||||
help: Help about participatory budgets
|
||||
section_footer:
|
||||
title: Help about participatory budgets
|
||||
help_text_1: "Participatory budgets are processes in which citizens decide directly on what is spent part of the municipal budget. Any registered person over 16 years old can propose an investment project that is preselected in a phase of citizen supports."
|
||||
help_text_2: "The most voted projects are evaluated and passed to a final vote in which they decide the actions to be carried out by the City Council once the municipal budgets of the next year are approved."
|
||||
help_text_3: "The presentation of participatory budgeting projects takes place from January and over a period of one and a half months. To participate and propose proposals for the entire city and / or districts, you must sign up on %{org} and verify your account."
|
||||
help_text_4: "To get as many supports and votes as possible, choose a descriptive and understandable headline for your project. Then you have a space to develop the approach of your proposal. Provide all the data and explanations, and even documents and images, to help other participants to better understand what you are proposing."
|
||||
investments:
|
||||
form:
|
||||
tag_category_label: "Categories"
|
||||
|
||||
35
config/locales/en/documents.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
en:
|
||||
documents:
|
||||
tab: Documents
|
||||
no_documents: Don't have uploaded documents
|
||||
upload_document: Upload document
|
||||
max_documents_allowed_reached_html: You have reached the maximum number of documents allowed! <strong>You have to delete one before you can upload another.</strong>
|
||||
form:
|
||||
title: Documents
|
||||
attachment_label: Choose document
|
||||
submit_button: Upload document
|
||||
delete_button: Remove document
|
||||
note: "You can upload up to a maximum of %{max_documents_allowed} documents of following content types: %{accepted_content_types}, up to %{max_file_size} MB per file."
|
||||
add_new_document: Add new document
|
||||
new:
|
||||
title: Upload document
|
||||
recommendations_title: File upload tips
|
||||
recommendation_one_html: You can upload up to a <strong>maximum of %{max_documents_allowed} documents</strong>.
|
||||
recommendation_two_html: You can upload <strong>%{accepted_content_types}</strong> files.
|
||||
recommendation_three_html: You can upload files up to <strong>%{max_file_size} MB</strong>.
|
||||
|
||||
actions:
|
||||
create:
|
||||
notice: Document was created successfully.
|
||||
alert: Cannot create document. Check form errors and try again.
|
||||
destroy:
|
||||
notice: Document was deleted successfully.
|
||||
alert: Cannot destroy document.
|
||||
confirm: Are you sure you want to delete the document? This action cannot be undone!
|
||||
buttons:
|
||||
download_document: Dowload file
|
||||
destroy_document: Destroy
|
||||
errors:
|
||||
messages:
|
||||
in_between: must be in between %{min} and %{max}
|
||||
wrong_content_type: content type %{content_type} does not match any of accepted content types %{accepted_content_types}
|
||||
@@ -118,6 +118,18 @@ en:
|
||||
select_order: Order by
|
||||
start_debate: Start a debate
|
||||
title: Debates
|
||||
section_header:
|
||||
icon_alt: Debates icon
|
||||
title: Debates
|
||||
description: Start a debate to share opinions with others about the topics you are concerned about.
|
||||
help: Help about debates
|
||||
section_footer:
|
||||
title: Help about debates
|
||||
help_text_1: "The space for citizen debates is aimed at anyone who can expose issues of their concern and those who want to share opinions with other people."
|
||||
help_text_2: 'To open a debate you need to sign up on %{org}. Users can also comment on open debates and rate them with the "I agree" or "I disagree" buttons found in each of them.'
|
||||
help_text_3: "Keep in mind that a debate does not start any specific action. If you want to make a %{proposal} for the city or raise a investment project of %{budget} when the phase is open, go to the corresponding section."
|
||||
proposals_link: proposal
|
||||
budget_link: participatory budgeting
|
||||
new:
|
||||
form:
|
||||
submit_button: Start a debate
|
||||
@@ -165,6 +177,7 @@ en:
|
||||
user: Account
|
||||
verification/sms: phone
|
||||
signature_sheet: Signature sheet
|
||||
document: Document
|
||||
geozones:
|
||||
none: All city
|
||||
all: All scopes
|
||||
@@ -177,10 +190,10 @@ en:
|
||||
footer:
|
||||
accessibility: Accessibility
|
||||
conditions: Terms and conditions of use
|
||||
consul: Consul application
|
||||
consul: CONSUL application
|
||||
consul_url: https://github.com/consul/consul
|
||||
contact_us: For technical assistance enters
|
||||
copyright: Consul, %{year}
|
||||
copyright: CONSUL, %{year}
|
||||
description: This portal uses the %{consul} which is %{open_source}.
|
||||
faq: technical assistance
|
||||
open_data_text: Every detail about the City Council is yours to access.
|
||||
@@ -205,7 +218,7 @@ en:
|
||||
external_link_transparency: Transparency
|
||||
external_link_transparency_url: https://transparency.consul
|
||||
locale: 'Language:'
|
||||
logo: Consul logo
|
||||
logo: CONSUL logo
|
||||
management: Management
|
||||
moderation: Moderation
|
||||
valuation: Valuation
|
||||
@@ -220,11 +233,10 @@ en:
|
||||
no_notifications: "You don't have new notifications"
|
||||
open: open
|
||||
open_city_slogan_html: There are cities that are governed directly by their inhabitants, who <b>discuss</b> the topics they are concerned about, <b>propose</b> ideas to improve their lives and <b>decide</b> among themselves which ones will be carried out.
|
||||
open_city_title: Love the city, and it will become a city you love.
|
||||
open_city_title: Love the city, and it will become a city you love
|
||||
open_gov: Open government
|
||||
proposals: Proposals
|
||||
poll_questions: Voting
|
||||
see_all: See proposals
|
||||
budgets: Participatory budgeting
|
||||
spending_proposals: Spending Proposals
|
||||
admin:
|
||||
@@ -351,6 +363,16 @@ en:
|
||||
title: Proposals
|
||||
top: Top weekly
|
||||
top_link_proposals: The most supported proposals by category
|
||||
section_header:
|
||||
icon_alt: Proposals icon
|
||||
title: Proposals
|
||||
description: Make a citizen proposal. If it gets enough supports it will go to voting phase, so you can get all the citizens to decide how they want their city to be.
|
||||
help: Help about proposals
|
||||
section_footer:
|
||||
title: Help about proposals
|
||||
help_text_1: "The citizen proposals are an opportunity for neighbours and collectives to decide directly how they want to shape their city. Any person can make a proposal about a topic or concern of their interest, for the City Council to make it, after it gets enough supports to be put to a citizens vote."
|
||||
help_text_2: "To create a proposal, you must sign up on %{org}. The proposals that get the support of 1% of the users in the web, goes to voting phase. To support proposals it is necessary to have a verified account."
|
||||
help_text_3: "A citizen vote is celebrated when the proposals get the necessary supports. Once celebrated, if there are more people in favor than against, the City Council assumes the proposal and carries it out."
|
||||
new:
|
||||
form:
|
||||
submit_button: Create proposal
|
||||
@@ -406,6 +428,8 @@ en:
|
||||
send_notification: Send notification
|
||||
no_notifications: "This proposal has any notifications."
|
||||
embed_video_title: "Video on %{proposal}"
|
||||
title_external_url: "Additional documentation"
|
||||
title_video_url: "External video"
|
||||
update:
|
||||
form:
|
||||
submit_button: Save changes
|
||||
@@ -431,6 +455,15 @@ en:
|
||||
cant_answer_not_logged_in: "You must sign in or sign up to participate"
|
||||
cant_answer_verify: "You must verify your account in order to answer"
|
||||
already_answer: "You already have participated in this poll"
|
||||
section_header:
|
||||
icon_alt: Voting icon
|
||||
title: Voting
|
||||
description: Sign up to vote on citizen proposals and questions the City Council ask to the neighbors. Make municipal decisions directly.
|
||||
help: Help about voting
|
||||
section_footer:
|
||||
title: Help about voting
|
||||
help_text_1: "Voting takes place when a citizen proposal supports reaches 1% of the census with voting rights. Voting can also include questions that the City Council ask to the citizens decision."
|
||||
help_text_2: "To participate in the next vote you have to sign up on %{org} and verify your account. All registered voters in the city over 16 years old can vote. The results of all votes are binding on the government."
|
||||
show:
|
||||
dates_title: "Participation dates"
|
||||
cant_answer_not_logged_in: "You must %{signin} or %{signup} to participate."
|
||||
@@ -554,8 +587,6 @@ en:
|
||||
unfollow: "Unfollow"
|
||||
unfollow_entity: "Unfollow %{entity}"
|
||||
outline:
|
||||
debates: Debates
|
||||
proposals: Proposals
|
||||
budget: Participatory budget
|
||||
searcher: Searcher
|
||||
go_to_page: "Go to page of "
|
||||
@@ -674,7 +705,8 @@ en:
|
||||
proposals:
|
||||
send_notification: "Send notification"
|
||||
retire: "Retire"
|
||||
retired: "Retired"
|
||||
retired: "Retired proposal"
|
||||
see: "See proposal"
|
||||
votes:
|
||||
agree: I agree
|
||||
anonymous: Too many anonymous votes to admit vote %{verify_account}.
|
||||
|
||||
@@ -64,6 +64,16 @@ en:
|
||||
no_open_processes: There aren't open processes
|
||||
no_next_processes: There aren't planned processes
|
||||
no_past_processes: There aren't past processes
|
||||
section_header:
|
||||
icon_alt: Legislation processes icon
|
||||
title: Legislation processes
|
||||
description: Participate in the debates and processes prior to the approval of a ordinance or a municipal action. Your opinion will be consider by the City Council.
|
||||
help: Help about legislation processes
|
||||
section_footer:
|
||||
title: Help about legislation processes
|
||||
help_text_1: "In participatory processes, the City Council offers to its citizens the opportunity to participate in the drafting and modification of regulations, affecting the city and to be able to give their opinion on certain actions that it plans to carry out."
|
||||
help_text_2: "People registered in %{org} can participate with contributions in the public consultation of new ordinances, regulations and guidelines, among others. Your comments are analyzed by the corresponding area and considered for the final drafting of the ordinances."
|
||||
help_text_3: "The City Council also opens processes to receive contributions and opinions on municipal actions."
|
||||
phase_not_open:
|
||||
not_open: This phase is not open yet
|
||||
phase_empty:
|
||||
|
||||
@@ -23,7 +23,7 @@ en:
|
||||
document_verifications:
|
||||
already_verified: This user account is already verified.
|
||||
has_no_account_html: In order to create an account, go to %{link} and click in <b>'Register'</b> in the upper-left part of the screen.
|
||||
link: Consul
|
||||
link: CONSUL
|
||||
in_census_has_following_permissions: 'This user can participate in the website with the following permissions:'
|
||||
not_in_census: This document is not registered.
|
||||
not_in_census_info: 'Citizens not in the Census can participate in the website with the following permissions:'
|
||||
|
||||
@@ -63,9 +63,9 @@ en:
|
||||
text: |-
|
||||
Use it in your local government or help us to improve it, it is free software.
|
||||
|
||||
This Open Government Portal use the [Consul app](https://github.com/ayuntamientomadrid 'consul github') that is free software, with [licence AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html 'AGPLv3 gnu' ), that means in simple words that anyone can use the code freely, copy it, see it in detail, modify it and redistribute it to the word with the modifications he wants (allowing others to do the same). Because we think culture is better and richer when it is released.
|
||||
This Open Government Portal use the [CONSUL app](https://github.com/ayuntamientomadrid 'consul github') that is free software, with [licence AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html 'AGPLv3 gnu' ), that means in simple words that anyone can use the code freely, copy it, see it in detail, modify it and redistribute it to the word with the modifications he wants (allowing others to do the same). Because we think culture is better and richer when it is released.
|
||||
|
||||
If you are a programmer, you can see the code and help us to improve it at [Consul app](https://github.com/ayuntamientomadrid 'consul github').
|
||||
If you are a programmer, you can see the code and help us to improve it at [CONSUL app](https://github.com/ayuntamientomadrid 'consul github').
|
||||
titles:
|
||||
how_to_use: Use it in your local government
|
||||
privacy: Privacy Policy
|
||||
|
||||
@@ -221,7 +221,8 @@ en:
|
||||
time:
|
||||
am: am
|
||||
formats:
|
||||
datetime: "%Y-%m-%d %H:%M:%S"
|
||||
default: "%a, %d %b %Y %H:%M:%S %z"
|
||||
long: "%B %d, %Y %H:%M"
|
||||
short: "%d %b %H:%M"
|
||||
pm: pm
|
||||
pm: pm
|
||||
|
||||
@@ -76,6 +76,9 @@ es:
|
||||
legislation/answers:
|
||||
one: "Respuesta"
|
||||
other: "Respuestas"
|
||||
documents:
|
||||
one: "Documento"
|
||||
other: "Documentos"
|
||||
attributes:
|
||||
budget:
|
||||
name: "Nombre"
|
||||
@@ -192,6 +195,9 @@ es:
|
||||
value: Valor
|
||||
legislation/annotation:
|
||||
text: Comentario
|
||||
document:
|
||||
title: Título
|
||||
attachment: Archivo adjunto
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
|
||||
@@ -879,7 +879,7 @@ es:
|
||||
content_blocks:
|
||||
form:
|
||||
content_blocks_information: Información sobre los bloques de texto
|
||||
content_block_about: Puedes crear bloques de HTML que se incrustarán en la cabecera o el pie de tu Cónsul.
|
||||
content_block_about: Puedes crear bloques de HTML que se incrustarán en la cabecera o el pie de tu CONSUL.
|
||||
content_block_top_links_html: "Los <strong>bloques de la cabecera (top_links)</strong> son bloques de enlaces que deben crearse con este formato:"
|
||||
content_block_footer_html: "Los <strong>bloques del pie (footer)</strong> pueden tener cualquier formato y se pueden utilizar para guardar huellas Javascript, contenido CSS o contenido HTML personalizado."
|
||||
create:
|
||||
|
||||
@@ -38,6 +38,17 @@ es:
|
||||
finished: Resultados
|
||||
index:
|
||||
title: Presupuestos participativos
|
||||
section_header:
|
||||
icon_alt: Icono de Presupuestos participativos
|
||||
title: Presupuestos participativos
|
||||
description: Con los presupuestos participativos la ciudadanía decide a qué proyectos presentados por los vecinos y vecinas va destinada una parte del presupuesto municipal.
|
||||
help: Ayuda sobre presupuestos participativos
|
||||
section_footer:
|
||||
title: Ayuda sobre presupuestos participativos
|
||||
help_text_1: "Los presupuestos participativos son unos procesos en los que la ciudadanía decide de forma directa en qué se gasta una parte del presupuesto municipal. Cualquier persona empadronada mayor de 16 años puede proponer un proyecto de gasto que se preselecciona en una fase de apoyos ciudadanos."
|
||||
help_text_2: "Los proyectos más votados se evalúan y pasan a una votación final en la que se deciden las actuaciones que llevará a cabo el Ayuntamiento una vez se aprueben los presupuestos municipales del año próximo."
|
||||
help_text_3: "La presentación de proyectos de presupuestos participativos se lleva a cabo desde enero y a lo largo de un periodo de mes y medio, aproximadamente. Para participar y plantear propuestas para toda la ciudad y/ los distritos hay que registrarse en %{org} y verificar la cuenta."
|
||||
help_text_4: "Para conseguir el mayor número de apoyos y votos posible, elige un titular descriptivo y comprensible de tu proyecto. Después tienes un espacio para desarrollar el planteamiento de tu propuesta. Aporta todos los datos y explicaciones, e incluso documentos e imágenes, para ayudar a otras personas participantes a entender mejor lo que planteas."
|
||||
investments:
|
||||
form:
|
||||
tags_instructions: "Etiqueta esta propuesta. Puedes elegir entre las categorías propuestas o introducir las que desees"
|
||||
|
||||
34
config/locales/es/documents.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
es:
|
||||
documents:
|
||||
tab: Documentos
|
||||
no_documents: No hay documentos subidos
|
||||
upload_document: Subir documento
|
||||
max_documents_allowed_reached_html: ¡Has alcanzado el número máximo de documentos permitidos! <strong>Tienes que eliminar uno antes de poder subir otro.</strong>
|
||||
form:
|
||||
title: Documentos
|
||||
attachment_label: Selecciona un documento
|
||||
submit_button: Subir documento
|
||||
delete_button: Eliminar documento
|
||||
note: "Puedes subir hasta un máximo de %{max_documents_allowed} documentos en los formatos: %{accepted_content_types}, y de hasta %{max_file_size} MB por archivo."
|
||||
add_new_document: Añadir nuevo documento
|
||||
new:
|
||||
title: Subir un documento
|
||||
recommendations_title: Consejos para subir archivos
|
||||
recommendation_one_html: Puedes subir hasta un máximo de <strong>%{max_documents_allowed} documentos</strong>
|
||||
recommendation_two_html: Sólo puedes subir <strong>archivos %{accepted_content_types}</strong>.
|
||||
recommendation_three_html: Puedes subir archivos de hasta <strong>%{max_file_size} MB</strong>
|
||||
actions:
|
||||
create:
|
||||
notice: "El documento se ha creado correctamente."
|
||||
alert: "El documento no se ha podido crear. Revise los errores del formulario."
|
||||
destroy:
|
||||
notice: "El documento se ha eliminado correctamente."
|
||||
alert: "El documento no se ha podido eliminar."
|
||||
confirm: "¿Está seguro de que desea eliminar el documento? Esta acción no se puede deshacer!"
|
||||
buttons:
|
||||
download_document: Descargar archivo
|
||||
destroy_document: Eliminar
|
||||
errors:
|
||||
messages:
|
||||
in_between: debe estar entre %{min} y %{max}
|
||||
wrong_content_type: El tipo de contenido %{content_type} del archivo no coincide con ninguno de los tipos de contenido aceptados %{accepted_content_types}
|
||||
@@ -118,6 +118,18 @@ es:
|
||||
select_order: Ordenar por
|
||||
start_debate: Empieza un debate
|
||||
title: Debates
|
||||
section_header:
|
||||
icon_alt: Icono de Debates
|
||||
title: Debates
|
||||
description: Inicia un debate para compartir puntos de vista con otras personas sobre los temas que te preocupan.
|
||||
help: Ayuda sobre los debates
|
||||
section_footer:
|
||||
title: Ayuda sobre los debates
|
||||
help_text_1: "El espacio de debates ciudadanos está dirigido a que cualquier persona pueda exponer temas que le preocupan y sobre los que quiera compartir puntos de vista con otras personas."
|
||||
help_text_2: 'Para abrir un debate es necesario registrarse en %{org}. Los usuarios ya registrados también pueden comentar los debates abiertos y valorarlos con los botones de "Estoy de acuerdo" o "No estoy de acuerdo" que se encuentran en cada uno de ellos.'
|
||||
help_text_3: "Ten en cuenta que un debate no activa ningún mecanismo de actuación concreto. Si quieres hacer una %{proposal} para la ciudad o plantear un proyecto de %{budget} cuando se abra la convocatoria, ve a la sección correspondiente."
|
||||
proposals_link: propuesta
|
||||
budget_link: presupuestos participativos
|
||||
new:
|
||||
form:
|
||||
submit_button: Empieza un debate
|
||||
@@ -165,6 +177,7 @@ es:
|
||||
user: la cuenta
|
||||
verification/sms: el teléfono
|
||||
signature_sheet: la hoja de firmas
|
||||
document: el documento
|
||||
geozones:
|
||||
none: Toda la ciudad
|
||||
all: Todos los ámbitos de actuación
|
||||
@@ -177,10 +190,10 @@ es:
|
||||
footer:
|
||||
accessibility: Accesibilidad
|
||||
conditions: Condiciones de uso
|
||||
consul: aplicación Consul
|
||||
consul: aplicación CONSUL
|
||||
consul_url: https://github.com/consul/consul
|
||||
contact_us: Para asistencia técnica entra en
|
||||
copyright: Consul, %{year}
|
||||
copyright: CONSUL, %{year}
|
||||
description: Este portal usa la %{consul} que es %{open_source}.
|
||||
faq: Asistencia técnica
|
||||
open_data_text: Todos los datos del Ayuntamiento son tuyos.
|
||||
@@ -205,7 +218,7 @@ es:
|
||||
external_link_transparency: Transparencia
|
||||
external_link_transparency_url: https://transparency.consul
|
||||
locale: 'Idioma:'
|
||||
logo: Consul logo
|
||||
logo: CONSUL logo
|
||||
management: Gestión
|
||||
moderation: Moderar
|
||||
valuation: Evaluación
|
||||
@@ -220,11 +233,10 @@ es:
|
||||
no_notifications: No tienes notificaciones nuevas
|
||||
open: abierto
|
||||
open_city_slogan_html: Existen ciudades gobernadas directamente por sus habitantes, que <strong>debaten</strong> sobre temas que les preocupan, <strong>proponen</strong> ideas para mejorar sus vidas y <strong>deciden</strong> entre todas y todos las que se llevan a cabo.
|
||||
open_city_title: La ciudad que quieres será la ciudad que quieras.
|
||||
open_city_title: La ciudad que quieres será la ciudad que quieras
|
||||
open_gov: Gobierno %{open}
|
||||
proposals: Propuestas
|
||||
poll_questions: Votaciones
|
||||
see_all: Ver propuestas
|
||||
budgets: Presupuestos participativos
|
||||
spending_proposals: "Propuestas de inversión"
|
||||
admin:
|
||||
@@ -351,6 +363,16 @@ es:
|
||||
title: Propuestas ciudadanas
|
||||
top: Top semanal
|
||||
top_link_proposals: Propuestas más apoyadas por categoría
|
||||
section_header:
|
||||
icon_alt: Icono de Propuestas
|
||||
title: Propuestas
|
||||
description: Haz una propuesta ciudadana. Si obtiene los apoyos suficientes y pasa a votación, puedes conseguir que todos los habitantes decidan cómo quieren que sea nuestra ciudad.
|
||||
help: Ayuda sobre las propuestas
|
||||
section_footer:
|
||||
title: Ayuda sobre las propuestas
|
||||
help_text_1: "Las propuestas ciudadanas son una oportunidad para que los vecinos y colectivos decidan directamente cómo quieren que sea su ciudad. Cualquier persona puede hacer una propuesta sobre un tema que le interese o preocupe para que el ayuntamiento la lleve a cabo, después de conseguir los apoyos suficientes y de someterse a votación ciudadana."
|
||||
help_text_2: "Para crear una propuesta hay que registrarse en %{org}. Las propuestas que consigan el apoyo del 1% de la gente en la web, pasan a votación. Para apoyar propuestas es necesario tener una cuenta verificada."
|
||||
help_text_3: "Se convoca una votación ciudadana cuando las propuestas consiguen los apoyos necesarios. Una vez celebrada, si hay más gente a favor que en contra, el Consistorio asume la propuesta y la lleva a cabo."
|
||||
new:
|
||||
form:
|
||||
submit_button: Crear propuesta
|
||||
@@ -406,6 +428,8 @@ es:
|
||||
share: Compartir
|
||||
no_notifications: "Esta propuesta no tiene notificaciones."
|
||||
embed_video_title: "Vídeo en %{proposal}"
|
||||
title_external_url: "Documentación adicional"
|
||||
title_video_url: "Vídeo externo"
|
||||
update:
|
||||
form:
|
||||
submit_button: Guardar cambios
|
||||
@@ -431,6 +455,15 @@ es:
|
||||
cant_answer_not_logged_in: "Necesitas iniciar sesión o registrarte para participar"
|
||||
cant_answer_verify: "Por favor verifica tu cuenta para poder responder"
|
||||
already_answer: "Ya has participado en esta votación"
|
||||
section_header:
|
||||
icon_alt: Icono de Votaciones
|
||||
title: Votaciones
|
||||
description: Regístrate para poder votar propuestas ciudadanas y las cuestiones que pregunta a sus vecinos el Ayuntamiento. Toma decisiones municipales de forma directa.
|
||||
help: Ayuda sobre las votaciones
|
||||
section_footer:
|
||||
title: Ayuda sobre las votaciones
|
||||
help_text_1: "Las votaciones se convocan cuando una propuesta ciudadana alcanza el 1% de apoyos del censo con derecho a voto. En las votaciones también se pueden incluir cuestiones que el Ayuntamiento somete a decisión directa de la ciudadanía."
|
||||
help_text_2: "Para participar en la próxima votación tienes que registrarte en %{org} y verificar tu cuenta. Pueden votar todas las personas empadronadas en la ciudad mayores de 16 años. Los resultados de todas las votaciones serán vinculantes para el gobierno."
|
||||
show:
|
||||
dates_title: "Fechas de participación"
|
||||
cant_answer_not_logged_in: "Necesitas %{signin} o %{signup} para participar."
|
||||
@@ -554,8 +587,6 @@ es:
|
||||
unfollow: Dejar de seguir
|
||||
unfollow_entity: "Dejar de seguir %{entity}"
|
||||
outline:
|
||||
debates: Debates
|
||||
proposals: Propuestas
|
||||
budget: Presupuestos participativos
|
||||
searcher: Buscador
|
||||
go_to_page: "Ir a la página de "
|
||||
@@ -674,7 +705,8 @@ es:
|
||||
proposals:
|
||||
send_notification: "Enviar notificación"
|
||||
retire: "Retirar"
|
||||
retired: "Retirada"
|
||||
retired: "Propuesta retirada"
|
||||
see: "Ver propuesta"
|
||||
votes:
|
||||
agree: Estoy de acuerdo
|
||||
anonymous: Demasiados votos anónimos, para poder votar %{verify_account}.
|
||||
|
||||
@@ -64,6 +64,16 @@ es:
|
||||
no_open_processes: No hay procesos activos
|
||||
no_next_processes: No hay procesos planeados
|
||||
no_past_processes: No hay procesos terminados
|
||||
section_header:
|
||||
icon_alt: Icono de Procesos legislativos
|
||||
title: Procesos legislativos
|
||||
description: Participa en los debates y procesos previos a la aprobación de una norma o de una actuación municipal. Tu opinión será tenida en cuenta por el Ayuntamiento.
|
||||
help: Ayuda sobre procesos legislativos
|
||||
section_footer:
|
||||
title: Ayuda sobre procesos legislativos
|
||||
help_text_1: "En los procesos participativos, el Ayuntamiento ofrece a la ciudadanía la oportunidad de participar en la elaboración y modificación de normativa que afecta a la ciudad y de dar su opinión sobre ciertas actuaciones que tiene previsto llevar a cabo."
|
||||
help_text_2: "Las personas registradas en %{org} pueden participar con aportaciones en la consulta pública de nuevas ordenanzas, reglamentos y directrices, entre otros. Sus comentarios son analizados por el área correspondiente y tenidos en cuenta de cara a la redacción final de las normas."
|
||||
help_text_3: "El Ayuntamiento también abre procesos para recibir aportaciones y opiniones sobre actuaciones municipales."
|
||||
phase_not_open:
|
||||
not_open: Esta fase del proceso todavía no está abierta
|
||||
phase_empty:
|
||||
|
||||
@@ -23,7 +23,7 @@ es:
|
||||
document_verifications:
|
||||
already_verified: Esta cuenta de usuario ya está verificada.
|
||||
has_no_account_html: Para crear un usuario entre en %{link} y haga clic en la opción <b>'Registrarse'</b> en la parte superior derecha de la pantalla.
|
||||
link: Consul
|
||||
link: CONSUL
|
||||
in_census_has_following_permissions: 'Este usuario puede participar en el Portal de Gobierno Abierto con las siguientes posibilidades:'
|
||||
not_in_census: Este documento no está registrado.
|
||||
not_in_census_info: 'Las personas no empadronadas pueden participar en el Portal de Gobierno Abierto con las siguientes posibilidades:'
|
||||
|
||||
@@ -63,9 +63,9 @@ es:
|
||||
text: |-
|
||||
Utilízalo en tu municipio libremente o ayúdanos a mejorarlo, es software libre.
|
||||
|
||||
Este Portal de Gobierno Abierto usa la [aplicación Consul](https://github.com/ayuntamientomadrid 'github consul') que es software libre, con [licencia AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html 'AGPLv3 gnu' ), esto significa en palabras sencillas, que cualquiera puede libremente usar el código, copiarlo, verlo en detalle, modificarlo, y redistribuirlo al mundo con las modificaciones que quiera (manteniendo el que otros puedan a su vez hacer lo mismo). Porque creemos que la cultura es mejor y más rica cuando se libera.
|
||||
Este Portal de Gobierno Abierto usa la [aplicación CONSUL](https://github.com/ayuntamientomadrid 'github consul') que es software libre, con [licencia AGPLv3](http://www.gnu.org/licenses/agpl-3.0.html 'AGPLv3 gnu' ), esto significa en palabras sencillas, que cualquiera puede libremente usar el código, copiarlo, verlo en detalle, modificarlo, y redistribuirlo al mundo con las modificaciones que quiera (manteniendo el que otros puedan a su vez hacer lo mismo). Porque creemos que la cultura es mejor y más rica cuando se libera.
|
||||
|
||||
Si eres programador, puedes ver el código y ayudarnos a mejorarlo en [aplicación Consul](https://github.com/ayuntamientomadrid 'github consul').
|
||||
Si eres programador, puedes ver el código y ayudarnos a mejorarlo en [aplicación CONSUL](https://github.com/ayuntamientomadrid 'github consul').
|
||||
titles:
|
||||
how_to_use: Utilízalo en tu municipio
|
||||
privacy: Política de Privacidad
|
||||
|
||||
@@ -14,7 +14,7 @@ common: &default_settings
|
||||
|
||||
# Your application name. Renaming here affects where data displays in New
|
||||
# Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications
|
||||
app_name: Consul
|
||||
app_name: CONSUL
|
||||
|
||||
# To disable the agent regardless of other settings, uncomment the following:
|
||||
# agent_enabled: false
|
||||
@@ -28,7 +28,7 @@ common: &default_settings
|
||||
# If your application has other named environments, configure them here.
|
||||
development:
|
||||
<<: *default_settings
|
||||
app_name: Consul (Development)
|
||||
app_name: CONSUL (Development)
|
||||
|
||||
# NOTE: There is substantial overhead when running in developer mode.
|
||||
# Do not use for production or load testing.
|
||||
@@ -41,7 +41,7 @@ test:
|
||||
|
||||
staging:
|
||||
<<: *default_settings
|
||||
app_name: Consul (Staging)
|
||||
app_name: CONSUL (Staging)
|
||||
|
||||
production:
|
||||
<<: *default_settings
|
||||
|
||||
@@ -95,6 +95,14 @@ Rails.application.routes.draw do
|
||||
|
||||
resources :follows, only: [:create, :destroy]
|
||||
|
||||
resources :documents, only: [:new, :create, :destroy] do
|
||||
collection do
|
||||
get :new_nested
|
||||
delete :destroy_upload
|
||||
post :upload
|
||||
end
|
||||
end
|
||||
|
||||
resources :stats, only: [:index]
|
||||
|
||||
resources :legacy_legislations, only: [:show], path: 'legislations'
|
||||
|
||||
@@ -18,13 +18,13 @@ Setting.create(key: 'comments_body_max_length', value: '1000')
|
||||
|
||||
Setting.create(key: 'twitter_handle', value: '@consul_dev')
|
||||
Setting.create(key: 'twitter_hashtag', value: '#consul_dev')
|
||||
Setting.create(key: 'facebook_handle', value: 'consul')
|
||||
Setting.create(key: 'youtube_handle', value: 'consul')
|
||||
Setting.create(key: 'telegram_handle', value: 'consul')
|
||||
Setting.create(key: 'instagram_handle', value: 'consul')
|
||||
Setting.create(key: 'facebook_handle', value: 'CONSUL')
|
||||
Setting.create(key: 'youtube_handle', value: 'CONSUL')
|
||||
Setting.create(key: 'telegram_handle', value: 'CONSUL')
|
||||
Setting.create(key: 'instagram_handle', value: 'CONSUL')
|
||||
Setting.create(key: 'blog_url', value: '/blog')
|
||||
Setting.create(key: 'url', value: 'http://localhost:3000')
|
||||
Setting.create(key: 'org_name', value: 'Consul')
|
||||
Setting.create(key: 'org_name', value: 'CONSUL')
|
||||
Setting.create(key: 'place_name', value: 'City')
|
||||
Setting.create(key: 'feature.debates', value: "true")
|
||||
Setting.create(key: 'feature.polls', value: "true")
|
||||
@@ -39,7 +39,7 @@ Setting.create(key: 'feature.legislation', value: "true")
|
||||
Setting.create(key: 'per_page_code_head', value: "")
|
||||
Setting.create(key: 'per_page_code_body', value: "")
|
||||
Setting.create(key: 'comments_body_max_length', value: '1000')
|
||||
Setting.create(key: 'mailer_from_name', value: 'Consul')
|
||||
Setting.create(key: 'mailer_from_name', value: 'CONSUL')
|
||||
Setting.create(key: 'mailer_from_address', value: 'noreply@consul.dev')
|
||||
Setting.create(key: 'meta_description', value: 'Citizen Participation and Open Government Application')
|
||||
Setting.create(key: 'meta_keywords', value: 'citizen participation, open government')
|
||||
@@ -84,6 +84,7 @@ manager.create_manager
|
||||
|
||||
valuator = create_user('valuator@consul.dev', 'valuator')
|
||||
valuator.create_valuator
|
||||
valuator.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.current, document_number: "2111111111")
|
||||
|
||||
poll_officer = create_user('poll_officer@consul.dev', 'Paul O. Fisher')
|
||||
poll_officer.create_poll_officer
|
||||
|
||||
14
db/migrate/20170720092638_create_documents.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class CreateDocuments < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :documents do |t|
|
||||
t.string :title
|
||||
t.attachment :attachment
|
||||
t.references :user, index: true, foreign_key: true
|
||||
t.references :documentable, polymorphic: true, index: true
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
|
||||
add_index :documents, [:user_id, :documentable_type, :documentable_id], name: "access_documents"
|
||||
end
|
||||
end
|
||||