d718c5a372
CI / compile_and_lint (push) Failing after 0s
CI / docker_build (linux/amd64, -linux-amd64-duckdb, duckdb) (push) Failing after 0s
CI / docker_build (linux/arm64, -linux-arm64, minimal) (push) Failing after 2s
CI / docker_build (linux/arm64, -linux-arm64-duckdb, duckdb) (push) Failing after 1s
CI / docker_build (linux/amd64, minimal) (push) Failing after 1s
CI / test (, sqlite, sqlite::memory:) (push) Has been skipped
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been skipped
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been skipped
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / playwright (push) Has been skipped
CI / docker_build (linux/arm/v7, -linux-arm-v7, minimal) (push) Failing after 0s
CI / hurl_examples (push) Failing after 8s
deploy website / deploy_official_site (push) Failing after 1s
CI / hurl (${{ matrix.example }}) (push) Has been skipped
CI / docker_push (duckdb) (push) Has been cancelled
CI / docker_push (minimal) (push) Has been cancelled
CI / windows_test (push) Has been cancelled
98 lines
4.6 KiB
SQL
98 lines
4.6 KiB
SQL
-- Include 'shell.sql' to generate the page header and footer
|
|
select 'dynamic' as component, sqlpage.run_sql('shell.sql') as properties;
|
|
|
|
-- Define a Common Table Expression (CTE) named 'updated'
|
|
-- CTEs are temporary named result sets, useful for complex queries
|
|
-- Here, it's used to perform the update and capture the results in one step
|
|
with updated as (
|
|
-- Update the 'todos' table and return the modified rows
|
|
-- This approach allows us to both update the data and use it for reporting
|
|
update todos set
|
|
-- Modify the title based on user input for labels
|
|
-- The CASE statements handle different scenarios for label management
|
|
title = case
|
|
-- If :remove_label is null, we keep the existing title as is
|
|
when :remove_label is null then
|
|
title
|
|
else
|
|
-- Remove any existing labels (text within parentheses)
|
|
-- This uses a regular expression to strip out (label) from the end
|
|
regexp_replace(title, '\s*\(.*\)', '')
|
|
end
|
|
-- Concatenate the result with a new label if provided
|
|
||
|
|
case
|
|
-- If no new label is provided, we don't add anything
|
|
when :new_label is null or :new_label = '' then
|
|
''
|
|
else
|
|
-- Add the new label in parentheses at the end
|
|
' (' || :new_label || ')'
|
|
end
|
|
-- Determine which todos to update based on user selection
|
|
where
|
|
-- Update specific todos if their IDs are in the :todos parameter
|
|
-- :todos is a JSON array of todo string IDs, e.g. ["1", "2", "3"]
|
|
-- that optionally includes "all" to update all todos
|
|
id in (
|
|
-- Parse the JSON array of todo IDs and convert each to integer
|
|
-- This allows for multiple todo selection in the UI
|
|
select e::int from jsonb_array_elements_text(:todos::jsonb) e
|
|
where e != 'all'
|
|
)
|
|
-- If 'all' is the only selected, update every todo (by making the where condition always true)
|
|
or :todos = '["all"]'
|
|
-- Return all updated rows for counting and potential further use
|
|
returning *
|
|
)
|
|
-- Generate an alert component to inform the user about the update result
|
|
-- This provides immediate feedback on the operation's outcome
|
|
select 'alert' as component,
|
|
'Batch update' as title,
|
|
-- Create a dynamic message with the count of updated todos
|
|
format('%s todos updated', (select count(*) from updated)) as description
|
|
-- Only display the alert if at least one todo was updated
|
|
-- This prevents showing unnecessary alerts for no-op updates
|
|
where exists (select * from updated);
|
|
|
|
-- Create a form component for the batch update interface
|
|
-- This sets up the structure for the user input form
|
|
select 'form' as component,
|
|
'Batch update' as title,
|
|
'Update all todos' as contents;
|
|
|
|
-- Create a select input for choosing which todos to update
|
|
-- This allows users to pick multiple todos or all todos for updating
|
|
select
|
|
'select' as type,
|
|
'Update these todos' as label,
|
|
'todos[]' as name,
|
|
true as multiple,
|
|
true as dropdown,
|
|
true as required,
|
|
-- Combine a static "all" option with dynamic options for each todo
|
|
-- This uses JSON functions to build a complex data structure for the UI
|
|
-- The JSON structure is used to set the label, value, and selection state for each option
|
|
-- The generated JSON looks like this:
|
|
-- [{"label":"Update all todos","value":"all","selected":true},{"label":"Todo 1","value":"1","selected":false}]
|
|
jsonb_build_array(jsonb_build_object( -- json_build_object takes a list of key-value pairs and returns a JSON object
|
|
'label', 'Update all todos', -- The label of the option
|
|
'value', 'all', -- The value of the option
|
|
'selected', :todos = '["all"]' or :todos is null -- Pre-select 'all' only if it was previously chosen or if :todos is not set (the page was just loaded)
|
|
)) ||
|
|
-- Generate an option for each todo in the database
|
|
jsonb_agg(jsonb_build_object(
|
|
'label', title,
|
|
'value', id,
|
|
-- Pre-select this todo if it was in the previous selection
|
|
'selected', (id in (select e::int from jsonb_array_elements_text(:todos::jsonb) e where e != 'all'))
|
|
)) as options
|
|
from todos;
|
|
|
|
-- Create a text input for entering a new label
|
|
-- This allows users to specify the label to be added to the selected todos
|
|
select 'new_label' as name, 'New label' as label;
|
|
|
|
-- Create a checkbox for optionally removing existing labels
|
|
-- This gives users the choice to strip old labels before adding a new one
|
|
select 'checkbox' as type, 'Remove previous labels' as label, 'remove_label' as name; |