Skip to content

Instantly share code, notes, and snippets.

View unematiii's full-sized avatar

Mati Kärner unematiii

  • Yolo Group
  • Tartu
View GitHub Profile

Phonix LiveView Forms

Deterministic rendering & state restoration without additional caching.

  1. Use session and URL params as the starting point
    • Session includes user ID, roles, or any state that persists across LiveViews.
    • URL params / handle_params/3: includes context, like which record is being edited. Only minimum data to restore state should be kept there. I.e. If we have multiple forms on page, and we need to keep track on which of them are open.
  2. Fetch all persistent data from a deterministic source (mount, handle_params)
  3. Use form params to reconstruct unsaved input
    • The phx-change / validate event sends the client’s current form state.
/**
* Hook for tracking form loading state changes, i.e.
* class "phx-change-loading" is added or removed.
*
* <.form id="test-form" phx-hook="FormLoadingState"></.form>
* <div data-form-loading-state="test-form"
* data-on-load-start={JS.add_class("form-loading")}
* data-on-load-end={JS.remove_class("form-loading")}>
* </div>
*/
import { createPopper } from "@popperjs/core";
/**
* PHX hook for dropdowns
*
* <button
* id="dropdown-trigger"
* phx-hook="dropdown"
* data-dropdown-target="dropdown"
* data-dropdown-placement="bottom-end"
@unematiii
unematiii / ts-string-utils.ts
Created May 19, 2021 16:26
TypeScript type for camelCase <--> snake_case
export type CamelCase<T extends string, D extends string = '_'> =
T extends `${infer A}${D}${infer B}`
? CamelCase<`${Capitalize<A>}${Capitalize<B>}`>
: Uncapitalize<T>;
// type A = CamelCase<'snake_case'>
// snakeCase
export type CamelCasedDictionary<T> = {
[K in keyof T as K extends string ? CamelCase<K> : K]: T[K];
@unematiii
unematiii / hostapd.conf
Created March 27, 2021 18:32
RPI4 5Ghz AP
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
auth_algs=1
beacon_int=100
ssid=raspi-webgui
wpa_passphrase=ChangeMe
country_code=US
@unematiii
unematiii / openvpn-server-iptables.sh
Last active February 27, 2021 03:12
OpenVPN server iptables rules
#!/bin/sh
# check for interface
[ "$IFACE" = "lo" ] || exit 0
# allow the tcp connection on the openvpn port
iptables -A INPUT -i eth0 -m state --state NEW -p udp --dport 1194 -j ACCEPT
# allow TUN interface connections to OpenVPN server
iptables -A INPUT -i tun+ -j ACCEPT
@unematiii
unematiii / wakeup.xml
Created January 22, 2021 22:59
Wake up call
<Response>
<Say voice="alice">There are many trios of integers (x,y,z) that satisfy x²+y²=z². These are known as the Pythagorean Triples, like (3,4,5) and (5,12,13). Now, do any trios (x,y,z) satisfy x³+y³=z³?</Say>
</Response>
@unematiii
unematiii / fastify-decorators+3.4.0.patch
Created November 21, 2020 16:09
fastify-decorators+3.4.0.patch
diff --git a/node_modules/fastify-decorators/testing/configure-controller-test.js b/node_modules/fastify-decorators/testing/configure-controller-test.js
index f63f585..a4afbbc 100644
--- a/node_modules/fastify-decorators/testing/configure-controller-test.js
+++ b/node_modules/fastify-decorators/testing/configure-controller-test.js
@@ -14,8 +14,10 @@ const symbols_1 = require("../symbols");
const mocks_manager_1 = require("./mocks-manager");
const decorators_1 = require("../decorators");
const class_properties_1 = require("../decorators/helpers/class-properties");
+const utils_1 = require("../utils/wrap-injectable");
async function configureControllerTest(config) {