chore: import upstream snapshot with attribution
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

This commit is contained in:
wehub-resource-sync
2026-07-13 12:31:57 +08:00
commit d718c5a372
986 changed files with 74597 additions and 0 deletions
@@ -0,0 +1,21 @@
# TapTempo
This small SQLPage example shows how to :
- save request logs to the database
- display graphs
- make computations on the database
- write a custom component with HTML and CSS
## TapTempo: a webapp to measure the tempo of a song
TapTempo is a webapp that lets you measure the tempo of a song by tapping on a button in rhythm with the music.
It is a simple example of a webapp that stores data in a database, and displays graphs.
### Implementation
At each tap, the webapp sends a request to the server, which stores the timestamp of the tap in the `tap` table.
A [window function](https://www.sqlite.org/windowfunctions.html) is used to compute the tempo of the song from the timestamps of the last two taps.
![taptempo screenshot](screenshot.png)
@@ -0,0 +1,8 @@
services:
web:
image: lovasoa/sqlpage:main
ports:
- "8080:8080"
volumes:
- .:/var/www
- ./sqlpage:/etc/sqlpage
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

@@ -0,0 +1,37 @@
SELECT 'shell' AS component,
'Tap Tempo' as title,
'/' as link,
'en-US' as lang,
'A tool to measure a tempo in bpm by clicking a button in rythm.' as description,
'Vollkorn' as font,
'music' as icon,
'Proudly powered by [SQLPage](https://sql-page.com)' as footer;
SELECT 'hero' as component,
'Tap Tempo' as title,
'Tap Tempo is a tool to **measure a tempo in bpm** by clicking a button in rythm.' as description_md,
'drums by Nana Yaw Otoo.jpg' as image,
sqlpage.link('taptempo.sql', json_object('session', random())) as link,
'Start tapping !' as link_text;
SELECT 'text' as component,
'About TapTempo' as title,
'
## Context
This tool is written in the SQL database query language, and uses the [SQLPage](https://sql-page.com) framework to generate the web interface.
It serves as a demo for the framework.
If what you really want is to measure a tempo, not learn about website building and databases,
you should probably use something else, that does not require a web server and a database to run 😉.
## History
There is a large family of implementations of the tap tempo tool.
It originates from a french linux discussion website, [linuxfr.org](https://linuxfr.org/), where it was implemented in C++ by [mzf](https://linuxfr.org/users/mzf).
[See alternative implementations](https://linuxfr.org/wiki/taptempo).
' as contents_md;
Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

@@ -0,0 +1,19 @@
CREATE TABLE tap(
tapping_session INTEGER,
day REAL NOT NULL, -- fractional julian day, easy to manipulate in SQLite
PRIMARY KEY (tapping_session, day)
);
CREATE VIEW tap_bpm AS
SELECT
*,
CAST(
1 / ((24 * 60) * (day - previous))
AS INTEGER
) AS bpm
FROM (
SELECT
*,
lag(day) OVER (ORDER BY day) AS previous
FROM tap
);
@@ -0,0 +1,31 @@
<a class="bigbutton" href="{{link}}">{{text}}</a>
<style>
.bigbutton {
/* A huge funky round button with a ton of visual effects */
display: block;
margin: auto;
width: 20rem;
height: 20rem;
line-height: 18rem;
font-size: 3rem;
text-align: center;
padding: 0.5em 1em;
border: 2px solid #000;
border-radius: 100%;
box-shadow: 0 0.5em 0.5em -0.4em #eb7f26;
text-decoration: none;
font-weight: bold;
transition: all 0.05s;
background: linear-gradient(to bottom, #ddd44f, #da6a36);
text-shadow: 2px 2px 3px rgba(87, 34, 34, 0.5);
color: black;
}
.bigbutton:hover {
background: linear-gradient(to bottom, #dad161, #e65e20);
transform: scale(1.1);
box-shadow: 0 0.8em 0.7em -0.5em #eb7f26;
text-decoration: none;
}
</style>
@@ -0,0 +1,21 @@
SELECT 'shell' AS component, 'Tap Tempo' as title, 'Vollkorn' as font, 'music' as icon;
-- See https://www.sqlite.org/lang_datefunc.html (unixepoch is not available in the current version of SQLite)
INSERT INTO tap(tapping_session, day) VALUES ($session, julianday('now'));
SELECT 'big_button' as component,
COALESCE(
(SELECT bpm || ' bpm' FROM tap_bpm WHERE tapping_session = $session ORDER BY day DESC LIMIT 1),
'Tap'
) AS text,
sqlpage.link('taptempo.sql', json_object('session', $session)) as link;
SELECT 'chart' as component, 'BPM over time' as title, 'area' as type, 'indigo' as color, 0 AS ymin, 200 AS ymax, 'BPM' as ytitle;
SELECT * FROM (
SELECT
strftime('%H:%M:%f', day) AS x,
bpm AS y
FROM tap_bpm
WHERE tapping_session = $session
ORDER BY day DESC LIMIT 10
) ORDER BY x ASC;
@@ -0,0 +1,22 @@
GET http://localhost:8080/
HTTP 200
[Captures]
start_url: xpath "string(//a[normalize-space()='Start tapping !']/@href)"
[Asserts]
body contains "Tap Tempo is a tool to"
body contains "measure a tempo in bpm"
body contains "About TapTempo"
GET http://localhost:8080/{{start_url}}
HTTP 200
[Captures]
tap_url: xpath "string(//a[normalize-space()='Tap']/@href)"
[Asserts]
body contains "Tap"
body contains "BPM over time"
GET http://localhost:8080/{{tap_url}}
HTTP 200
[Asserts]
body contains " bpm"
body contains "BPM over time"