Skip to content

Commit 67d2979

Browse files
committed
Merge branch 'main' into oidc
2 parents 845b39b + 8017ecd commit 67d2979

File tree

13 files changed

+157
-37
lines changed

13 files changed

+157
-37
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
- Update default chart colors and text shadows for better readability with all themes
66
- Optimize memory layout by boxing large structs. Slightly reduces memory usage.
77
- New example: [Rich text editor](./examples/rich-text-editor/). Let your users safely write formatted text with links and images.
8+
- Update the Tabler CSS library to [v1.2](https://tabler.io/changelog#/changelog/tabler-1.2). This fixes issues with
9+
- the alignment inside chart tooltips
10+
- the display of lists
811

912
## v0.34 (2025-03-23)
1013

Cargo.lock

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sqlpage"
3-
version = "0.34.0"
3+
version = "0.35.0"
44
edition = "2021"
55
description = "Build data user interfaces entirely in SQL. A web server that takes .sql files and formats the query result using pre-made configurable professional-looking components."
66
keywords = ["web", "sql", "framework"]

examples/official-site/sqlpage/migrations/01_documentation.sql

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,7 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
770770
('sort', 'Make the columns clickable to let the user sort by the value contained in the column.', 'BOOLEAN', TRUE, TRUE),
771771
('search', 'Add a search bar at the top of the table, letting users easily filter table rows by value.', 'BOOLEAN', TRUE, TRUE),
772772
('initial_search_value', 'Pre-fills the search bar used to filter the table. The user will still be able to edit the value to display table rows that will initially be filtered out.', 'TEXT', TRUE, TRUE),
773+
('search_placeholder', 'Customizes the placeholder text shown in the search input field. Replaces the default "Search..." with text that better describes what users should search for.', 'TEXT', TRUE, TRUE),
773774
('markdown', 'Set this to the name of a column whose content should be interpreted as markdown . Used to display rich text with links in the table. This argument can be repeated multiple times to intepret multiple columns as markdown.', 'TEXT', TRUE, TRUE),
774775
('icon', 'Set this to the name of a column whose content should be interpreted as a tabler icon name. Used to display icons in the table. This argument can be repeated multiple times to intepret multiple columns as icons. Introduced in v0.8.0.', 'TEXT', TRUE, TRUE),
775776
('align_right', 'Name of a column the contents of which should be right-aligned. This argument can be repeated multiple times to align multiple columns to the right. Introduced in v0.15.0.', 'TEXT', TRUE, TRUE),
@@ -801,9 +802,11 @@ INSERT INTO example(component, description, properties) VALUES
801802
('table', 'The most basic table.',
802803
json('[{"component":"table"}, {"a": 1, "b": 2}, {"a": 3, "b": 4}]')),
803804
('table', 'A table of users with filtering and sorting.',
804-
json('[{"component":"table", "sort":true, "search":true}, '||
805-
'{"First Name": "Ophir", "Last Name": "Lojkine", "Pseudonym": "lovasoa"},' ||
806-
'{"First Name": "Linus", "Last Name": "Torvalds", "Pseudonym": "torvalds"}]')),
805+
json('[
806+
{"component":"table", "sort":true, "search":true, "search_placeholder": "Filter by name"},
807+
{"First Name": "Ophir", "Last Name": "Lojkine", "Pseudonym": "lovasoa"},
808+
{"First Name": "Linus", "Last Name": "Torvalds", "Pseudonym": "torvalds"}
809+
]')),
807810
('table', 'A table that uses markdown to display links',
808811
json('[{"component":"table", "markdown": "Name", "icon": "icon", "search": true}, '||
809812
'{"icon": "table", "name": "[Table](?component=table)", "description": "Displays SQL results as a searchable table.", "_sqlpage_color": "red"},
@@ -835,8 +838,12 @@ Numbers can be displayed
835838
'table',
836839
'A table with some presentation options',
837840
json(
838-
'[{"component":"table", "hover": true, "striped_rows": true, "description": "Some Star Trek Starfleet starships", "small": true, "initial_search_value": "NCC-" },'||
839-
'{"name": "USS Enterprise", "registry": "NCC-1701-C", "class":"Ambassador"},
841+
'[{"component":"table",
842+
"hover": true, "striped_rows": true,
843+
"description": "Some Star Trek Starfleet starships",
844+
"small": true, "initial_search_value": "NCC-"
845+
},
846+
{"name": "USS Enterprise", "registry": "NCC-1701-C", "class":"Ambassador"},
840847
{"name": "USS Archer", "registry": "NCC-44278", "class":"Archer"},
841848
{"name": "USS Endeavour", "registry": "NCC-06", "class":"Columbia"},
842849
{"name": "USS Constellation", "registry": "NCC-1974", "class":"Constellation"},
@@ -1174,6 +1181,8 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
11741181
('fixed_top_menu', 'Fixes the top bar with menu at the top (the top bar remains visible when scrolling long pages).', 'BOOLEAN', TRUE, TRUE),
11751182
('search_target', 'When this is set, a search field will appear in the top navigation bar, and load the specified sql file with an URL parameter named "search" when the user searches something.', 'TEXT', TRUE, TRUE),
11761183
('search_value', 'This value will be placed in the search field when "search_target" is set. Using the "$search" query parameter value will mirror the value that the user has searched for.', 'TEXT', TRUE, TRUE),
1184+
('search_placeholder', 'Customizes the placeholder text shown in the search input field. Replaces the default "Search" with text that better describes what users should search for.', 'TEXT', TRUE, TRUE),
1185+
('search_button', 'Customizes the text displayed on the search button. Replaces the default "Search" label with custom text that may better match your applications terminology or language.', 'TEXT', TRUE, TRUE),
11771186
('norobot', 'Forbids robots to save this page in their database and follow the links on this page. This will prevent this page to appear in Google search results for any query, for instance.', 'BOOLEAN', TRUE, TRUE),
11781187
('font', 'Specifies the font to be used for displaying text, which can be a valid font name from fonts.google.com or the path to a local WOFF2 font file starting with a slash (e.g., "/fonts/MyLocalFont.woff2").', 'TEXT', TRUE, TRUE),
11791188
('font_size', 'Font size on the page, in pixels. Set to 18 by default.', 'INTEGER', TRUE, TRUE),

examples/official-site/sqlpage/migrations/09_redirect.sql

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,38 @@ INSERT INTO component (name, description, icon, introduced_in_version)
22
VALUES (
33
'redirect',
44
'Redirects the user to another page.
5-
This component is useful for implementing redirects after a form submission,
6-
or to redirect users to a login page if they are not logged in.
7-
8-
Contrary to the http_header component, this component completely stops the execution of the page after it is called,
9-
so it is suitable to use to hide sensitive information from users that are not logged in, for example.
105
11-
Since it uses an HTTP header to redirect the user, it is not possible to use this component after the page has started being sent to the browser.',
6+
This component helps you:
7+
1. Send users to a different page
8+
1. Stop execution of the current page
9+
10+
### Conditional logic
11+
12+
There is no `IF` statement in SQL. Even when you use a [`CASE` expression](https://modern-sql.com/caniuse/case_(simple)), all branches are always evaluated (and only one is returned).
13+
14+
To conditionally execute a component or a [SQLPage function](/functions.sql), you can use the `redirect` component.
15+
A common use case is error handling. You may want to proceed with the rest of a page only when certain pre-conditions are met.
16+
17+
```sql
18+
SELECT
19+
''redirect'' AS component,
20+
''error_page.sql'' AS link
21+
WHERE NOT your_condition;
22+
23+
-- The rest of the page is only executed if the condition is true
24+
```
25+
### Technical limitation
26+
27+
You must use this component **at the beginning of your SQL file**, before any other components that might send content to the browser.
28+
Since the component needs to tell the browser to go to a different page by sending an *HTTP header*,
29+
it will fail if the HTTP headers have already been sent by the time it is executed.
30+
31+
> **Important difference from [http_header](?component=http_header)**
32+
>
33+
> This component completely stops the page from running after it''s called.
34+
> This makes it a good choice for protecting sensitive information from unauthorized users.
35+
36+
',
1237
'arrow-right',
1338
'0.7.2'
1439
);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
INSERT INTO component(name, icon, description, introduced_in_version) VALUES
2+
('empty_state', 'info-circle', 'Displays a large placeholder message to communicate a single information to the user and invite them to take action.
3+
4+
Typically includes a title, an optional icon/image, descriptive text (rich text formatting and images supported via Markdown), and a call-to-action button.
5+
6+
Ideal for first-use screens, empty data sets, "no results" pages, or error messages.', '0.35.0');
7+
8+
INSERT INTO parameter(component, name, description, type, top_level, optional) SELECT 'empty_state', * FROM (VALUES
9+
('title','Description of the empty state.','TEXT',TRUE,FALSE),
10+
('header','Text displayed on the top of the empty state.','TEXT',TRUE,TRUE),
11+
('icon','Name of an icon to be displayed on the top of the empty state.','ICON',TRUE,TRUE),
12+
('image','The URL (absolute or relative) of an image to display at the top of the empty state.','URL',TRUE,TRUE),
13+
('description','A short text displayed below the title.','TEXT',TRUE,TRUE),
14+
('link_text','The text displayed on the button.','TEXT',TRUE,FALSE),
15+
('link_icon','Name of an icon to be displayed on the left side of the button.','ICON',TRUE,FALSE),
16+
('link','The URL to which the button should navigate when clicked.','URL',TRUE,FALSE),
17+
('class','Class attribute added to the container in HTML. It can be used to apply custom styling to this item through css.','TEXT',TRUE,TRUE),
18+
('id','ID attribute added to the container in HTML. It can be used to target this item through css or for scrolling to this item through links (use "#id" in link url).','TEXT',TRUE,TRUE)
19+
) x;
20+
21+
INSERT INTO example(component, description, properties) VALUES
22+
('empty_state', '
23+
This example shows how to create a 404-style "Not Found" empty state with
24+
- a prominent header displaying "404",
25+
- a helpful description suggesting to adjust search parameters, and
26+
- a "Search again" button with a search icon that links back to the search page.
27+
',
28+
json('[{
29+
"component": "empty_state",
30+
"title": "No results found",
31+
"header": "404",
32+
"description": "Try adjusting your search or filter to find what you''re looking for.",
33+
"link_text": "Search again",
34+
"link_icon": "search",
35+
"link": "#not-found",
36+
"id": "not-found"
37+
}]')),
38+
('empty_state', '
39+
It''s possible to use an icon or an image to illustrate the problem.
40+
',
41+
json('[{
42+
"component": "empty_state",
43+
"title": "A critical problem has occurred",
44+
"icon": "mood-wrrr",
45+
"description_md": "SQLPage can do a lot of things, but this is not one of them.
46+
47+
Please restart your browser and **cross your fingers**.",
48+
"link_text": "Close and restart",
49+
"link_icon": "rotate-clockwise",
50+
"link": "#"
51+
}]'));
52+

sqlpage/sqlpage.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
/* !include https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/css/tabler.min.css */
2-
/* !include https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/css/tabler-vendors.min.css */
1+
/* !include https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/css/tabler.min.css */
2+
/* !include https://cdn.jsdelivr.net/npm/[email protected]/dist/css/tom-select.bootstrap5.css */
3+
/* !include https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/css/tabler-vendors.min.css */
34

45
:root {
56
/* Workaround for https://github.com/tabler/tabler/issues/1879 */

sqlpage/sqlpage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* !include https://cdn.jsdelivr.net/npm/@tabler/core@1.0.0/dist/js/tabler.min.js */
1+
/* !include https://cdn.jsdelivr.net/npm/@tabler/core@1.2.0/dist/js/tabler.min.js */
22
const nonce = document.currentScript.nonce;
33

44
function sqlpage_card() {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<div class="empty{{#if class}} {{class}}{{/if}}"{{#if id}} id="{{id}}"{{/if}}>
2+
{{#if header}}
3+
<div class="empty-header">{{header}}</div>
4+
{{else}}
5+
{{#if icon}}
6+
<div class="empty-icon">
7+
<span>{{icon_img icon }}</span>
8+
</div>
9+
{{else}}
10+
{{#if image}}
11+
<div class="empty-img"><img src="{{image}}" height="128" alt="{{image}}"/></div>
12+
{{/if}}
13+
{{/if}}
14+
{{/if}}
15+
<p class="empty-title">{{title}}</p>
16+
<div class="empty-subtitle text-secondary remove-bottom-margin">
17+
{{~#if description}}<p>{{description}}</p>{{/if~}}
18+
{{~#if description_md~}}
19+
{{{markdown description_md}}}
20+
{{~/if~}}
21+
</div>
22+
23+
<div class="empty-action">
24+
<a href="{{link}}" class="btn btn-primary">
25+
<span class="me-1">{{icon_img link_icon}}</span>
26+
{{link_text}}
27+
</a>
28+
</div>
29+
</div>

sqlpage/templates/list.handlebars

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<div class="row align-items-center m-0">
1212
{{#if link}}<a href="{{link}}"
1313
{{~else}}<div {{/if}}
14-
class="col row align-items-center text-decoration-none link-body-emphasis m-0 {{#if ../compact}}p-1{{else}}p-3{{/if}}">
14+
class="col row align-items-center text-decoration-none text-body m-0 {{#if ../compact}}p-1{{else}}p-3{{/if}}">
1515
{{#if color}}
1616
<div class="col-auto"><span class="badge bg-{{color}}"></span></div>
1717
{{/if}}
@@ -48,7 +48,7 @@
4848

4949
{{#if delete_link}}
5050
<form method="POST" action="{{delete_link}}" class="col-auto m-0 p-0">
51-
<button type="submit" class="btn btn-link link-secondary p-0 border-0" title="Delete">
51+
<button type="submit" class="btn btn-link link-secondary p-0 border-0 bg-transparent" title="Delete">
5252
{{~icon_img 'trash'~}}
5353
</button>
5454
</form>

0 commit comments

Comments
 (0)