Skip to content

Commit

Permalink
Add latLng for explicit Feed geo point (#154)
Browse files Browse the repository at this point in the history
* Add longitudeLatitude field to feed - json of 'lng' and 'lat' to make it more explicit

* Fix small type error

* Add longitudeLatitude to Player type

* Update variable name, seeds, and add admin account on seed

* Blank commit to trigger github actions

* Update ui/src/components/MapLayout.tsx

Co-authored-by: Paul Cretu <paul.s.cretu@gmail.com>

* `latitudeLongitude` -> `latLng`

* Update user admin creation

* Finish swapping around lat and lng

* array -> property accessor

* Add types for latLng

* Make locationPoint non-nil

---------

Co-authored-by: Paul Cretu <paul.s.cretu@gmail.com>
  • Loading branch information
skanderm and paulcretu authored Jul 28, 2023
1 parent 054186b commit 2b4a559
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 53 deletions.
1 change: 0 additions & 1 deletion server/assets_v2/src/queries/feeds.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export const GET_FEED = gql`
name
slug
nodeName
locationPoint
introHtml
thumbUrl
mapUrl
Expand Down
1 change: 0 additions & 1 deletion server/assets_v2/src/types/feedType.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ export const feedType = shape({
name: string.isRequired,
slug: string.isRequired,
nodeName: string.isRequired,
locationPoint: object,
introHtml: string
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Orcasite.Radio.Calculations.LongitudeLatitude do
defmodule Orcasite.Radio.Calculations.LatLng do
use Ash.Calculation

@impl true
Expand All @@ -9,7 +9,7 @@ defmodule Orcasite.Radio.Calculations.LongitudeLatitude do
@impl true
def calculate(records, _opts, _arguments) do
Enum.map(records, fn %{location_point: %{coordinates: {lng, lat}}} ->
"#{lng},#{lat}"
"#{lat},#{lng}"
end)
end
end
34 changes: 17 additions & 17 deletions server/lib/orcasite/radio/feed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Orcasite.Radio.Feed do
attribute :name, :string
attribute :node_name, :string
attribute :slug, :string
attribute :location_point, :geometry
attribute :location_point, :geometry, allow_nil?: false

create_timestamp :inserted_at
update_timestamp :updated_at
Expand All @@ -32,7 +32,7 @@ defmodule Orcasite.Radio.Feed do

prepare fn query, _context ->
query
|> Ash.Query.load(:longitude_latitude)
|> Ash.Query.load(:lat_lng)
end
end

Expand All @@ -44,22 +44,22 @@ defmodule Orcasite.Radio.Feed do
primary? true
reject [:location_point]

argument :longitude_latitude, :string do
argument :lat_lng, :string do
description "A comma-separated string of longitude and latitude"
end

change &change_longitude_latitude/2
change &change_lat_lng/2
end

update :update do
primary? true
reject [:location_point]

argument :longitude_latitude, :string do
argument :lat_lng, :string do
description "A comma-separated string of longitude and latitude"
end

change &change_longitude_latitude/2
change &change_lat_lng/2
end
end

Expand All @@ -70,19 +70,19 @@ defmodule Orcasite.Radio.Feed do
end

calculations do
calculate :longitude_latitude,
calculate :lat_lng,
:string,
{Orcasite.Radio.Calculations.LongitudeLatitude,
{Orcasite.Radio.Calculations.LatLng,
keys: [:location_point], select: [:location_point]}
end

defp change_longitude_latitude(changeset, _context) do
with {:is_string, lng_lat} when is_binary(lng_lat) <-
{:is_string, Ash.Changeset.get_argument(changeset, :longitude_latitude)},
{:two_els, [lng, lat]} <-
{:two_els, lng_lat |> String.split(",") |> Enum.map(&String.trim/1)},
{:two_floats, [{longitude, _}, {latitude, _}]} <-
{:two_floats, [lng, lat] |> Enum.map(&Float.parse/1)} do
defp change_lat_lng(changeset, _context) do
with {:is_string, lat_lng} when is_binary(lat_lng) <-
{:is_string, Ash.Changeset.get_argument(changeset, :lat_lng)},
{:two_els, [lat, lng]} <-
{:two_els, lat_lng |> String.split(",") |> Enum.map(&String.trim/1)},
{:two_floats, [{latitude, _}, {longitude, _}]} <-
{:two_floats, [lat, lng] |> Enum.map(&Float.parse/1)} do
changeset
|> Ash.Changeset.change_attribute(:location_point, %Geo.Point{
coordinates: {longitude, latitude},
Expand All @@ -95,13 +95,13 @@ defmodule Orcasite.Radio.Feed do
{:two_els, _} ->
changeset
|> Ash.Changeset.add_error(
field: :longitude_latitude,
field: :lat_lng,
message: "must be a comma-separated string"
)

{:two_floats, _} ->
changeset
|> Ash.Changeset.add_error(field: :longitude_latitude, message: "must be two floats")
|> Ash.Changeset.add_error(field: :lat_lng, message: "must be two floats")
end
end

Expand Down
2 changes: 1 addition & 1 deletion server/lib/orcasite/radio_legacy/radio_legacy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Orcasite.RadioLegacy do

import Ecto.Query, warn: false
alias Orcasite.Repo
alias Orcasite.RadioLegacy.{Feed, Detection, Candidate}
alias Orcasite.RadioLegacy.{Detection, Candidate}

def verify_can_submit_detection(
feed_id,
Expand Down
14 changes: 8 additions & 6 deletions server/lib/orcasite_web/graphql/types/feed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ defmodule OrcasiteWeb.Types.Feed do
"""
use Absinthe.Schema.Notation

object :lat_lng do
field(:lat, non_null(:float))
field(:lng, non_null(:float))
end

object :feed do
field(:id, non_null(:id))
field(:name, non_null(:string))
field(:node_name, non_null(:string))
field(:slug, non_null(:string))

field :location_point, non_null(:json) do
field :lat_lng, non_null(:lat_lng) do
resolve(fn
%{location_point: point}, _, _ when not is_nil(point) ->
Geo.JSON.encode(point)

_, _, _ ->
{:ok, %{}}
%{location_point: %{coordinates: {lng, lat}}}, _, _ ->
{:ok, %{lat: lat, lng: lng}}
end)
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule Orcasite.Repo.Migrations.MakeLocationPointNonNil do
@moduledoc """
Updates resources based on their most recent snapshots.
This file was autogenerated with `mix ash_postgres.generate_migrations`
"""

use Ecto.Migration

def up do
alter table(:feeds) do
modify :location_point, :geometry, null: false
end
end

def down do
alter table(:feeds) do
modify :location_point, :geometry, null: true
end
end
end
21 changes: 16 additions & 5 deletions server/priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,31 @@ alias Orcasite.RadioLegacy.Feed

feeds = [
%{
location_point: Geo.WKT.decode!("SRID=4326;POINT(48.5583362 -123.1735774)"),
location_point: Geo.WKT.decode!("SRID=4326;POINT(-123.1735774 48.5583362)"),
name: "Orcasound Lab (Haro Strait)",
node_name: "rpi_orcasound_lab",
slug: "orcasound-lab"
},
%{
location_point: Geo.WKT.decode!("SRID=4326;POINT(48.0336664 -122.6040035)"),
location_point: Geo.WKT.decode!("SRID=4326;POINT(-122.6040035 48.0336664)"),
name: "Bush Point",
node_name: "rpi_bush_point",
slug: "bush-point"
},
%{
location_point: Geo.WKT.decode!("SRID=4326;POINT(48.135743 -122.760614)"),
location_point: Geo.WKT.decode!("SRID=4326;POINT(-122.760614 48.135743)"),
name: "Port Townsend",
node_name: "rpi_port_townsend",
slug: "port-townsend"
},
%{
location_point: Geo.WKT.decode!("SRID=4326;POINT(47.86497296593844 -122.33393605795372)"),
location_point: Geo.WKT.decode!("SRID=4326;POINT(-122.33393605795372 47.86497296593844)"),
name: "Sunset Bay",
node_name: "rpi_sunset_bay",
slug: "sunset-bay"
},
%{
location_point: Geo.WKT.decode!("SRID=4326;POINT(48.591294 -123.058779)"),
location_point: Geo.WKT.decode!("SRID=4326;POINT(-123.058779 48.591294)"),
name: "North San Juan Channel",
node_name: "rpi_north_sjc",
slug: "north-sjc"
Expand All @@ -60,3 +60,14 @@ for attrs <- feeds do
|> Orcasite.Repo.insert!()
end
end

# Create admin account
strategy = AshAuthentication.Info.strategy!(Orcasite.Accounts.User, :password)
Orcasite.Accounts.User
|> Ash.Changeset.for_create(strategy.register_action_name, %{
email: "admin@example.com",
password: "password",
password_confirmation: "password",
})
|> Ash.Changeset.force_change_attribute(:admin, true)
|> Orcasite.Accounts.create!()
98 changes: 98 additions & 0 deletions server/priv/resource_snapshots/repo/feeds/20230728032135.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"attributes": [
{
"default": "nil",
"size": null,
"type": "bigint",
"source": "id",
"references": null,
"allow_nil?": false,
"primary_key?": true,
"generated?": true
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "name",
"references": null,
"allow_nil?": true,
"primary_key?": false,
"generated?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "node_name",
"references": null,
"allow_nil?": true,
"primary_key?": false,
"generated?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "slug",
"references": null,
"allow_nil?": true,
"primary_key?": false,
"generated?": false
},
{
"default": "nil",
"size": null,
"type": "geometry",
"source": "location_point",
"references": null,
"allow_nil?": false,
"primary_key?": false,
"generated?": false
},
{
"default": "fragment(\"now()\")",
"size": null,
"type": "utc_datetime_usec",
"source": "inserted_at",
"references": null,
"allow_nil?": false,
"primary_key?": false,
"generated?": false
},
{
"default": "fragment(\"now()\")",
"size": null,
"type": "utc_datetime_usec",
"source": "updated_at",
"references": null,
"allow_nil?": false,
"primary_key?": false,
"generated?": false
}
],
"table": "feeds",
"hash": "CFF5AB9134C541B23476FBE8EEE1739B188560E3D2BBC8E5B318F60127E90B06",
"repo": "Elixir.Orcasite.Repo",
"identities": [
{
"name": "unique_slug",
"keys": [
"slug"
],
"base_filter": null,
"index_name": "feeds_unique_slug_index"
}
],
"schema": null,
"multitenancy": {
"global": null,
"attribute": null,
"strategy": null
},
"base_filter": null,
"check_constraints": [],
"custom_indexes": [],
"custom_statements": [],
"has_create_action": true
}
4 changes: 2 additions & 2 deletions ui/src/components/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function Map({
feeds,
}: {
setMap?: (map: LeafletMap) => void
currentFeed?: Pick<Feed, 'slug' | 'locationPoint'>
currentFeed?: Pick<Feed, 'slug' | 'latLng'>
feeds: FeedsQuery['feeds']
}) {
const router = useRouter()
Expand Down Expand Up @@ -50,7 +50,7 @@ export default function Map({
{feeds.map((feed) => (
<Marker
key={feed.slug}
position={feed.locationPoint.coordinates}
position={feed.latLng}
icon={
feed.slug === currentFeed?.slug
? hydrophoneActiveIcon
Expand Down
6 changes: 2 additions & 4 deletions ui/src/components/MapLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ const feedFromSlug = (feedSlug: string) => ({
slug: feedSlug,
nodeName: feedSlug,
// TODO: figure out which coordinates to use for dynamic feeds
locationPoint: {
coordinates: [47.6, -122.3],
},
latLng: { lat: 47.6, lng: -122.3 },
})

function MapLayout({ children }: { children: ReactNode }) {
Expand All @@ -46,7 +44,7 @@ function MapLayout({ children }: { children: ReactNode }) {
useEffect(() => {
if (feed && feed.slug !== currentFeed?.slug) {
setCurrentFeed(feed)
map?.panTo(feed.locationPoint.coordinates)
map?.panTo(feed.latLng)
}
}, [feed, map, currentFeed])

Expand Down
8 changes: 2 additions & 6 deletions ui/src/components/Player/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ export type PlayerStatus = 'idle' | 'loading' | 'playing' | 'paused' | 'error'
export default function Player({
currentFeed,
}: {
currentFeed?: Pick<
Feed,
'id' | 'slug' | 'nodeName' | 'name' | 'locationPoint'
>
currentFeed?: Pick<Feed, 'id' | 'slug' | 'nodeName' | 'name' | 'latLng'>
}) {
const [playerStatus, setPlayerStatus] = useState<PlayerStatus>('idle')
const playerRef = useRef<VideoJSPlayer | null>(null)
Expand Down Expand Up @@ -152,8 +149,7 @@ export default function Player({
: 'Select a location to start listening live'}
</Box>
<Box sx={{ mx: 4, flexGrow: 1, textAlign: 'end' }}>
{currentFeed &&
`${currentFeed.locationPoint.coordinates[0]}, ${currentFeed.locationPoint.coordinates[1]}`}
{currentFeed && `${currentFeed.latLng.lng}, ${currentFeed.latLng.lat}`}
</Box>
</Box>
)
Expand Down
Loading

0 comments on commit 2b4a559

Please sign in to comment.