Skip to content

Instantly share code, notes, and snippets.

View cblavier's full-sized avatar

Christian Blavier cblavier

View GitHub Profile
@cblavier
cblavier / mjml.ex
Created March 5, 2023 18:28
mjml.ex
defmodule Readable.Emails.MJML do
@external_resource __DIR__
def mjml_template(path) do
template = path |> Path.expand(__DIR__) |> File.read!()
{:ok, html} =
~r|<mj-include\s+path="([^"]*)"\s+/>|
|> Regex.scan(template)
|> Enum.map(fn [match, path] ->
@cblavier
cblavier / transloadit.ex
Created February 21, 2023 20:49
Transloadit Elixir client
defmodule Readable.Transloadit do
use Tesla
plug Tesla.Middleware.BaseUrl, "https://api2.transloadit.com/"
plug Tesla.Middleware.JSON
@behaviour Readable.Transloadit.TransloaditAPI
@impl true
def run_assembly(assembly, file_path, source_container, target_container) do
@cblavier
cblavier / pagination.ex
Created February 2, 2023 14:18
Phoenix pagination components
defmodule ReadableWeb.Pagination do
use Phoenix.Component
attr :page, :integer, required: true
attr :page_count, :integer, required: true
attr :path, :string, required: true
def pagination(assigns) do
~H"""
<ul class="inline-flex items-center h-8">
@cblavier
cblavier / post_coverage.sh
Created May 4, 2022 07:54
Script to post lcov test coverage as a PR GitHub comment.
#! /usr/bin/env bash
export GITHUB_TOKEN="REDACTED"
branch=$1
pr_number=$(gh pr list -H $branch --json number | jq ".[0].number")
# testing if $pr_number is a number
if [ "$pr_number" -eq "$pr_number" ]; then
echo "found PR: $pr_number"
@cblavier
cblavier / appsignal_telemetry.ex
Last active April 14, 2022 01:27
A Phoenix Telemetry agent to monitor all LiveView events & errors
defmodule AppSignalTelemetry do
use GenServer
require Appsignal.Utils
import Appsignal.Utils, only: [module_name: 1]
@tracer Appsignal.Utils.compile_env(:appsignal, :appsignal_tracer, Appsignal.Tracer)
@span Appsignal.Utils.compile_env(:appsignal, :appsignal_span, Appsignal.Span)
@appsignal_namespace "live_view"
def start_link do
@cblavier
cblavier / _table_example.html.slim
Last active April 28, 2021 17:37
Table live_component with phx_component_helpers
= live_component @socket, Table,
headers: [id: "ID", last_name: "Nom et email", actions: ""],
sortable: [:id, :last_name],
selectable: :checkbox,
mobile_hidden: [:id, :actions],
current_sorting: @table_sorting,
row_count: @user_count,
selected_row_count: @selected_user_count,
sticky_header: true do
@cblavier
cblavier / app.js
Created January 9, 2021 10:55
Responsive Phoenix LiveView
const Hooks = { ViewportResizeHooks}
const connectLiveSocket = () => {
const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute('content')
const liveSocket = new LiveSocket('/my_app/live', Socket, {
params: {
_csrf_token: csrfToken,
viewport: {
width: window.innerWidth,
height: window.innerHeight
@cblavier
cblavier / rewrite_request_logger_cookie.ex
Created October 13, 2020 12:34
Phoenix plug to rewrite phoenix_live_dashboard request_logger cookie to parent domain
@cblavier
cblavier / ecto_producer.ex
Created November 2, 2019 10:50
GenStage producer streaming / buffering data from an Ecto query. Can be used with Flow.
defmodule Flow.EctoProducer do
use GenStage
import Ecto.Query
@default_chunk_size 5000
@default_key :id
@stop_delay 10
# Possible options for producer
$> mix n_test 1 4
$> mix n_test 2 4
$> mix n_test 3 4
$> mix n_test 4 4