Skip to content

Commit

Permalink
Dataset : ajout de colonnes pour logos personnalisés (#3741)
Browse files Browse the repository at this point in the history
* Add custom_logos columns and use them

* Add script to generate logos and output commands

* Move bucket URL to config
  • Loading branch information
AntoineAugusti authored Jan 24, 2024
1 parent 318a225 commit 8c9bb84
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 7 deletions.
24 changes: 24 additions & 0 deletions apps/transport/lib/db/dataset.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ defmodule DB.Dataset do
field(:latest_data_gouv_comment_timestamp, :utc_datetime)
field(:archived_at, :utc_datetime_usec)
field(:custom_tags, {:array, :string}, default: [])
# URLs for custom logos.
# Currently we host custom logos in Cellar buckets.
# See config: `:transport, :logos_bucket_url`
field(:custom_logo, :string)
field(:custom_full_logo, :string)

timestamps(type: :utc_datetime_usec)

Expand Down Expand Up @@ -1068,4 +1073,23 @@ defmodule DB.Dataset do
false
"""
def has_custom_tag?(%__MODULE__{custom_tags: custom_tags}, tag_name), do: tag_name in (custom_tags || [])

@doc """
iex> logo(%DB.Dataset{logo: "https://example.com/logo.png", custom_logo: nil})
"https://example.com/logo.png"
iex> logo(%DB.Dataset{logo: "https://example.com/logo.png", custom_logo: "https://example.com/custom.png"})
"https://example.com/custom.png"
"""
@spec logo(__MODULE__.t()) :: binary()
def logo(%__MODULE__{logo: logo, custom_logo: custom_logo}), do: custom_logo || logo

@doc """
iex> full_logo(%DB.Dataset{full_logo: "https://example.com/logo.png", custom_full_logo: nil})
"https://example.com/logo.png"
iex> full_logo(%DB.Dataset{full_logo: "https://example.com/logo.png", custom_full_logo: "https://example.com/custom.png"})
"https://example.com/custom.png"
"""
@spec full_logo(__MODULE__.t()) :: binary()
def full_logo(%__MODULE__{full_logo: full_logo, custom_full_logo: custom_full_logo}),
do: custom_full_logo || full_logo
end
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ defmodule TransportWeb.Plugs.CustomSecureBrowserHeaders do
default-src 'none';
connect-src *;
font-src *;
img-src 'self' data: https://api.mapbox.com https://static.data.gouv.fr https://www.data.gouv.fr https://*.dmcdn.net;
img-src 'self' data: https://api.mapbox.com https://static.data.gouv.fr https://www.data.gouv.fr https://*.dmcdn.net #{Application.fetch_env!(:transport, :logos_bucket_url)};
script-src 'self' 'unsafe-eval' 'unsafe-inline' https://stats.data.gouv.fr/matomo.js;
frame-src https://www.dailymotion.com/;
style-src 'self' 'nonce-#{nonce}' #{vega_hash_values};
Expand All @@ -54,7 +54,7 @@ defmodule TransportWeb.Plugs.CustomSecureBrowserHeaders do
default-src 'none';
connect-src *;
font-src *;
img-src 'self' data: https://api.mapbox.com https://static.data.gouv.fr https://demo-static.data.gouv.fr https://www.data.gouv.fr https://demo.data.gouv.fr https://*.dmcdn.net;
img-src 'self' data: https://api.mapbox.com https://static.data.gouv.fr https://demo-static.data.gouv.fr https://www.data.gouv.fr https://demo.data.gouv.fr https://*.dmcdn.net #{Application.fetch_env!(:transport, :logos_bucket_url)};
script-src 'self' 'unsafe-eval' 'unsafe-inline' https://stats.data.gouv.fr/matomo.js;
frame-src https://www.dailymotion.com/;
style-src 'self' 'nonce-#{nonce}' #{vega_hash_values};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@
<div class="dataset-metas">
<div class="panel">
<div class="dataset__logo">
<%= img_tag(@dataset.full_logo, alt: @dataset.custom_title) %>
<%= img_tag(DB.Dataset.full_logo(@dataset), alt: @dataset.custom_title) %>
</div>
<div>
<i class="icon fa fa-map-marker-alt" /><%= Dataset.get_territory_or_nil(@dataset) %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
<div class="panel__content">
<div class="dataset__description">
<div class="dataset__image" data-provider={dataset.custom_title}>
<%= img_tag(dataset.logo, alt: dataset.custom_title) %>
<%= img_tag(DB.Dataset.logo(dataset), alt: dataset.custom_title) %>
</div>
<div class="dataset__infos">
<h3 class="dataset__title">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defmodule DB.Repo.Migrations.DatasetCustomLogosColumns do
use Ecto.Migration

def change do
alter table(:dataset) do
add(:custom_logo, :string)
add(:custom_full_logo, :string)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,28 @@ defmodule TransportWeb.DatasetControllerTest do
assert [] == Floki.find(doc, "#custom-message")
end

test "custom logo is displayed", %{conn: conn} do
dataset =
insert(:dataset,
type: "public-transit",
is_active: true,
custom_title: custom_title = "Super JDD",
custom_logo: custom_logo = "https://example.com/logo_#{Ecto.UUID.generate()}.png"
)

assert DB.Dataset.logo(dataset) == custom_logo

assert [
{"div", [{"class", "dataset__image"}, {"data-provider", _}],
[{"img", [{"alt", ^custom_title}, {"src", ^custom_logo}], []}]}
] =
conn
|> get(dataset_path(conn, :index))
|> html_response(200)
|> Floki.parse_document!()
|> Floki.find(".dataset__image")
end

describe "climate and resilience bill" do
test "displayed for public-transit", %{conn: conn} do
conn = conn |> get(dataset_path(conn, :index, type: "public-transit"))
Expand Down Expand Up @@ -473,6 +495,26 @@ defmodule TransportWeb.DatasetControllerTest do
assert content =~ "Le service de transport de ce jeu de donnée ne fonctionne pas toute l'année"
end

test "custom logo is displayed when set", %{conn: conn} do
dataset =
insert(:dataset,
is_active: true,
custom_title: custom_title = "Super JDD",
custom_full_logo: custom_full_logo = "https://example.com/logo_#{Ecto.UUID.generate()}.png"
)

set_empty_mocks()

assert DB.Dataset.full_logo(dataset) == custom_full_logo

assert [{"div", [{"class", "dataset__logo"}], [{"img", [{"alt", custom_title}, {"src", custom_full_logo}], []}]}] ==
conn
|> get(dataset_path(conn, :details, dataset.slug))
|> html_response(200)
|> Floki.parse_document!()
|> Floki.find(".dataset__logo")
end

test "gtfs-rt entities" do
dataset = %{id: dataset_id} = insert(:dataset, type: "public-transit")
%{id: resource_id_1} = insert(:resource, dataset_id: dataset_id, format: "gtfs-rt")
Expand Down
3 changes: 2 additions & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ config :transport,
gtfs_diff: "gtfs-diff-dev"
},
# by default, use the production validator. This can be overriden with dev.secret.exs
gtfs_validator_url: "https://validation.transport.data.gouv.fr"
gtfs_validator_url: "https://validation.transport.data.gouv.fr",
logos_bucket_url: "https://transport-data-gouv-fr-logos-dev.cellar-c2.services.clever-cloud.com"

config :oauth2, Datagouvfr.Authentication,
site: datagouvfr_site,
Expand Down
6 changes: 4 additions & 2 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ if app_env == :staging do
history: "resource-history-staging",
on_demand_validation: "on-demand-validation-staging",
gtfs_diff: "gtfs-diff-staging"
}
},
logos_bucket_url: "https://transport-data-gouv-fr-logos-staging.cellar-c2.services.clever-cloud.com"
end

base_oban_conf = [repo: DB.Repo, insert_trigger: false]
Expand Down Expand Up @@ -248,7 +249,8 @@ if config_env() == :prod do
"aires" => "673a16bf-49ec-4645-9da2-cf975d0aa0ea"
}
}
})
}),
logos_bucket_url: "https://transport-data-gouv-fr-logos-prod.cellar-c2.services.clever-cloud.com"

config :transport, Transport.Mailer,
adapter: Swoosh.Adapters.Mailjet,
Expand Down
39 changes: 39 additions & 0 deletions scripts/custom_logo.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Run script:
# `elixir scripts/custom_logo.exs /tmp/logo.jpg f0700f5f9954`
Mix.install([{:image, "~> 0.37"}])

require Logger

cellar_base_url = "http://transport-data-gouv-fr-logos-prod.cellar-c2.services.clever-cloud.com/"

{[], [src_path, datagouv_id]} = OptionParser.parse!(System.argv(), strict: [src_path: :string, datagouv_id: :string])

extension = src_path |> Path.extname() |> String.downcase()

logo_filename = "#{datagouv_id}#{extension}"
full_logo_filename = "#{datagouv_id}_full#{extension}"
logo_path = "/tmp/#{logo_filename}"
full_logo_path = "/tmp/#{full_logo_filename}"

src_path
|> Image.thumbnail!(100)
|> Image.embed!(100, 100, background_color: :white)
|> Image.write!(logo_path)

src_path
|> Image.thumbnail!(500)
|> Image.write!(full_logo_path)

Logger.info("Logos have been generated to:\n- #{logo_path}\n- #{full_logo_path}")

commands =
[logo_path, full_logo_path]
|> Enum.map_join("\n", fn path ->
"s3cmd put --acl-public --add-header='Cache-Control: public, max-age=604800' #{path} s3://transport-data-gouv-fr-logos-prod/"
end)

Logger.info("Run the following commands to upload files.\n#{commands}")

Logger.info(
"Query:\nUPDATE dataset SET custom_logo = '#{cellar_base_url}#{logo_filename}', custom_full_logo = '#{cellar_base_url}#{full_logo_filename}' WHERE datagouv_id = '#{datagouv_id}';"
)

0 comments on commit 8c9bb84

Please sign in to comment.