Skip to content

Commit 36b92a3

Browse files
committed
Prefill fields in record submitter if possible
1 parent 3e3a7c8 commit 36b92a3

9 files changed

Lines changed: 73 additions & 22 deletions

File tree

pointercrate-core-pages/static/js/modules/form.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ export class DynamicSuggestionDropdown extends Dropdown {
133133
constructor(html) {
134134
super(html);
135135

136+
if (this.input.dataset.default !== undefined) {
137+
this.input.value = this.input.dataset.default;
138+
}
136139
this.endpoint = html.dataset.endpoint;
137140
this.field = html.dataset.field;
138141

pointercrate-demonlist-api/src/pages.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use pointercrate_core_api::{
99
error::Result,
1010
response::{Page, Response2},
1111
};
12-
use pointercrate_demonlist::player::claim::PlayerClaim;
12+
use pointercrate_demonlist::player::{claim::PlayerClaim, DatabasePlayer};
1313
use pointercrate_demonlist::player::{FullPlayer, Player};
1414
use pointercrate_demonlist::{
1515
demon::{audit::audit_log_for_demon, current_list, list_at, FullDemon, MinimalDemon},
@@ -110,11 +110,18 @@ pub async fn demon_permalink(demon_id: i32, pool: &State<PointercratePool>) -> R
110110

111111
#[localized]
112112
#[rocket::get("/<position>/")]
113-
pub async fn demon_page(position: i16, pool: &State<PointercratePool>, gd: &State<GeometryDashConnector>) -> Result<Page> {
113+
pub async fn demon_page(
114+
position: i16, auth: Option<Auth<NonMutating>>, pool: &State<PointercratePool>, gd: &State<GeometryDashConnector>,
115+
) -> Result<Page> {
114116
let mut connection = pool.connection().await?;
115117

116118
let full_demon = FullDemon::by_position(position, &mut connection).await?;
117119

120+
let claimed_player = match auth {
121+
Some(auth) => DatabasePlayer::by_user(auth.user.user().id, &mut connection).await?,
122+
None => None,
123+
};
124+
118125
let audit_log = audit_log_for_demon(full_demon.demon.base.id, &mut connection).await?;
119126

120127
let mut addition_time = None;
@@ -161,6 +168,7 @@ pub async fn demon_page(position: i16, pool: &State<PointercratePool>, gd: &Stat
161168
movements: modifications,
162169
integration: gd.load_level_for_demon(&full_demon.demon).await,
163170
data: full_demon,
171+
claimed_player,
164172
}))
165173
}
166174

pointercrate-demonlist-pages/src/account/demons.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ fn change_verifier_dialog() -> Markup {
303303
&tr("demon-verifier-dialog.info"),
304304
&tr("demon-verifier-dialog.submit"),
305305
"verifier",
306+
None,
306307
)
307308
}
308309

@@ -314,6 +315,7 @@ fn change_publisher_dialog() -> Markup {
314315
&tr("demon-publisher-dialog.info"),
315316
&tr("demon-publisher-dialog.submit"),
316317
"publisher",
318+
None,
317319
)
318320
}
319321

@@ -325,6 +327,7 @@ fn add_creator_dialog() -> Markup {
325327
&tr("demon-creator-dialog.info"),
326328
&tr("demon-creator-dialog.submit"),
327329
"creator",
330+
None,
328331
)
329332
}
330333

@@ -370,13 +373,13 @@ fn demon_submitter() -> Markup {
370373
span.form-input.flex.col data-type = "dropdown" {
371374
label{(tr("demon-add-form.verifier-field")) }
372375
br;
373-
(player_selection_dropdown("demon-add-verifier", "/api/v1/players/", "name", "verifier"))
376+
(player_selection_dropdown("demon-add-verifier", "/api/v1/players/", "name", "verifier", None))
374377
p.error {}
375378
}
376379
span.form-input.flex.col data-type = "dropdown" {
377380
label {(tr("demon-add-form.publisher-field")) }
378381
br;
379-
(player_selection_dropdown("demon-add-publisher", "/api/v1/players/", "name", "publisher"))
382+
(player_selection_dropdown("demon-add-publisher", "/api/v1/players/", "name", "publisher", None))
380383
p.error {}
381384
}
382385
span.form-input.flex.col #demon-add-video {

pointercrate-demonlist-pages/src/account/records.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use pointercrate_core_pages::{
1010
};
1111
use pointercrate_demonlist::{
1212
demon::{current_list, Demon},
13+
player::DatabasePlayer,
1314
LIST_HELPER,
1415
};
1516
use pointercrate_user::auth::{AuthenticatedUser, NonMutating};
@@ -43,7 +44,7 @@ impl AccountPageTab for RecordsPage {
4344
}
4445

4546
async fn content(
46-
&self, _user: &AuthenticatedUser<NonMutating>, _permissions: &PermissionsManager, connection: &mut PgConnection,
47+
&self, user: &AuthenticatedUser<NonMutating>, _permissions: &PermissionsManager, connection: &mut PgConnection,
4748
) -> Markup {
4849
let demons = match current_list(connection).await {
4950
Ok(demons) => demons,
@@ -57,9 +58,11 @@ impl AccountPageTab for RecordsPage {
5758
},
5859
};
5960

61+
let player = DatabasePlayer::by_user(user.user().id, connection).await.unwrap_or(None);
62+
6063
html! {
6164
div.left {
62-
(RecordSubmitter::new(false, &demons[..]))
65+
(RecordSubmitter::new(false, &demons[..], player.as_ref(), None))
6366
(record_manager(&demons[..]))
6467
(note_adder())
6568
div.panel.fade #record-notes-container style = "display:none" {
@@ -386,6 +389,7 @@ fn change_holder_dialog() -> Markup {
386389
&tr("record-holder-dialog.info"),
387390
&tr("record-holder-dialog.submit"),
388391
"player",
392+
None,
389393
)
390394
}
391395

@@ -401,7 +405,7 @@ fn change_demon_dialog(demons: &[Demon]) -> Markup {
401405
p {
402406
(tr("record-videolink-dialog.info"))
403407
}
404-
(demon_dropdown("edit-demon-record", demons.iter()))
408+
(demon_dropdown("edit-demon-record", demons.iter(), None))
405409
}
406410
}
407411
}

pointercrate-demonlist-pages/src/components/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ pub mod submitter;
99
pub mod team;
1010
pub mod time_machine;
1111

12-
pub fn demon_dropdown<'a>(dropdown_id: &str, demons: impl Iterator<Item = &'a Demon>) -> Markup {
12+
pub fn demon_dropdown<'a>(dropdown_id: &str, demons: impl Iterator<Item = &'a Demon>, initial_demon: Option<i16>) -> Markup {
1313
html! {
1414
div.dropdown-menu.js-search #(dropdown_id) {
1515
div {
16-
input type = "text" name = "demon" required="" autocomplete="off";
16+
input type = "text" name = "demon" required="" autocomplete="off" data-default=[initial_demon];
1717
}
1818
div.menu {
1919
ul {
@@ -26,11 +26,13 @@ pub fn demon_dropdown<'a>(dropdown_id: &str, demons: impl Iterator<Item = &'a De
2626
}
2727
}
2828

29-
pub fn player_selection_dropdown(dropdown_id: &str, endpoint: &str, field: &str, form_field: &str) -> Markup {
29+
pub fn player_selection_dropdown(
30+
dropdown_id: &str, endpoint: &str, field: &str, form_field: &str, initial_player: Option<&DatabasePlayer>,
31+
) -> Markup {
3032
html! {
3133
div.dropdown-menu #(dropdown_id) data-endpoint = (endpoint) data-field = (field) {
3234
div {
33-
input type = "text" name = (form_field) required="" autocomplete="off" placeholder = (tr("record-submission.holder-input-placeholder"));
35+
input type = "text" name = (form_field) required="" autocomplete="off" placeholder = (tr("record-submission.holder-input-placeholder")) data-default=[initial_player.map(|p| &p.name)];
3436
}
3537
div.menu {
3638
// dynamically populated once the user starts typing
@@ -42,6 +44,7 @@ pub fn player_selection_dropdown(dropdown_id: &str, endpoint: &str, field: &str,
4244

4345
pub fn player_selection_dialog(
4446
dialog_id: &str, dropdown_id: &str, headline: &str, description: &str, button_text: &str, form_field: &str,
47+
initial_player: Option<&DatabasePlayer>,
4548
) -> Markup {
4649
html! {
4750
div.overlay.closable {
@@ -55,7 +58,7 @@ pub fn player_selection_dialog(
5558
(description)
5659
}
5760
span.form-input.flex.col data-type = "dropdown" {
58-
(player_selection_dropdown(dropdown_id, "/api/v1/players/", "name", form_field))
61+
(player_selection_dropdown(dropdown_id, "/api/v1/players/", "name", form_field, initial_player))
5962
p.error {}
6063
}
6164
input.button.blue.hover type = "submit" style = "margin: 15px auto 0px;" value = (button_text);

pointercrate-demonlist-pages/src/components/submitter.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,31 @@ use crate::components::{demon_dropdown, player_selection_dropdown};
22
use maud::{html, Markup, Render};
33
use pointercrate_core::{localization::tr, trp};
44
use pointercrate_core_pages::trp_html;
5-
use pointercrate_demonlist::{config, demon::Demon};
5+
use pointercrate_demonlist::{config, demon::Demon, player::DatabasePlayer};
66

7-
pub struct RecordSubmitter<'a> {
7+
pub struct RecordSubmitter<'d, 'p> {
88
initially_visible: bool,
9-
demons: &'a [Demon],
9+
demons: &'d [Demon],
10+
initial_demon: Option<i16>,
11+
initial_holder: Option<&'p DatabasePlayer>,
1012
}
1113

12-
impl<'a> RecordSubmitter<'a> {
13-
pub fn new(visible: bool, demons: &'a [Demon]) -> RecordSubmitter<'a> {
14+
impl<'d, 'p> RecordSubmitter<'d, 'p> {
15+
/// * `visible` - Show the record submitter.
16+
/// * `demons` - The Demonlist.
17+
/// * `holder` - Player to preselect as the record holder. `None` to not preselect a player.
18+
/// * `demon` - Position of the demon in the demonlist to preselect. `None` to not preselect a demon.
19+
pub fn new(visible: bool, demons: &'d [Demon], holder: Option<&'p DatabasePlayer>, demon: Option<i16>) -> RecordSubmitter<'d, 'p> {
1420
RecordSubmitter {
1521
initially_visible: visible,
1622
demons,
23+
initial_demon: demon,
24+
initial_holder: holder,
1725
}
1826
}
1927
}
2028

21-
impl Render for RecordSubmitter<'_> {
29+
impl Render for RecordSubmitter<'_, '_> {
2230
fn render(&self) -> Markup {
2331
html! {
2432
section.panel.fade.closable #submitter style=(if !self.initially_visible {"display:none"} else {""}) {
@@ -36,7 +44,7 @@ impl Render for RecordSubmitter<'_> {
3644
(trp!("record-submission.demon-info", "list-size" = config::extended_list_size()))
3745
}
3846
span.form-input data-type = "dropdown" {
39-
(demon_dropdown("id_demon", self.demons.iter().filter(|demon| demon.base.position <= config::extended_list_size())))
47+
(demon_dropdown("id_demon", self.demons.iter().filter(|demon| demon.base.position <= config::extended_list_size()), self.initial_demon))
4048
p.error {}
4149
}
4250
h3 {
@@ -46,7 +54,7 @@ impl Render for RecordSubmitter<'_> {
4654
(tr("record-submission.holder-info"))
4755
}
4856
span.form-input.flex.col data-type = "dropdown" {
49-
(player_selection_dropdown("id_player", "/api/v1/players/", "name", "player"))
57+
(player_selection_dropdown("id_player", "/api/v1/players/", "name", "player", self.initial_holder))
5058
p.error {}
5159
}
5260
h3 {

pointercrate-demonlist-pages/src/demon_page.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use chrono::NaiveDateTime;
1010
use maud::{html, Markup, PreEscaped};
1111
use pointercrate_core::{localization::tr, trp};
1212
use pointercrate_core_pages::{head::HeadLike, trp_html, PageFragment};
13+
use pointercrate_demonlist::player::DatabasePlayer;
1314
use pointercrate_demonlist::{
1415
config::{self as list_config, extended_list_size},
1516
demon::{Demon, FullDemon},
@@ -29,6 +30,7 @@ pub struct DemonPage {
2930
pub data: FullDemon,
3031
pub movements: Vec<DemonMovement>,
3132
pub integration: Option<IntegrationLevel>,
33+
pub claimed_player: Option<DatabasePlayer>,
3234
}
3335

3436
impl From<DemonPage> for PageFragment {
@@ -145,12 +147,18 @@ impl DemonPage {
145147
}
146148
}
147149

150+
let demon = self
151+
.demonlist
152+
.iter()
153+
.position(|d| d.base.id == self.data.demon.base.id)
154+
.map(|i| i as i16 + 1);
155+
148156
html! {
149157
(dropdowns)
150158

151159
div.flex.m-center.container {
152160
main.left {
153-
(RecordSubmitter::new(false, &self.demonlist))
161+
(RecordSubmitter::new(false, &self.demonlist, self.claimed_player.as_ref(), demon))
154162
(self.demon_panel())
155163
div.panel.fade.js-scroll-anim.js-collapse data-anim = "fade" {
156164
h2.underlined.pad {

pointercrate-demonlist-pages/src/overview.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl OverviewPage {
9797
div.flex.m-center.container {
9898
main.left {
9999
(self.time_machine)
100-
(RecordSubmitter::new(self.submitter_initially_visible, &self.demonlist))
100+
(RecordSubmitter::new(self.submitter_initially_visible, &self.demonlist, self.claimed_player.as_ref().map(|p| &p.player.base), None))
101101

102102
@match &self.time_machine {
103103
Tardis::Activated { demons, ..} => {

pointercrate-demonlist/src/player/get.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,20 @@ impl DatabasePlayer {
114114
result => result,
115115
}
116116
}
117+
118+
pub async fn by_user(user_id: i32, connection: &mut PgConnection) -> Result<Option<DatabasePlayer>> {
119+
sqlx::query_as!(
120+
DatabasePlayer,
121+
"SELECT players.id, players.name, players.banned FROM players
122+
JOIN player_claims ON player_claims.player_id = players.id
123+
JOIN members ON members.member_id = player_claims.member_id
124+
WHERE members.member_id = $1",
125+
user_id
126+
)
127+
.fetch_optional(connection)
128+
.await
129+
.map_err(DemonlistError::from)
130+
}
117131
}
118132

119133
#[cfg(test)]

0 commit comments

Comments
 (0)