Skip to content

Commit

Permalink
Merge branch '143-hide-filter-by-type-setting-if-the-setting-cannot-b…
Browse files Browse the repository at this point in the history
…e-changed-on-decidim-geo' into 'main'

Hide "Filter by type" setting if the setting cannot be changed on Decidim GEO

See merge request decidim/decidim-module-geo!131
  • Loading branch information
Hadrien Froger committed Oct 9, 2024
2 parents 1c48717 + 1df41d6 commit d6c917e
Show file tree
Hide file tree
Showing 20 changed files with 320 additions and 267 deletions.
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ PATH
decidim-decidim_geo (0.2.4)
activerecord-postgis-adapter (>= 6.0)
decidim-admin (>= 0.26, < 0.28)
decidim-api (>= 0.26, < 0.28)
decidim-core (>= 0.26, < 0.28)
deface (>= 1.8.1)
ffi-geos (~> 2.4)
Expand Down
117 changes: 117 additions & 0 deletions app/controllers/decidim/geo/points_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# frozen_string_literal: true

module Decidim
module Geo
class PointsController < ::Decidim::Api::ApplicationController
before_action :set_default_format

def index
results = query.select(
permitted_fields_params
).where(
query.arel_table[:id].gt(after_params)
).limit(
first_params
).reorder(
id: :asc
)
last_modified = query.maximum(:updated_at) || 1.year.from_now
etag = query.cache_key_with_version + "/params-" + Digest::MD5.hexdigest(permitted_params.to_json)
if stale?(last_modified: last_modified.utc, etag: etag)
last_id = query.maximum(:id)
render json: {
meta: {
fields: permitted_fields_params,
filters: filters_params,
organization: current_organization.id,
end_cursor: results.last && results.last.id,
default_locale: current_organization.default_locale,
first: first_params,
after: after_params,
has_more: results.last && results.last.id != last_id
},
data: results
}
end
end

private

def permitted_params
@permitted_params ||= params.permit(:first, :after, :locale, :is_index, :format, fields: [], filters: [])
end

def first_params
@first_params ||= (permitted_params[:first] || "50").to_i
end

def after_params
@after_params ||= (permitted_params[:after] || "0").to_i
end

def query
::Decidim::Geo::Api::GeoQuery.new(
current_organization,
current_user,
{
filters: filters_params,
is_index: is_index_params
},
locale_param
).results
end

def is_index_params
@is_index_params ||= permitted_params[:is_index] || false
end

def locale_param
@locale_param ||= permitted_params[:locale] || I18n.default_locale
end

def filters_params
@filters_params ||= (permitted_params[:filters] || []).map { |f| JSON.parse(f).with_indifferent_access }
end

def fields_params
@fields_params ||= permitted_params[:fields] || []
end

def include_lonlat?
fields_params.include? "lonlat"
end

def permitted_fields_params
@permitted_fields_params ||= begin
allowed_fields = %w(
resourceUrl
resourceId
resourceStatus
participatorySpaceId
participatorySpaceType
componentId
resourceType
startDate
endDate
title
shortDescription
descriptionHtml
imageUrl
lonlat
geoScopeId
extendedData
lonlat
)

filtered_fields = fields_params.select { |field| allowed_fields.include?(field.to_s) }
filtered_fields.push("id")
filtered_fields.map(&:underscore)
end
end

def set_default_format
request.format = :json
end
end
end
end
12 changes: 12 additions & 0 deletions app/models/decidim/geo/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ def coordinates
}
end
end

def as_json(options = {})
default_serialized = super(options)

# Use deep_transform_keys to camelize all keys
camelized = default_serialized.deep_transform_keys { |key| key.to_s.camelize(:lower) }

# Merge lonlat (coordinates) if it exists
camelized.merge!(lonlat: coordinates) if camelized.has_key?("lonlat")

camelized
end
end
end
end
73 changes: 54 additions & 19 deletions app/packs/src/decidim/geo/api/getGeoDataSource.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,71 @@
import { _getGeoDataSource, _getGeoDataSourceIds } from "./queries";

const getGeoDataSource = async (params = {}, fetchAll = true) => {
let results = [];
if (!params.variables) {
params.variables = {};
}
const apiQuery = fetchAll ? _getGeoDataSource : _getGeoDataSourceIds;


const getGeoDataSource = async (params = {}, fetchAll = true, callback) => {
const { filters = [], locale, isIndex = false, after = 0, first = 50 } = params;
const fields = fetchAll
? [
"resourceUrl",
"resourceId",
"resourceType",
"resourceStatus",
"participatorySpaceId",
"participatorySpaceType",
"componentId",
"startDate",
"endDate",
"title",
"shortDescription",
"descriptionHtml",
"imageUrl",
"latitude",
"longitude",
"scopeId",
"lonlat",
"extendedData"
]
: ["resourceType"];

const searchParams = new URLSearchParams({
locale,
is_index: isIndex,
after,
first
});
filters.forEach((f) => {
searchParams.append("filters[]", JSON.stringify(f))
})
fields.forEach((f) => searchParams.append("fields[]", f));
let page;
try {
page = await apiQuery(params);
const response = await fetch("/api/decidim-geo/points?" + searchParams.toString());
if (response.ok) page = await response.json();
else throw new Error(await response.text());
} catch (error) {
console.error(error);
throw error;
}
if (!page) return { nodes: [], edges: [] };
const { hasNextPage = false, endCursor = "" } = page?.pageInfo || {};
results = results.concat(page.nodes);
let hasMore = hasNextPage;
params.variables.after = endCursor;
while (hasMore) {
const { has_more: hasMoreThanOne, end_cursor: endCursor } = page?.meta || {};
callback(page.data, hasMoreThanOne)
if (!hasMoreThanOne) return;

searchParams.set("after", endCursor);
while (true) {
try {
page = await apiQuery(params);
const response = await fetch("/api/decidim-geo/points?" + searchParams.toString());
if (response.ok) page = await response.json();
else throw new Error(await response.text());
} catch (error) {
console.error(error);
return { nodes: results };
return;
}
const { endCursor = params.variables.after, hasNextPage } = page.pageInfo || {};
results = results.concat(page.nodes);
hasMore = hasNextPage;
params.variables.after = endCursor;
const { end_cursor: endCursor, has_more: hasMore } = page.meta || {};
callback(page.data, hasMore)
if (!hasMore) break;
searchParams.set("after", endCursor);
}

return { nodes: results };
};
export default getGeoDataSource;
24 changes: 8 additions & 16 deletions app/packs/src/decidim/geo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,11 @@ async function prepareLeaflet(isSmallScreen) {
configStore.setState(() => ({ map, tile, isSmallScreen }));
}
async function fetchData() {
const { addProcess, removeProcess, fetchAll, pointsForFilters } = pointStore.getState();
const { addProcess, removeProcess, fetchAll } = pointStore.getState();
addProcess();
// Fetch all the data
await Promise.allSettled([
fetchAll(filterStore.getState().defaultFilters),
pointsForFilters(filterStore.getState().defaultFilters, true)
]).then((results) => {
const rejected = results.filter((result) => result.status === "rejected");
if (rejected.length > 0)
console.error("ERR: fail to fetchData." + rejected.map((r) => r.reason).join("."));
removeProcess();
return results.map(({ value }) => value);
});
await fetchAll(filterStore.getState().defaultFilters)
removeProcess();
}
async function displayMap() {
try {
Expand All @@ -62,19 +54,19 @@ async function displayMap() {
});

pointStore.subscribe(
(state) => [!!state.isLoading, state.getFilteredPoints, state._lastResponse],
([isLoading, getFilteredPoints]) => {
(state) => [!!state.isLoading, state.getFilteredPoints, state.fetchesRunning, state._lastResponse],
([isLoading, getFilteredPoints, fetchesRunning]) => {
if (isLoading > 0) return;
const { space_ids: spaceIds, map } = configStore.getState();
const { selectedPoint, selectedScope } = geoStore.getState();
const { savedCenter } = memoryStore.getState();
pointsLayer.clearLayers();
let boudingBoxFilter = () => true;
if (!selectedPoint && !selectedScope && spaceIds) {
if (!fetchesRunning && !selectedPoint && !selectedScope && spaceIds) {
boudingBoxFilter = (node) =>
node.isGeoLocated() && spaceIds.includes(`${node.scopeId}`);
}
if (selectedScope?.layer && selectedScope && !selectedPoint) {
if (!fetchesRunning && selectedScope?.layer && selectedScope && !selectedPoint) {
map.fitBounds(selectedScope.layer.getBounds(), { padding: [64, 64] });
}

Expand All @@ -94,7 +86,7 @@ async function displayMap() {
: idealBoundingBox,
{ updateWhenZooming: true }
);
if (!savedCenter && boundingBox && !selectedScope && !selectedPoint) {
if (!fetchesRunning && !savedCenter && boundingBox && !selectedScope && !selectedPoint) {
map.fitBounds(boundingBox.getBounds(), { padding: [64, 64] });
}
}
Expand Down
12 changes: 7 additions & 5 deletions app/packs/src/decidim/geo/models/GeoDatasourceNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ export default class GeoDatasourceNode {
}

get type() {
if (!this.data.id || !this.data.type) return undefined;
return this.data.type;
if (!this.data.id || !this.data.resourceType) return undefined;
return this.data.resourceType;
}
get resourceType() {
return this.type;
}

get id() {
if (!this.data.id || !this.data.type) return undefined;
return `${this.data.type}::${this.data.id}`;
return parseInt(`${this.data.id}`) || undefined;
}

get scopeId() {
Expand Down Expand Up @@ -105,7 +107,7 @@ export default class GeoDatasourceNode {
}

init() {
if (this.data?.coordinates?.latitude && this.data?.coordinates?.longitude) {
if (this.data?.lonlat?.latitude && this.data?.lonlat?.longitude) {
this.marker = nodeMarker(this.data);
this.marker.on("click", this.select.bind(this));
this.marker.bringToFront();
Expand Down
Loading

0 comments on commit d6c917e

Please sign in to comment.