Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add latLng for explicit Feed geo point #154

Merged
merged 14 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}
skanderm marked this conversation as resolved.
Show resolved Hide resolved
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
Loading