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
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:
@@ -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.
|
||||
|
||||

|
||||
@@ -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
|
||||
);
|
||||
+31
@@ -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"
|
||||
Reference in New Issue
Block a user