mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-25 01:15:26 +10:00
feat: add application timeline history (#3237)
* feat: add application timeline history * fix: address application timeline review * fix: keep application tracker e2e stable * fix: use stable timeline e2e selector * fix: target timeline note input in e2e
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
WITH entries AS (
|
||||
SELECT
|
||||
a.id AS application_id,
|
||||
entry.value AS entry,
|
||||
entry.ordinality,
|
||||
coalesce(nullif(entry.value ->> 'id', ''), md5(a.id || ':' || entry.ordinality::text)) AS entry_id,
|
||||
coalesce(nullif(entry.value ->> 'at', ''), a.applied_at::text, a.created_at::text, now()::text) AS entry_at,
|
||||
lower(coalesce(entry.value ->> 'text', '')) AS entry_text
|
||||
FROM "application" a
|
||||
CROSS JOIN LATERAL jsonb_array_elements(
|
||||
CASE WHEN jsonb_typeof(a.activity) = 'array' THEN a.activity ELSE '[]'::jsonb END
|
||||
) WITH ORDINALITY AS entry(value, ordinality)
|
||||
),
|
||||
normalized AS (
|
||||
SELECT
|
||||
application_id,
|
||||
ordinality,
|
||||
CASE
|
||||
WHEN entry ->> 'type' = 'stage'
|
||||
AND entry ->> 'stage' IN ('saved', 'applied', 'screening', 'interview', 'offer', 'rejected') THEN
|
||||
jsonb_build_object('id', entry_id, 'type', 'stage', 'stage', entry ->> 'stage', 'at', entry_at)
|
||||
WHEN entry ->> 'type' IN ('created', 'stage')
|
||||
AND CASE
|
||||
WHEN entry_text LIKE '%screening%' THEN 'screening'
|
||||
WHEN entry_text LIKE '%interview%' THEN 'interview'
|
||||
WHEN entry_text LIKE '%offer%' THEN 'offer'
|
||||
WHEN entry_text LIKE '%rejected%' THEN 'rejected'
|
||||
WHEN entry_text LIKE '%applied%' THEN 'applied'
|
||||
WHEN entry_text LIKE '%saved%' THEN 'saved'
|
||||
END IS NOT NULL THEN
|
||||
jsonb_build_object(
|
||||
'id', entry_id,
|
||||
'type', 'stage',
|
||||
'stage', CASE
|
||||
WHEN entry_text LIKE '%screening%' THEN 'screening'
|
||||
WHEN entry_text LIKE '%interview%' THEN 'interview'
|
||||
WHEN entry_text LIKE '%offer%' THEN 'offer'
|
||||
WHEN entry_text LIKE '%rejected%' THEN 'rejected'
|
||||
WHEN entry_text LIKE '%applied%' THEN 'applied'
|
||||
WHEN entry_text LIKE '%saved%' THEN 'saved'
|
||||
END,
|
||||
'at', entry_at
|
||||
)
|
||||
ELSE
|
||||
jsonb_build_object(
|
||||
'id', entry_id,
|
||||
'type', 'note',
|
||||
'text', coalesce(nullif(btrim(entry ->> 'text'), ''), 'Imported timeline entry'),
|
||||
'at', entry_at
|
||||
)
|
||||
END AS normalized_entry
|
||||
FROM entries
|
||||
),
|
||||
grouped AS (
|
||||
SELECT application_id, jsonb_agg(normalized_entry ORDER BY ordinality) AS activity
|
||||
FROM normalized
|
||||
GROUP BY application_id
|
||||
)
|
||||
UPDATE "application" a
|
||||
SET activity = grouped.activity
|
||||
FROM grouped
|
||||
WHERE a.id = grouped.application_id;
|
||||
--> statement-breakpoint
|
||||
UPDATE "application"
|
||||
SET activity = jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'id', md5(id || ':stage'),
|
||||
'type', 'stage',
|
||||
'stage', status,
|
||||
'at', coalesce(applied_at::text, created_at::text, now()::text)
|
||||
)
|
||||
)
|
||||
WHERE jsonb_typeof(activity) IS DISTINCT FROM 'array' OR activity = '[]'::jsonb;
|
||||
--> statement-breakpoint
|
||||
WITH stage_stats AS (
|
||||
SELECT
|
||||
a.id AS application_id,
|
||||
max((entry.value ->> 'at')::timestamptz) FILTER (WHERE entry.value ->> 'type' = 'stage') AS latest_stage_at,
|
||||
max((entry.value ->> 'at')::timestamptz) FILTER (
|
||||
WHERE entry.value ->> 'type' = 'stage' AND entry.value ->> 'stage' = a.status
|
||||
) AS current_stage_at
|
||||
FROM "application" a
|
||||
CROSS JOIN LATERAL jsonb_array_elements(
|
||||
CASE WHEN jsonb_typeof(a.activity) = 'array' THEN a.activity ELSE '[]'::jsonb END
|
||||
) AS entry(value)
|
||||
GROUP BY a.id
|
||||
),
|
||||
anchors AS (
|
||||
SELECT
|
||||
a.id,
|
||||
a.status,
|
||||
greatest(
|
||||
coalesce(stage_stats.latest_stage_at, a.applied_at, a.created_at, now()),
|
||||
coalesce(a.applied_at, a.created_at, now())
|
||||
) AS anchor_at,
|
||||
stage_stats.latest_stage_at,
|
||||
stage_stats.current_stage_at
|
||||
FROM "application" a
|
||||
LEFT JOIN stage_stats ON stage_stats.application_id = a.id
|
||||
WHERE jsonb_typeof(a.activity) = 'array'
|
||||
)
|
||||
UPDATE "application" a
|
||||
SET activity = a.activity || jsonb_build_array(
|
||||
jsonb_build_object(
|
||||
'id', md5(a.id || ':stage:' || a.status || ':anchor'),
|
||||
'type', 'stage',
|
||||
'stage', a.status,
|
||||
'at', anchors.anchor_at::text
|
||||
)
|
||||
)
|
||||
FROM anchors
|
||||
WHERE a.id = anchors.id
|
||||
AND (
|
||||
anchors.current_stage_at IS NULL
|
||||
OR (anchors.latest_stage_at IS NOT NULL AND anchors.current_stage_at < anchors.latest_stage_at)
|
||||
);
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user