From 289f681e8288b5a12ff7017f93be2a40c2a99c38 Mon Sep 17 00:00:00 2001 From: lovasoa Date: Fri, 13 Sep 2024 22:12:51 +0200 Subject: [PATCH] add a detailed example of the usage of multi-select fields with many comments --- .../todo application (PostgreSQL)/batch.sql | 98 +++++++++++++++++++ .../todo application (PostgreSQL)/shell.sql | 1 + 2 files changed, 99 insertions(+) create mode 100644 examples/todo application (PostgreSQL)/batch.sql diff --git a/examples/todo application (PostgreSQL)/batch.sql b/examples/todo application (PostgreSQL)/batch.sql new file mode 100644 index 00000000..28e6d4b2 --- /dev/null +++ b/examples/todo application (PostgreSQL)/batch.sql @@ -0,0 +1,98 @@ +-- 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; \ No newline at end of file diff --git a/examples/todo application (PostgreSQL)/shell.sql b/examples/todo application (PostgreSQL)/shell.sql index 0701c89c..3a1e9bd4 100644 --- a/examples/todo application (PostgreSQL)/shell.sql +++ b/examples/todo application (PostgreSQL)/shell.sql @@ -1,6 +1,7 @@ select 'shell' as component, format ('Todo list (%s)', count(*)) as title, + 'batch' as menu_item, 'timeline' as menu_item from todos; \ No newline at end of file