From b54a8458d5029b3494165b7430e21b3ae34ecc0c Mon Sep 17 00:00:00 2001 From: hellekin Date: Fri, 22 Jan 2021 05:32:15 +0100 Subject: Upgrade Rails and add StimulusJS support --- app/assets/stylesheets/application.css | 15 --- app/assets/stylesheets/application.scss | 21 ++++ app/assets/stylesheets/sections.scss | 3 + app/assets/stylesheets/taxonomies.scss | 2 + app/controllers/categories_controller.rb | 5 + app/controllers/sections_controller.rb | 16 ++++ app/controllers/users_controller.rb | 13 +-- app/helpers/application_helper.rb | 19 ---- app/helpers/leaflet_helper.rb | 11 +++ app/helpers/map_helper.rb | 19 ++++ app/helpers/sections_helper.rb | 19 ++++ app/helpers/taxonomies/filter_helper.rb | 2 +- app/javascript/controllers/map_controller.js | 59 +++++++++--- app/javascript/controllers/taxonomy_controller.js | 112 ++++++++++++++++++++-- app/javascript/packs/application.js | 6 ++ app/models/agency.rb | 28 ------ app/models/resource.rb | 20 +++- app/views/agents/_edit.html.erb | 6 ++ app/views/agents/_form.html.erb | 22 +++++ app/views/agents/index.html.erb | 5 + app/views/agents/new.html.erb | 2 + app/views/agents/show.html.erb | 3 + app/views/categories/_category.html.erb | 17 ++++ app/views/categories/_edit.html.erb | 6 ++ app/views/categories/_form.html.erb | 25 +++++ app/views/categories/edit.html.erb | 1 + app/views/categories/show.html.erb | 2 + app/views/layouts/application.html.erb | 55 +++++------ app/views/resources/_resource.json.erb | 1 + app/views/resources/show.json.erb | 1 + app/views/sections/show.html.erb | 11 +++ app/views/sections/show.json.erb | 1 + app/views/taxonomies/_taxonomy.html.erb | 1 - app/views/taxonomies/index.html.erb | 2 +- app/views/users/_user.html.erb | 3 + app/views/users/index.html.erb | 6 +- app/views/welcome/authenticate.html.erb | 2 +- app/views/welcome/index.html.erb | 5 +- 38 files changed, 415 insertions(+), 132 deletions(-) delete mode 100644 app/assets/stylesheets/application.css create mode 100644 app/assets/stylesheets/application.scss create mode 100644 app/assets/stylesheets/sections.scss create mode 100644 app/controllers/sections_controller.rb create mode 100644 app/helpers/leaflet_helper.rb create mode 100644 app/helpers/map_helper.rb create mode 100644 app/helpers/sections_helper.rb create mode 100644 app/views/agents/_edit.html.erb create mode 100644 app/views/agents/_form.html.erb create mode 100644 app/views/agents/index.html.erb create mode 100644 app/views/agents/new.html.erb create mode 100644 app/views/agents/show.html.erb create mode 100644 app/views/categories/_category.html.erb create mode 100644 app/views/categories/_edit.html.erb create mode 100644 app/views/categories/_form.html.erb create mode 100644 app/views/categories/edit.html.erb create mode 100644 app/views/categories/show.html.erb create mode 100644 app/views/resources/_resource.json.erb create mode 100644 app/views/resources/show.json.erb create mode 100644 app/views/sections/show.html.erb create mode 100644 app/views/sections/show.json.erb create mode 100644 app/views/users/_user.html.erb (limited to 'app') diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css deleted file mode 100644 index d05ea0f..0000000 --- a/app/assets/stylesheets/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's - * vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS - * files in this directory. Styles in this file should be added after the last require_* statement. - * It is generally better to create a new file per style scope. - * - *= require_tree . - *= require_self - */ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss new file mode 100644 index 0000000..94d00ec --- /dev/null +++ b/app/assets/stylesheets/application.scss @@ -0,0 +1,21 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require normalize.css/normalize.css + *= require_self + *= require leaflet + *= require leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css + *= require leaflet.markercluster/dist/MarkerCluster.css + *= require leaflet.markercluster/dist/MarkerCluster.Default.css + *= require_tree . + * + */ diff --git a/app/assets/stylesheets/sections.scss b/app/assets/stylesheets/sections.scss new file mode 100644 index 0000000..d540c09 --- /dev/null +++ b/app/assets/stylesheets/sections.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sections controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: https://sass-lang.com/ diff --git a/app/assets/stylesheets/taxonomies.scss b/app/assets/stylesheets/taxonomies.scss index 4e227da..b1fabcd 100644 --- a/app/assets/stylesheets/taxonomies.scss +++ b/app/assets/stylesheets/taxonomies.scss @@ -68,9 +68,11 @@ button[data-action="taxonomy#toggle"] { font-weight: bold; ol { display: block; + z-index: 1002; } li.active { text-align: right; + z-index: 1002; } } diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 40f1ff5..da8d837 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -10,6 +10,11 @@ class CategoriesController < ApplicationController def show @category = Category.find(params[:id]) + + respond_to do |format| + format.html + format.js + end end def edit diff --git a/app/controllers/sections_controller.rb b/app/controllers/sections_controller.rb new file mode 100644 index 0000000..fed1d57 --- /dev/null +++ b/app/controllers/sections_controller.rb @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2020 IN COMMON Collective +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +class SectionsController < ApplicationController + skip_before_action :verify_authenticity_token, only: :show + + def show + @section = Section.find(params[:id]) + respond_to do |format| + format.html + format.js + format.json + end + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9a3cf74..f0479d1 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -3,18 +3,9 @@ # SPDX-License-Identifier: AGPL-3.0-or-later class UsersController < ApplicationController - # GET /my/users - # If you're a leader, you will see a list of Agent members + # GET /my/peers def index - begin - return 403 unless current_user.agencies.find_by(name: current_agent).leader? - rescue Exception => e - Rails.logger.info("Exception %s: %s" % [e.class, e.message]) - flash[:notice] = "Talk to your leader!" - redirect_to root_url and return - end - - @users = Agent.where(name: current_agent).members + @users = current_agent.members end # GET /my/account diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 15d5082..e39da5f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -6,25 +6,6 @@ module ApplicationHelper def current_agency current_user.agencies.where(agent: current_agent).first end - %w(observer editor maintainer leader).each do |role| - define_method :"current_user_#{role}?" do - current_agency.send(:"#{role}?") - end - end - - def map_container(map = Map.first) - raw tag.div( - tag.div(id: 'map', - data: { - target: 'map.container' - }), - data: { - controller: 'map', - 'map-latitude': map.latitude, - 'map-longitude': map.longitude, - 'map-zoom': map.zoom - }) - end # Markdown helper # Always use all extensions. Additional parser and render options may be diff --git a/app/helpers/leaflet_helper.rb b/app/helpers/leaflet_helper.rb new file mode 100644 index 0000000..6ca03f3 --- /dev/null +++ b/app/helpers/leaflet_helper.rb @@ -0,0 +1,11 @@ +module LeafletHelper + def marker_for(resource, options = {}) + coords = [resource.latitude, resource.longitude] + + "L.marker(#{coords}, #{options}).bindPopup(%s)" % popup_for(resource) + end + + def popup_for(resource) + render partial: 'resource/popup', locals: { resource: resource } + end +end diff --git a/app/helpers/map_helper.rb b/app/helpers/map_helper.rb new file mode 100644 index 0000000..3403801 --- /dev/null +++ b/app/helpers/map_helper.rb @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2020 IN COMMON Collective +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +module MapHelper + def map_container(map = Map.first) + raw tag.div( + tag.div(id: 'map', + data: { + target: 'map.container' + }), + data: { + controller: 'map', + 'map-latitude': map.latitude, + 'map-longitude': map.longitude, + 'map-zoom': map.zoom + }) + end +end diff --git a/app/helpers/sections_helper.rb b/app/helpers/sections_helper.rb new file mode 100644 index 0000000..8180fee --- /dev/null +++ b/app/helpers/sections_helper.rb @@ -0,0 +1,19 @@ +module SectionsHelper + # Render a section as a GeoJSON FeatureCollection + def geojson_feature_collection(section) + out = [] + class_name = { baseVal: "cat#{section.category_id} sec#{section.id}" } + style = { fill: section.category.color } + + section.resources.each do |marker| + # Add styling + marker = marker.to_geojson + marker['className'] = class_name + marker['style'] = style + + out << marker.to_json + end + + raw("{ \"type\": \"FeatureCollection\", \"features\": [ #{out.join(',')} ] }") + end +end diff --git a/app/helpers/taxonomies/filter_helper.rb b/app/helpers/taxonomies/filter_helper.rb index 97fe271..92a501f 100644 --- a/app/helpers/taxonomies/filter_helper.rb +++ b/app/helpers/taxonomies/filter_helper.rb @@ -11,7 +11,7 @@ module Taxonomies::FilterHelper @taxonomy.categories.each do |cat| list = [] cat.sections.each do |sec| - list << tag.li(h("#{sec.rank}. #{sec.name}"), id: "section-#{sec.id}", data: { action: "taxonomy#section", target: 'taxonomy.section', 'taxonomy-section-id': sec.id }) + list << tag.li(h("#{sec.rank}. #{sec.name}"), id: "section-#{sec.id}", data: { action: "click->taxonomy#section", target: 'taxonomy.section', 'taxonomy-section-id': sec.id }) end html << tag.li(h("#{cat.rank}. #{cat.name}") << tag.ol(list.join.html_safe), id: "category-#{cat.id}", diff --git a/app/javascript/controllers/map_controller.js b/app/javascript/controllers/map_controller.js index 30c1361..1704da8 100644 --- a/app/javascript/controllers/map_controller.js +++ b/app/javascript/controllers/map_controller.js @@ -7,32 +7,65 @@ // import { Controller } from "stimulus" -import "leaflet/dist/leaflet.css" -import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css'; // Re-uses images from ~leaflet package -import L from "leaflet" +import 'leaflet/dist/leaflet.css' +// Re-uses images from ~leaflet package +import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css' + +import * as L from 'leaflet' +import 'leaflet-defaulticon-compatibility' +import "leaflet-providers" +import "leaflet.markercluster/dist/leaflet.markercluster.js" + +import 'leaflet-makimarkers' export default class extends Controller { static targets = [ "container" ] initialize() { - + console.log("Map controller initialized.") + this.mapBoxAPIToken = 'pk.eyJ1IjoibmVtYWVsIiwiYSI6ImNrZzBrYjBudTB3bnMyenFmNWtrN3h3bmMifQ.Rkeyhm-9iIQOV7NAMA5LaA' } connect() { - this.map = L.map(this.containerTarget, { - zoomDelta: 0.5, - zoomSnap: 0.5, - }).setView(this._coordinates(), this._zoom()); + L.MakiMarkers.accessToken = this.mapBoxAPIToken - L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { + var mapbox = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery Mapbox', maxZoom: 18, id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, - accessToken: 'pk.eyJ1IjoibmVtYWVsIiwiYSI6ImNrZzBrYjBudTB3bnMyenFmNWtrN3h3bmMifQ.Rkeyhm-9iIQOV7NAMA5LaA' - }).addTo(this.map); + accessToken: this.mapBoxAPIToken + }) + + var stamen_tr = L.tileLayer.provider('Stamen.Toner') + var stamen_wc = L.tileLayer.provider('Stamen.Watercolor') + var tiles_osm = L.tileLayer.provider('OpenStreetMap.Mapnik') + var tiles_sat = L.tileLayer.provider('Esri.WorldImagery') + + const tilemaps = { + 'osm': tiles_osm, + 'mapbox': mapbox, + 'watercolor': stamen_wc, + 'greyscale': stamen_tr, + 'satellite': tiles_sat + } + + const overlays = {} + + this.map = L.map(this.containerTarget, { + zoomDelta: 0.5, + zoomSnap: 0.5, + layers: [ tiles_osm ], + }).setView(this._coordinates(), this._zoom()); + + L.control.layers(tilemaps, overlays).addTo(this.map) + + L.DomEvent.on(window, 'hashchange', this.doSomethingCool); + + // Allow calling the mapController from elsewhere. + this.element[this.identifier] = this } disconnect() { @@ -40,6 +73,10 @@ export default class extends Controller { console.log('Map controller disconnected.') } + doSomethingCool() { + console.log(window.location.hash) + } + _coordinates() { return [this.data.get('latitude'), this.data.get('longitude')]; } diff --git a/app/javascript/controllers/taxonomy_controller.js b/app/javascript/controllers/taxonomy_controller.js index 16d57fa..02b1483 100644 --- a/app/javascript/controllers/taxonomy_controller.js +++ b/app/javascript/controllers/taxonomy_controller.js @@ -9,15 +9,18 @@ import { Controller } from "stimulus" export default class extends Controller { - static targets = [ "category", "deploy", "filter", "section", "toggle" ] + static targets = [ "category", "deploy", "filter", "layers", "section", "toggle" ] initialize() { console.log("Taxonomy controller initialized.") + + this.overlays = {} + this.sectionsOnMap = [] } connect() { console.log("Taxonomy controller connected.") - + this.taxonomy_uuid = this.data.get('uuid') if (this.hasFilterTarget) { let url = `/taxonomies/${this.data.get('uuid')}/filter.js` console.log(`loading url = ${url}`) @@ -29,10 +32,19 @@ export default class extends Controller { } else { console.log("Taxonomy filter is missing") } + + // Access the map + if (this.map = document.querySelector('#map').parentElement.map.map) { + console.log("Taxonomy Controller connected to this.map") + } else { + console.log("Taxonomy Controller could not load map!") + } } + deploy() { console.log(`deploying taxonomy ${this.data.get('uuid')}`); + fetch(`/taxonomies/${this.data.get('uuid')}.js`) .then(response => response.text()) .then(html => this.deployTarget.innerHTML = html); @@ -45,12 +57,100 @@ export default class extends Controller { } category(event) { - let catId = event.target.dataset.taxonomyCategoryId - event.target.classList.toggle('active') + let catId = (event.target.dataset.taxonomyCategoryId || event.target.parentNode.parentNode.dataset.CategoryId) + let secId = event.target.dataset.taxonomySectionId + console.log(`Category: ${catId}/${secId}`) + var active = event.target.classList.toggle('active') + if (active) { + console.log('activated') + } else { + console.log('deactivated') + } + } + + loadCategory(catId) { + document.querySelector(`#category-${catId}`).lastChild.childNodes.forEach(function(li) { + this._mapLayerToggleSection(li.dataset.taxonomySectionId) + }) } section(event) { - let catId = event.target.dataset.taxonomySectionId - event.target.classList.toggle('active') + let secId = event.target.dataset.taxonomySectionId + console.log(`Section: ${secId} to be loaded`) + this._loadMarkers(secId) + this._mapLayerToggleSection(secId) + } + + _sectionIconName(secId) { + const names = { + 215: 'campsite', + 216: 'hospital', + 217: 'landmark', + 218: 'shelter', + 219: 'lodging', + 220: 'playground', + 221: 'residential-community', + 222: 'home', + 223: 'residential-community', + 224: 'residential-community', + 225: 'home' + + } + return names[secId] || 'circle' + } + + _loadMarkers(secId) { + if (this.overlays[secId] == undefined) { + console.log(`loading markers for section ${secId} [${this._sectionIconName(secId)}]...`) + let overlay = L.layerGroup(); + let markers = L.markerClusterGroup(); + let iconName = this._sectionIconName(secId); + + fetch(`/sections/${secId}.json`, { + headers: { 'X-CSRF-Token': this._csrfToken() } + }) + .then(response => response.json()) + .then(data => { + L.geoJSON(data, { + pointToLayer: function (feature, latlng) { + return L.marker(latlng, { + attribution: feature.source, + icon: L.MakiMarkers.icon({ + icon: iconName, + className: feature.className.baseVal, + color: feature.style.fill, + size: 'm' + }) + }); + }, + onEachFeature: (feature, layer) => { + layer.on('click', () => this.onClick(layer)) + layer.addTo(markers) + } + }) + }) + console.log(`cluster counts ${markers.length} markers`) + this.overlays[secId] = markers + } + } + + onClick(layer) { + console.log(layer) + } + + _mapLayerToggleSection(secId) { + if (this.sectionsOnMap.includes(secId)) { + console.log(`removing section ${secId} from map`) + this.map.removeLayer(this.overlays[secId]) + this.sectionsOnMap.pop(secId) + } else { + console.log(`adding section ${secId} to the map`) + this.sectionsOnMap.push(secId) + this.overlays[secId].addTo(this.map) + } + } + + _csrfToken() { + return document.querySelector('[name=csrf-token]').content } } diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 5e3eec0..a4b51a8 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -15,4 +15,10 @@ require("@rails/activestorage").start() // const images = require.context('../images', true) // const imagePath = (name) => images(name, true) +//= require leaflet +//= require leaflet-defaulticon-compatibility +//= require leaflet.markercluster + import "controllers" + +import 'stylesheets/application' diff --git a/app/models/agency.rb b/app/models/agency.rb index 7ffe489..842e8bd 100644 --- a/app/models/agency.rb +++ b/app/models/agency.rb @@ -3,34 +3,6 @@ # SPDX-License-Identifier: AGPL-3.0-or-later class Agency < ApplicationRecord - include Bitfields - belongs_to :agent belongs_to :user - - bitfield :roles, :observer, :editor, :maintainer, :leader - - class << self - # Grant role in agent to user - def grant(agent, user, role) - r = find_or_create_by(agent: agent, user: user) - r&.public_send("#{role}=", true) && r&.save - end - - # Revoke role in agent from user - def revoke(agent, user, role) - r = find_by(agent: agent, user: user) - r&.public_send("#{role}=", false) && r&.save - end - end - - # Grant role to current user in current agent - def grant(role) - self.class.grant(agent, user, role) - end - - # Revoke role from current user in current agent - def revoke(role) - self.class.revoke(agent, user, role) - end end diff --git a/app/models/resource.rb b/app/models/resource.rb index 8df106c..bde0c56 100644 --- a/app/models/resource.rb +++ b/app/models/resource.rb @@ -44,17 +44,17 @@ class Resource < ApplicationRecord # You can use, e.g.: res.longitude = 0.123 def longitude - feature['geometry']['coordinates'][0] + format('%3.7f', lon: feature['geometry']['coordinates'][0]).to_f end def longitude=(value) - feature['geometry']['coordinates'][0] = value + feature['geometry']['coordinates'][0] = format('%3.7f', lon: value).to_f end # You can use, e.g.: res.latitude = 0.123 def latitude - feature['geometry']['coordinates'][1] + format('%2.7f', lat: feature['geometry']['coordinates'][1]).to_f end def latitude=(value) - feature['geometry']['coordinates'][1] = value + feature['geometry']['coordinates'][1] = format('%2.7f', lat: value).to_f end # Properties @@ -68,4 +68,16 @@ class Resource < ApplicationRecord feature['properties'][prop.to_s] = v end end + + # Poor man's GeoJSON output + def to_geojson + out = feature.dup + # Convert original Dewey IDs with local Section IDs + out['properties']['categories'] = Section.where(dewey_id: out['properties']['categories']).pluck(:id) + # Add IN COMMON Resource UUID property + out['properties']['uuid'] = uuid + # Add IN COMMON Agent UUID property + out['properties']['agent_uuid'] = agent.uuid + out + end end diff --git a/app/views/agents/_edit.html.erb b/app/views/agents/_edit.html.erb new file mode 100644 index 0000000..72ce56d --- /dev/null +++ b/app/views/agents/_edit.html.erb @@ -0,0 +1,6 @@ +

Edit <%= @agent.presence&.name || 'new agent' %>

+

Context: <%= current_agent %>

+ +<%= form_with model: @agent, url: controller.action_name == 'new' ? agents_path : agent_path(@agent) do |f| %> + <%= render partial: 'form', locals: { agent: @agent, f: f } %> +<% end %> diff --git a/app/views/agents/_form.html.erb b/app/views/agents/_form.html.erb new file mode 100644 index 0000000..563e8ec --- /dev/null +++ b/app/views/agents/_form.html.erb @@ -0,0 +1,22 @@ +
+ <%= tag.legend "Propriétés de l'Agent" %> + +
+
<%= f.label :name %>
+
<%= f.text_field :name, maxlength: 64, placeholder: 'incommon' %> +
hint: this must match a group name on talk.incommon.cc
+ +
<%= f.label :summary %>
+
<%= f.text_field :summary, maxlength: 136, placeholder: 'Default Agent' %>
+ +
<%= f.label :description %>
+
<%= f.text_area :description, cols: 72, rows: 10, spellcheck: true, +placeholder: '## IN COMMON Default Agent + +La description _peut_ comporter du [Markdown]. + +[Markdown]: https://www.markdownguide.org/getting-started/' %>
+
+
+ +

<%= f.submit 'Save' %>

diff --git a/app/views/agents/index.html.erb b/app/views/agents/index.html.erb new file mode 100644 index 0000000..6cb9fb3 --- /dev/null +++ b/app/views/agents/index.html.erb @@ -0,0 +1,5 @@ +
+

Agents

+ + <%= render partial: @agents %> +
diff --git a/app/views/agents/new.html.erb b/app/views/agents/new.html.erb new file mode 100644 index 0000000..3794662 --- /dev/null +++ b/app/views/agents/new.html.erb @@ -0,0 +1,2 @@ +<%= render partial: 'edit', locals: { agent: @agent } %> + diff --git a/app/views/agents/show.html.erb b/app/views/agents/show.html.erb new file mode 100644 index 0000000..0652dc8 --- /dev/null +++ b/app/views/agents/show.html.erb @@ -0,0 +1,3 @@ +
+ <%= render partial: @agent %> +
diff --git a/app/views/categories/_category.html.erb b/app/views/categories/_category.html.erb new file mode 100644 index 0000000..d301fe6 --- /dev/null +++ b/app/views/categories/_category.html.erb @@ -0,0 +1,17 @@ +
+
+

<%= category.taxonomy.name %>

+

<%= category.name %>

+
+

<%= h category.summary %>

+
<%= h category.description %>
+

Info

+

<%= pluralize(category.sections_count, 'section') %>

+

<%= pluralize(category.sections.map { |s| s.resources }.sum(&:count) || 0, 'resources') %>

+
+
+
    +
  • <%= link_to 'edit', edit_category_path(category) %>
  • +
+
+
diff --git a/app/views/categories/_edit.html.erb b/app/views/categories/_edit.html.erb new file mode 100644 index 0000000..4a2da94 --- /dev/null +++ b/app/views/categories/_edit.html.erb @@ -0,0 +1,6 @@ +

Edit <%= @category.presence&.name || 'new category' %>

+

Context: <%= @taxonomy %>

+ +<%= form_with model: [@taxonomy,@category], url: controller.action_name == 'new' ? taxonomy_categories_path(taxonomy: @taxonomy) : category_path(@category) do |f| %> + <%= render partial: 'form', locals: { category: category, f: f } %> +<% end %> diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb new file mode 100644 index 0000000..c4c77c6 --- /dev/null +++ b/app/views/categories/_form.html.erb @@ -0,0 +1,25 @@ +
+ <%= tag.legend "Categorie..." %> + +
+
<%= f.label :name %>
+
<%= f.text_field :name, maxlength: 64, placeholder: 'Se loger' %>
+ +
<%= f.label :summary %>
+
<%= f.text_field :summary, maxlength: 136, placeholder: 'Une ferme locale' %>
+ +
<%= f.label :description %>
+
<%= f.text_area :description, cols: 72, rows: 10, placeholder: '## Un choix pertinent + +La description _peut_ comporter du [Markdown]. + +[Markdown]: https://www.markdownguide.org/getting-started/' %>
+ +
<%= f.label :color %>
+
<%= f.color_field :color, placeholder: '#cc0077 (or: rgba(255 0 0 0.5)' %>
+
+
+ +<%= f.hidden_field :taxonomy_id, value: @category.taxonomy_id %> + +

<%= f.submit 'Save' %>

diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb new file mode 100644 index 0000000..054bed3 --- /dev/null +++ b/app/views/categories/edit.html.erb @@ -0,0 +1 @@ +<%= render partial: 'edit', locals: { category: @category } %> diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb new file mode 100644 index 0000000..ed548c6 --- /dev/null +++ b/app/views/categories/show.html.erb @@ -0,0 +1,2 @@ +<%= @category.inspect %> +<%= render @category %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 210ace8..bc02585 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -4,33 +4,34 @@ Carte IN COMMON - <%= csrf_meta_tags %> - <%= csp_meta_tag %> + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + <%= display_meta_tags site: 'IN COMMON Map' %> - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> - <%= yield :head %> - + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> + <%= yield :head %> + - -
-

<%= link_to image_tag("https://talk.incommon.cc/uploads/disc_6_incommon/original/1X/92f926e8210ea7a5412d6e2bdabfa825233e808b.png", alt: "IN COMMON", size: "x4em"), '/' %>

- <%= render 'application/user_info' %> - <%= yield :header %> -
-
-
- <%= yield %> -
-
- -
- <%= yield :footer %> -
- <%= render partial: 'debug' %> - <%= render partial: 'flash' %> - <%= yield :body_end %> - + +
+

<%= link_to image_tag("https://talk.incommon.cc/uploads/disc_6_incommon/original/1X/92f926e8210ea7a5412d6e2bdabfa825233e808b.png", alt: "IN COMMON", size: "x4em"), '/' %>

+ <%= render 'application/user_info' %> + <%= yield :header %> +
+
+
+ <%= yield %> +
+
+ +
+ <%= yield :footer %> +
+ <%= render partial: 'debug' %> + <%= render partial: 'flash' %> + <%= yield :body_end %> + diff --git a/app/views/resources/_resource.json.erb b/app/views/resources/_resource.json.erb new file mode 100644 index 0000000..a3769d6 --- /dev/null +++ b/app/views/resources/_resource.json.erb @@ -0,0 +1 @@ +<%= resource.as_json %> diff --git a/app/views/resources/show.json.erb b/app/views/resources/show.json.erb new file mode 100644 index 0000000..5855d72 --- /dev/null +++ b/app/views/resources/show.json.erb @@ -0,0 +1 @@ +<%= render @resource %> diff --git a/app/views/sections/show.html.erb b/app/views/sections/show.html.erb new file mode 100644 index 0000000..9a69891 --- /dev/null +++ b/app/views/sections/show.html.erb @@ -0,0 +1,11 @@ +

+// First, create a section layer on the map, then assign all resource markers to it.
+sec<%= @section.id %> = L.layerGroup
+
+<% @section.resources.each_with_index do |res, i| %>
+mk_<%= i %> = L.marker([<%= res.latitude %>, <%= res.longitude %>]).addTo(sec<%= @section.id %>)
+<% end %>
+
+sec<%= @section.id %>.addTo(map)
+
+
diff --git a/app/views/sections/show.json.erb b/app/views/sections/show.json.erb new file mode 100644 index 0000000..9520404 --- /dev/null +++ b/app/views/sections/show.json.erb @@ -0,0 +1 @@ +<%= geojson_feature_collection(@section) %> diff --git a/app/views/taxonomies/_taxonomy.html.erb b/app/views/taxonomies/_taxonomy.html.erb index eff6931..eb2dd79 100644 --- a/app/views/taxonomies/_taxonomy.html.erb +++ b/app/views/taxonomies/_taxonomy.html.erb @@ -5,4 +5,3 @@
- diff --git a/app/views/taxonomies/index.html.erb b/app/views/taxonomies/index.html.erb index d060f6c..705b0d4 100644 --- a/app/views/taxonomies/index.html.erb +++ b/app/views/taxonomies/index.html.erb @@ -1,5 +1,5 @@

Available Taxonomies

- <%= render collection: @taxonomies: %> + <%= render collection: @taxonomies %>
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb new file mode 100644 index 0000000..2da5239 --- /dev/null +++ b/app/views/users/_user.html.erb @@ -0,0 +1,3 @@ +
+ <%= user.name %> +
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 0d53728..3451981 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,4 +1,4 @@ -

Users#index

-

Find me in app/views/users/index.html.erb

+

Agent <%= current_agent %> Members

+

This agent counts (<%= pluralize(@users.count, "member") %>)

-

Show a table with Agent <%= current_agent %> members (<%= pluralize(@users.count, "user") %>), their roles, and ways to change them.

+<%= render partial: 'user', collection: @users %> diff --git a/app/views/welcome/authenticate.html.erb b/app/views/welcome/authenticate.html.erb index 548101b..ba9f1c5 100644 --- a/app/views/welcome/authenticate.html.erb +++ b/app/views/welcome/authenticate.html.erb @@ -5,7 +5,7 @@

Your Agents:

    <% @current_user&.agencies&.each do |a| %> -
  • <%= a.name %> (<%= a.roles %>)
  • +
  • <%= a.name %>
  • <% end %>

diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index 2a154ae..d9fd0f6 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -8,14 +8,11 @@
+
<% end %> <% content_for :debug do %> <% if current_user.present? %> -

Premier élément de la liste:

- <% res = @resources.first %> -

<%= res.feature["properties"]["name"] %>

-

<%= res.feature["geometry"]["coordinates"] %>

<% end %><%# ensure it does not break when we don't have a record... %> <% end %> -- cgit v1.2.3