Skip to content

Giveaway dashboard: scheduling, deletion, history, preview and names - #62

Merged
Musiker15 merged 7 commits into
mainfrom
feat/giveaway-dashboard-v2
Oct 28, 2026
Merged

Musiker15 merged 7 commits into
mainfrom
feat/giveaway-dashboard-v2

Conversation

@Musiker15

Copy link
Copy Markdown
Member

Connects the giveaway dashboard to the new endpoints of the giveaway bot (MSK-Scripts/discord_giveawaybot#20).

Dashboard

  • Server switcher shows the server's name and icon from /guild instead of "Server ".
  • Winners show name and avatar with the id beside them, or the id alone where the bot has no name. Avatars only load from https://cdn.discordapp.com.
  • Scheduled giveaways: optional start in the create form (datetime-local, sent with the browser's offset), status badge, filter tab, overview tile with the next start. Editing a scheduled one only sends start and duration when they changed. Running-only actions are never offered.
  • Delete for ended, cancelled and scheduled giveaways, on the detail page, through ConfirmDialog. When coupon codes were handed out the dialog warns that they stay valid.
  • Activity card on the overview: created, ended and entries per day over 30 or 90 days, three small SVG charts on one time axis, with a sentence and a table carrying the same numbers.
  • Live preview of the post beside the form, built by the bot, debounced. Discord markup is parsed into a small tree and rendered as React text, no dangerouslySetInnerHTML.

API routes

  • Data route allows guild and history. days is 30 or 90, a giveaway id has to match the bot's shape.
  • Action route allows delete and preview. The delete id is checked against the same shape, the preview language against the bot's languages. Guild and user still come from the signed session.
  • After the bot confirms a deletion, the shop removes the public result page of that one giveaway, scoped to the session's guild (lib/giveawayResults.ts). The bot's guild-wide delete route uses the same helper.
  • CSP unchanged, img-src already allowed the Discord CDN.

Public stats and landing page

  • Scheduled giveaways get their own entry in the status breakdown and are not counted as running or ended. Average entries count started giveaways only.
  • The giveaway bot page lists "Scheduled Start" in both languages.

Older bot

Each feature checks its own answer, there is no version flag. Until the bot is deployed the new routes answer 404 and the dashboard looks as it does today.

Checks

tsc, eslint, vitest (1468 tests, 32 new route and stats tests), npm run build. Every new rule was counter-checked by breaking it. Screenshots at 375, 1440 and 3440 px in light and dark, against the new and the old bot API: no overflow, no console errors, no target under 44 px.

…I routes

The giveaway bot gains a guild endpoint, a daily history, a message preview
and a delete action (MSK-Scripts/discord_giveawaybot#20). The two dashboard
routes only pass on what they list, so the new kinds and actions are added
there with the same care as the old ones: the guild comes from the signed
session, the history range is one of 30 or 90 days, a giveaway id has the
bot's shape and the preview language is one the bot speaks.

A deletion also removes the public result page of that one giveaway. The
shop does this itself, after the bot confirmed, and only within the
session's guild, so an id from the client can never reach the page of
another server. The delete logic moves into lib/giveawayResults.ts, which
the bot's own guild-wide route now uses too.

The public statistics read the bot's database directly. A scheduled giveaway
is neither running nor over, so it gets its own entry in the status
breakdown and no longer pulls down the average entries per giveaway.
…names

Connects the dashboard to the bot's scheduling release
(MSK-Scripts/discord_giveawaybot#20). The parts share the model, the
provider and the translation table, which is why they land together:

- The server switcher shows the server's name and icon from /guild instead
  of "Server <id>". The provider now wraps the shell so the shell can read
  it, and only a guild answer for the session's server is used.
- Winners show the name and avatar the bot stored at the draw, the id
  beside the name, and the id alone where there is no name. The detail page
  asks the bot for that one giveaway, which also fills in older names.
- Scheduled giveaways: an optional start in the create form (native
  datetime-local, read in the browser's zone and sent with its offset), a
  status badge, a filter tab and an overview tile of their own, and an edit
  form with start and duration. Start and duration are only sent when they
  changed, so a title fix right before the start is not refused. A
  scheduled giveaway offers cancel, never the actions of a running one.
- Delete for ended, cancelled and scheduled giveaways, through
  ConfirmDialog. The dialog says what goes and warns when coupon codes were
  handed out, since they stay valid and can no longer be revoked. The
  ConfirmDialog gained a notice slot for that warning.
- An activity chart on the overview: created, ended and entries per day over
  30 or 90 days as three small SVG charts on one time axis instead of a dual
  axis, with a sentence and a table that say the same.
- A live preview of the post beside the form, built by the bot from the
  form, debounced and cancelled on new input. Discord markup is read into a
  small tree and rendered as React text: timestamps through lib/format.ts,
  mentions with the loaded role and channel names, custom emoji by name.
  Nothing from the embed is ever turned into HTML.

Until the bot is deployed it answers the new routes with 404 and sends none
of the new fields. Each feature checks its own answer: no /guild keeps the
id, no /history no chart, a 404 from the preview no preview, no couponsIssued
no delete, and no startAt on the giveaways (or a preview answer) no start
field. No version flag is involved.
The bot can now post a giveaway at a chosen time, set up in the web
dashboard. The feature list says so in both languages, at the same place in
each, so the lists stay the same length and order.
The giveaway dashboard brings a second hand-written chart, so DESIGN.md now
says how charts are built here: SVG without a library because of the nonce
CSP, one scale per chart, small charts on one time axis instead of a second
y-axis, and a sentence plus a table for everything the bars show. The
server switcher row and the ConfirmDialog row name their new parts.
Rebuilt with one AST worker, as the parallel pool drops TypeScript files
under Python 3.14.
Beside the form on a wide screen the preview stuck 16 px from the top of
the viewport, under the dashboard's sticky top bar, which hid its heading.
It now sticks below the bar, by the same measure the sidebar uses.
The shell test handed its content in as the children prop, which the lint
rule react/no-children-prop refuses.
@strix-security

Copy link
Copy Markdown

Strix is installed on this repository, but we couldn't run this PR security review because this workspace's trial has ended. Add a card to resume code reviews here.

So far, Strix has reviewed 50 pull requests and surfaced 1 security issue across this workspace.

@github-actions

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-code-quality

Copy link
Copy Markdown

Code coverage overview

Languages: TypeScript

TypeScript / code-coverage/vitest

main b424eb0 feat/giveaway-dashbo... 768ff52 +/-
71% 72% +1%
View coverage of the 4 most impacted files.
File main b424eb0 feat/giveaway-dashbo... 768ff52 +/-
lib/format.ts 100% 100% 0%
lib/giveawaySession.ts 97% 97% 0%
lib/giveawayStats.ts 0% 100% +100%
lib/giveawayResults.ts 0% 100% +100%

ℹ️ Calculations represent line coverage. Results may change as calculations are updated.

@Musiker15
Musiker15 merged commit 9d3ebbb into main Oct 28, 2026
11 checks passed
@Musiker15
Musiker15 deleted the feat/giveaway-dashboard-v2 branch October 28, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant