diff --git a/rails/app/controllers/api/base_controller.rb b/rails/app/controllers/api/base_controller.rb index 6bb714a06..fae5c11d8 100644 --- a/rails/app/controllers/api/base_controller.rb +++ b/rails/app/controllers/api/base_controller.rb @@ -4,6 +4,21 @@ class BaseController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, with: :not_found + + helper_method :envelope + def envelope(json, pageMeta = nil) + json.data do + yield if block_given? + end + if pageMeta + json.meta do + json.total @page.total + json.hasNextPage @page.has_next_page? + json.nextPageMeta @page.next_page_meta + end + end + end + protected def not_found diff --git a/rails/app/views/api/communities/index.json.jbuilder b/rails/app/views/api/communities/index.json.jbuilder index 7ce2dd06d..2d4fde710 100644 --- a/rails/app/views/api/communities/index.json.jbuilder +++ b/rails/app/views/api/communities/index.json.jbuilder @@ -1,27 +1,29 @@ -json.array! @communities do |community| - json.extract! community, :name, :description, :slug +envelope(json) do + json.array! @communities do |community| + json.extract! community, :name, :description, :slug - json.createdAt community.created_at - json.updatedAt community.updated_at + json.createdAt community.created_at + json.updatedAt community.updated_at - if community.display_image.attached? - json.displayImage rails_blob_url(community.display_image) - end + if community.display_image.attached? + json.displayImage rails_blob_url(community.display_image) + end - if community.theme.static_map.attached? - json.staticMapUrl rails_blob_url(community.theme.static_map) - end + if community.theme.static_map.attached? + json.staticMapUrl rails_blob_url(community.theme.static_map) + end - json.mapConfig do - json.mapboxAccessToken community.theme.mapbox_access_token - json.mapboxStyle community.theme.mapbox_style - json.mapbox3dEnabled community.theme.mapbox_3d - json.mapProjection community.theme.map_projection + json.mapConfig do + json.mapboxAccessToken community.theme.mapbox_access_token + json.mapboxStyle community.theme.mapbox_style + json.mapbox3dEnabled community.theme.mapbox_3d + json.mapProjection community.theme.map_projection - json.center community.theme.center + json.center community.theme.center - json.zoom community.theme.zoom - json.pitch community.theme.pitch - json.bearing community.theme.bearing + json.zoom community.theme.zoom + json.pitch community.theme.pitch + json.bearing community.theme.bearing + end end -end +end \ No newline at end of file diff --git a/rails/app/views/api/communities/show.json.jbuilder b/rails/app/views/api/communities/show.json.jbuilder index a3c9a3327..4c33ae419 100644 --- a/rails/app/views/api/communities/show.json.jbuilder +++ b/rails/app/views/api/communities/show.json.jbuilder @@ -1,45 +1,47 @@ -json.(@community, :name, :slug, :description) - -# Details are used specifically in the Explore Panel -json.details do - json.(@community, :name, :description) - json.sponsorLogos @community.sponsor_logos do |logo| - json.url rails_blob_url(logo) - json.blobId logo.blob.id +envelope(json) do + json.(@community, :name, :slug, :description) + + # Details are used specifically in the Explore Panel + json.details do + json.(@community, :name, :description) + json.sponsorLogos @community.sponsor_logos do |logo| + json.url rails_blob_url(logo) + json.blobId logo.blob.id + end + if @community.display_image.attached? + json.displayImage rails_blob_url(@community.display_image) + end end - if @community.display_image.attached? - json.displayImage rails_blob_url(@community.display_image) + + # Initial Map Configuration + stories = @community.stories.preload(:places).where(permission_level: :anonymous) + json.storiesCount stories.size + json.points stories.flat_map(&:public_points).uniq + + # Side Panel Filter Categories + json.categories Community::FILTERABLE_ATTRIBUTES + + # Side Panel Filter Options (generated from available content) + json.filters @community.filters + + json.mapConfig do + json.mapboxAccessToken @community.theme.mapbox_access_token + json.mapboxStyle @community.theme.mapbox_style + json.mapbox3dEnabled @community.theme.mapbox_3d + json.mapProjection @community.theme.map_projection + + json.centerLat @community.theme.center_lat + json.centerLong @community.theme.center_long + json.swBoundaryLat @community.theme.sw_boundary_lat + json.swBoundaryLong @community.theme.sw_boundary_long + json.neBoundaryLat @community.theme.ne_boundary_lat + json.neBoundaryLong @community.theme.ne_boundary_long + + json.center @community.theme.center + json.maxBounds @community.theme.boundaries + + json.zoom @community.theme.zoom + json.pitch @community.theme.pitch + json.bearing @community.theme.bearing end -end - -# Initial Map Configuration -stories = @community.stories.preload(:places).where(permission_level: :anonymous) -json.storiesCount stories.size -json.points stories.flat_map(&:public_points).uniq - -# Side Panel Filter Categories -json.categories Community::FILTERABLE_ATTRIBUTES - -# Side Panel Filter Options (generated from available content) -json.filters @community.filters - -json.mapConfig do - json.mapboxAccessToken @community.theme.mapbox_access_token - json.mapboxStyle @community.theme.mapbox_style - json.mapbox3dEnabled @community.theme.mapbox_3d - json.mapProjection @community.theme.map_projection - - json.centerLat @community.theme.center_lat - json.centerLong @community.theme.center_long - json.swBoundaryLat @community.theme.sw_boundary_lat - json.swBoundaryLong @community.theme.sw_boundary_long - json.neBoundaryLat @community.theme.ne_boundary_lat - json.neBoundaryLong @community.theme.ne_boundary_long - - json.center @community.theme.center - json.maxBounds @community.theme.boundaries - - json.zoom @community.theme.zoom - json.pitch @community.theme.pitch - json.bearing @community.theme.bearing -end +end \ No newline at end of file diff --git a/rails/app/views/api/places/show.json.jbuilder b/rails/app/views/api/places/show.json.jbuilder index f69054b6a..cc322088f 100644 --- a/rails/app/views/api/places/show.json.jbuilder +++ b/rails/app/views/api/places/show.json.jbuilder @@ -1,6 +1,8 @@ -json.(@place, :id, :name, :description, :region) +envelope(json) do + json.(@place, :id, :name, :description, :region) -json.placenameAudio @place.name_audio_url(full_url: true) -json.typeOfPlace @place.type_of_place + json.placenameAudio @place.name_audio_url(full_url: true) + json.typeOfPlace @place.type_of_place -json.points [@place.public_point_feature] + json.points [@place.public_point_feature] +end \ No newline at end of file diff --git a/rails/app/views/api/stories/index.json.jbuilder b/rails/app/views/api/stories/index.json.jbuilder index 021761f4e..681cb7385 100644 --- a/rails/app/views/api/stories/index.json.jbuilder +++ b/rails/app/views/api/stories/index.json.jbuilder @@ -1,17 +1,14 @@ -json.total @page.total - -# Regardless of Story list page, all points in the data relation -# should be returned for map markers. -json.points @page.relation.flat_map { |s| s.public_points }.uniq - -json.stories @stories do |story| - json.extract! story, :id, :title, :topic, :desc, :language - json.mediaContentTypes story.media_types - json.mediaPreviewUrl story.media_preview_thumbnail - - json.createdAt story.created_at - json.updatedAt story.updated_at -end - -json.hasNextPage @page.has_next_page? -json.nextPageMeta @page.next_page_meta \ No newline at end of file +envelope(json, @page) do + # Regardless of Story list page, all points in the data relation + # should be returned for map markers. + json.points @page.relation.flat_map { |s| s.public_points }.uniq + + json.stories @stories do |story| + json.extract! story, :id, :title, :topic, :desc, :language + json.mediaContentTypes story.media_types + json.mediaPreviewUrl story.media_preview_thumbnail + + json.createdAt story.created_at + json.updatedAt story.updated_at + end +end \ No newline at end of file diff --git a/rails/app/views/api/stories/show.json.jbuilder b/rails/app/views/api/stories/show.json.jbuilder index a3c2d2669..13277f374 100644 --- a/rails/app/views/api/stories/show.json.jbuilder +++ b/rails/app/views/api/stories/show.json.jbuilder @@ -1,3 +1,4 @@ +envelope(json) do json.(@story, :id, :title, :desc, :topic, :language) json.media @story.media do |media| json.contentType media.content_type @@ -46,3 +47,4 @@ json.places @story.places do |place| end json.points @story.public_points +end \ No newline at end of file diff --git a/rails/spec/requests/api/public_communities_spec.rb b/rails/spec/requests/api/public_communities_spec.rb index 18d0c5964..e49979d65 100644 --- a/rails/spec/requests/api/public_communities_spec.rb +++ b/rails/spec/requests/api/public_communities_spec.rb @@ -4,10 +4,6 @@ let!(:public_community) { FactoryBot.create(:public_community, name: "Cool Community") } let!(:community) { FactoryBot.create(:community, name: "Private Community") } - def json_response - JSON.parse(response.body) - end - it "returns an array of public communities" do get "/api/communities" diff --git a/rails/spec/requests/api/public_community_spec.rb b/rails/spec/requests/api/public_community_spec.rb index 2f83a5fdb..0c9559a89 100644 --- a/rails/spec/requests/api/public_community_spec.rb +++ b/rails/spec/requests/api/public_community_spec.rb @@ -3,10 +3,6 @@ RSpec.describe "Public Community (show) Endpoint", type: :request do let!(:public_community) { FactoryBot.create(:public_community, name: "Cool Community") } - def json_response - JSON.parse(response.body) - end - it "returns 404 when community can't be found" do get "/api/communities/unknown" diff --git a/rails/spec/requests/api/public_place_spec.rb b/rails/spec/requests/api/public_place_spec.rb index ad5a08cef..a607c7fa2 100644 --- a/rails/spec/requests/api/public_place_spec.rb +++ b/rails/spec/requests/api/public_place_spec.rb @@ -24,11 +24,6 @@ ) end - - def json_response - JSON.parse(response.body) - end - it "returns a 404 not found if community is not found" do get "/api/communities/unknown/places/123" diff --git a/rails/spec/requests/api/public_stories_spec.rb b/rails/spec/requests/api/public_stories_spec.rb index 569d7e444..715d182bc 100644 --- a/rails/spec/requests/api/public_stories_spec.rb +++ b/rails/spec/requests/api/public_stories_spec.rb @@ -3,10 +3,6 @@ RSpec.describe "Public Stories Endpoint", type: :request do let!(:community) { FactoryBot.create(:public_community, name: "Cool Community") } - def json_response - JSON.parse(response.body) - end - it "returns 404 when community can't be found" do get "/api/communities/unknown/stories" @@ -25,7 +21,8 @@ def json_response get "/api/communities/cool_community/stories" expect(response).to have_http_status(:ok) - expect(json_response.keys).to contain_exactly("total", "points", "stories", "hasNextPage", "nextPageMeta") + expect(json_response.keys).to contain_exactly("points", "stories") + expect(json_meta.keys).to contain_exactly("total", "hasNextPage", "nextPageMeta") end context "filters and sort" do @@ -90,43 +87,43 @@ def json_response # filter by place (id / name) get "/api/communities/cool_community/stories", params: {places: [place_2.id]} - expect(json_response["total"]).to eq(1) + expect(json_meta["total"]).to eq(1) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_1.id) # filter by region get "/api/communities/cool_community/stories", params: {region: ["the internet"]} - expect(json_response["total"]).to eq(2) + expect(json_meta["total"]).to eq(2) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_2.id, story_3.id) # filter by type of place get "/api/communities/cool_community/stories", params: {type_of_place: ["online"]} - expect(json_response["total"]).to eq(1) + expect(json_meta["total"]).to eq(1) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_1.id) # filter by topic get "/api/communities/cool_community/stories", params: {topic: ["nonprofit work", "tech"]} - expect(json_response["total"]).to eq(2) + expect(json_meta["total"]).to eq(2) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_2.id, story_3.id) # filter by language get "/api/communities/cool_community/stories", params: {language: ["Spanish", "Other"]} - expect(json_response["total"]).to eq(1) + expect(json_meta["total"]).to eq(1) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_3.id) # filter by speaker get "/api/communities/cool_community/stories", params: {speakers: [speaker_1.id, speaker_2.id]} - expect(json_response["total"]).to eq(3) + expect(json_meta["total"]).to eq(3) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_1.id, story_2.id, story_3.id) # filter by speaker community get "/api/communities/cool_community/stories", params: {speaker_community: ["ruby for good"]} - expect(json_response["total"]).to eq(2) + expect(json_meta["total"]).to eq(2) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_1.id, story_2.id) end @@ -136,7 +133,7 @@ def json_response get "/api/communities/cool_community/stories" - expect(json_response["total"]).to eq(1) + expect(json_meta["total"]).to eq(1) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_1.id) end @@ -145,7 +142,7 @@ def json_response get "/api/communities/cool_community/stories" - expect(json_response["total"]).to eq(2) + expect(json_meta["total"]).to eq(2) expect(json_response["stories"].map { |s| s["id"] }).to contain_exactly(story_1.id, story_3.id) end @@ -172,16 +169,16 @@ def json_response it "correctly paginates with filters" do get "/api/communities/cool_community/stories", params: {limit: 1} - expect(json_response["total"]).to eq(3) + expect(json_meta["total"]).to eq(3) expect(json_response["stories"].count).to eq(1) - expect(json_response["hasNextPage"]).to be true + expect(json_meta["hasNextPage"]).to be true # filter down to one place get "/api/communities/cool_community/stories", params: {limit: 1, places: [place_2.id]} - expect(json_response["total"]).to eq(1) + expect(json_meta["total"]).to eq(1) expect(json_response["stories"].count).to eq(1) - expect(json_response["hasNextPage"]).to be false + expect(json_meta["hasNextPage"]).to be false end end end diff --git a/rails/spec/requests/api/public_story_spec.rb b/rails/spec/requests/api/public_story_spec.rb index c68952c08..b2e31e39c 100644 --- a/rails/spec/requests/api/public_story_spec.rb +++ b/rails/spec/requests/api/public_story_spec.rb @@ -20,10 +20,6 @@ ) end - def json_response - JSON.parse(response.body) - end - it "returns 404 when community can't be found" do get "/api/communities/unknown/stories/123" diff --git a/rails/spec/support/api_helpers.rb b/rails/spec/support/api_helpers.rb new file mode 100644 index 000000000..b65b44edb --- /dev/null +++ b/rails/spec/support/api_helpers.rb @@ -0,0 +1,11 @@ +def json_body + JSON.parse(response.body) +end + +def json_response + json_body["data"] +end + +def json_meta + json_body["meta"] +end