Skip to content

Commit d1c7351

Browse files
Dan product notifications (#1524)
1 parent cabbfa5 commit d1c7351

File tree

24 files changed

+739
-77
lines changed

24 files changed

+739
-77
lines changed

pgml-dashboard/src/api/deployment/deployment_models.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rocket::route::Route;
22
use sailfish::TemplateOnce;
33

44
use crate::{
5+
guards::Cluster,
56
guards::ConnectedCluster,
67
responses::{Error, ResponseOk},
78
};
@@ -17,8 +18,8 @@ use std::collections::HashMap;
1718

1819
// Returns models page
1920
#[get("/models")]
20-
pub async fn deployment_models(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error> {
21-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
21+
pub async fn deployment_models(cluster: &Cluster) -> Result<ResponseOk, Error> {
22+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
2223
layout.breadcrumbs(vec![NavLink::new("Models", &urls::deployment_models()).active()]);
2324

2425
let tabs = vec![tabs::Tab {
@@ -28,16 +29,16 @@ pub async fn deployment_models(cluster: ConnectedCluster<'_>) -> Result<Response
2829

2930
let nav_tabs = tabs::Tabs::new(tabs, Some("Models"), Some("Models"))?;
3031

31-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
32+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
3233
}
3334

3435
// Returns models page
3536
#[get("/models/<model_id>")]
36-
pub async fn model(cluster: ConnectedCluster<'_>, model_id: i64) -> Result<ResponseOk, Error> {
37+
pub async fn model(cluster: &Cluster, model_id: i64) -> Result<ResponseOk, Error> {
3738
let model = models::Model::get_by_id(cluster.pool(), model_id).await?;
3839
let project = models::Project::get_by_id(cluster.pool(), model.project_id).await?;
3940

40-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
41+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
4142
layout.breadcrumbs(vec![
4243
NavLink::new("Models", &urls::deployment_models()),
4344
NavLink::new(&project.name, &urls::deployment_project_by_id(project.id)),
@@ -51,7 +52,7 @@ pub async fn model(cluster: ConnectedCluster<'_>, model_id: i64) -> Result<Respo
5152

5253
let nav_tabs = tabs::Tabs::new(tabs, Some("Models"), Some("Models"))?;
5354

54-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
55+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
5556
}
5657

5758
#[get("/models_turboframe")]

pgml-dashboard/src/api/deployment/notebooks.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::utils::urls;
2020

2121
// Returns notebook page
2222
#[get("/notebooks")]
23-
pub async fn notebooks(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error> {
24-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
23+
pub async fn notebooks(cluster: &Cluster) -> Result<ResponseOk, Error> {
24+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
2525
layout.breadcrumbs(vec![NavLink::new("Notebooks", &urls::deployment_notebooks()).active()]);
2626

2727
let tabs = vec![tabs::Tab {
@@ -31,15 +31,15 @@ pub async fn notebooks(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Erro
3131

3232
let nav_tabs = tabs::Tabs::new(tabs, Some("Notebooks"), Some("Notebooks"))?;
3333

34-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
34+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
3535
}
3636

3737
// Returns the specified notebook page.
3838
#[get("/notebooks/<notebook_id>")]
39-
pub async fn notebook(cluster: ConnectedCluster<'_>, notebook_id: i64) -> Result<ResponseOk, Error> {
39+
pub async fn notebook(cluster: &Cluster, notebook_id: i64) -> Result<ResponseOk, Error> {
4040
let notebook = models::Notebook::get_by_id(cluster.pool(), notebook_id).await?;
4141

42-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
42+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
4343
layout.breadcrumbs(vec![
4444
NavLink::new("Notebooks", &urls::deployment_notebooks()),
4545
NavLink::new(notebook.name.as_str(), &urls::deployment_notebook_by_id(notebook_id)).active(),
@@ -52,7 +52,7 @@ pub async fn notebook(cluster: ConnectedCluster<'_>, notebook_id: i64) -> Result
5252

5353
let nav_tabs = tabs::Tabs::new(tabs, Some("Notebooks"), Some("Notebooks"))?;
5454

55-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
55+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
5656
}
5757

5858
// Returns all the notebooks for a deployment in a turbo frame.

pgml-dashboard/src/api/deployment/projects.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rocket::route::Route;
22
use sailfish::TemplateOnce;
33

44
use crate::{
5+
guards::Cluster,
56
guards::ConnectedCluster,
67
responses::{Error, ResponseOk},
78
};
@@ -15,8 +16,8 @@ use crate::utils::urls;
1516

1617
// Returns the deployments projects page.
1718
#[get("/projects")]
18-
pub async fn projects(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error> {
19-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
19+
pub async fn projects(cluster: &Cluster) -> Result<ResponseOk, Error> {
20+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
2021
layout.breadcrumbs(vec![NavLink::new("Projects", &urls::deployment_projects()).active()]);
2122

2223
let tabs = vec![tabs::Tab {
@@ -26,15 +27,15 @@ pub async fn projects(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error
2627

2728
let nav_tabs = tabs::Tabs::new(tabs, Some("Notebooks"), Some("Projects"))?;
2829

29-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
30+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
3031
}
3132

3233
// Return the specified project page.
3334
#[get("/projects/<project_id>")]
34-
pub async fn project(cluster: ConnectedCluster<'_>, project_id: i64) -> Result<ResponseOk, Error> {
35+
pub async fn project(cluster: &Cluster, project_id: i64) -> Result<ResponseOk, Error> {
3536
let project = models::Project::get_by_id(cluster.pool(), project_id).await?;
3637

37-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
38+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
3839
layout.breadcrumbs(vec![
3940
NavLink::new("Projects", &urls::deployment_projects()),
4041
NavLink::new(project.name.as_str(), &urls::deployment_project_by_id(project_id)).active(),
@@ -47,7 +48,7 @@ pub async fn project(cluster: ConnectedCluster<'_>, project_id: i64) -> Result<R
4748

4849
let nav_tabs = tabs::Tabs::new(tabs, Some("Projects"), Some("Projects"))?;
4950

50-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
51+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
5152
}
5253

5354
// Returns all the deployments for the project in a turbo frame.

pgml-dashboard/src/api/deployment/snapshots.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rocket::route::Route;
22
use sailfish::TemplateOnce;
33

44
use crate::{
5+
guards::Cluster,
56
guards::ConnectedCluster,
67
responses::{Error, ResponseOk},
78
};
@@ -16,8 +17,8 @@ use std::collections::HashMap;
1617

1718
// Returns snapshots page
1819
#[get("/snapshots")]
19-
pub async fn snapshots(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error> {
20-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
20+
pub async fn snapshots(cluster: &Cluster) -> Result<ResponseOk, Error> {
21+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
2122
layout.breadcrumbs(vec![NavLink::new("Snapshots", &urls::deployment_snapshots()).active()]);
2223

2324
let tabs = vec![tabs::Tab {
@@ -27,15 +28,15 @@ pub async fn snapshots(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Erro
2728

2829
let nav_tabs = tabs::Tabs::new(tabs, Some("Snapshots"), Some("Snapshots"))?;
2930

30-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
31+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
3132
}
3233

3334
// Returns the specific snapshot page
3435
#[get("/snapshots/<snapshot_id>")]
35-
pub async fn snapshot(cluster: ConnectedCluster<'_>, snapshot_id: i64) -> Result<ResponseOk, Error> {
36+
pub async fn snapshot(cluster: &Cluster, snapshot_id: i64) -> Result<ResponseOk, Error> {
3637
let snapshot = models::Snapshot::get_by_id(cluster.pool(), snapshot_id).await?;
3738

38-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
39+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
3940
layout.breadcrumbs(vec![
4041
NavLink::new("Snapshots", &urls::deployment_snapshots()),
4142
NavLink::new(&snapshot.relation_name, &urls::deployment_snapshot_by_id(snapshot.id)).active(),
@@ -48,7 +49,7 @@ pub async fn snapshot(cluster: ConnectedCluster<'_>, snapshot_id: i64) -> Result
4849

4950
let nav_tabs = tabs::Tabs::new(tabs, Some("Snapshots"), Some("Snapshots"))?;
5051

51-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
52+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
5253
}
5354

5455
// Returns all snapshots for the deployment in a turboframe.

pgml-dashboard/src/api/deployment/uploader.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rocket::route::Route;
55
use sailfish::TemplateOnce;
66

77
use crate::{
8+
guards::Cluster,
89
guards::ConnectedCluster,
910
responses::{BadRequest, Error, ResponseOk},
1011
};
@@ -18,8 +19,8 @@ use crate::utils::urls;
1819

1920
// Returns the uploader page.
2021
#[get("/uploader")]
21-
pub async fn uploader(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error> {
22-
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster.inner.context);
22+
pub async fn uploader(cluster: &Cluster) -> Result<ResponseOk, Error> {
23+
let mut layout = crate::templates::WebAppBase::new("Dashboard", &cluster);
2324
layout.breadcrumbs(vec![NavLink::new("Upload Data", &urls::deployment_uploader()).active()]);
2425

2526
let tabs = vec![tabs::Tab {
@@ -29,7 +30,7 @@ pub async fn uploader(cluster: ConnectedCluster<'_>) -> Result<ResponseOk, Error
2930

3031
let nav_tabs = tabs::Tabs::new(tabs, Some("Upload Data"), Some("Upload Data"))?;
3132

32-
Ok(ResponseOk(layout.render(templates::Dashboard { tabs: nav_tabs })))
33+
Ok(ResponseOk(layout.render(templates::Dashboard::new(nav_tabs))))
3334
}
3435

3536
// Returns uploader module in a turboframe.

pgml-dashboard/src/components/modal/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub struct Modal {
1010
pub header: Option<Component>,
1111
pub body: Component,
1212
pub default_style: bool,
13+
static_backdrop: String,
1314
}
1415

1516
component!(Modal);
@@ -63,6 +64,15 @@ impl Modal {
6364
self.default_style = false;
6465
self
6566
}
67+
68+
pub fn set_static_backdrop(mut self, set_static: bool) -> Modal {
69+
if set_static {
70+
self.static_backdrop = r#"data-bs-backdrop="static""#.into();
71+
} else {
72+
self.static_backdrop = String::new();
73+
}
74+
self
75+
}
6676
}
6777

6878
#[cfg(test)]

pgml-dashboard/src/components/modal/template.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
<div class="modal <%- size_class %>" id="<%= id %>" data-controller="modal" tabindex="-1" aria-modal="true" role="dialog" data-modal-target="modal" >
1+
<div
2+
class="modal <%- size_class %>"
3+
id="<%= id %>"
4+
data-controller="modal" tabindex="-1" aria-modal="true" role="dialog" data-modal-target="modal"
5+
data-action="show->modal#show hide->modal#hide"
6+
<%- static_backdrop %>
7+
>
28
<div class="modal-dialog">
39
<div class="modal-content">
410
<% if let Some(header) = header { %>

pgml-dashboard/src/components/notifications/marketing/alert_banner/template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</div>
1313

1414
<% if notification.dismissible && notification.level != NotificationLevel::Level3 {%>
15-
<a class="w-0 overflow-visible d-flex align-items-center" style="right: 4vw" href="/dashboard/notifications/remove_banner?id=<%- notification.id%>&alert=true">
15+
<a class="w-0 overflow-visible d-flex align-items-center" style="right: 4vw" href="/dashboard/notifications/remove_banner?id=<%- notification.id%>&notification_type=alert">
1616
<span class="material-symbols-outlined <% if notification.level == NotificationLevel::Level2 {%>close-light<% } else {%>close-dark<% } %>">
1717
close
1818
</span></a>

pgml-dashboard/src/components/notifications/marketing/feature_banner/feature_banner.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ div[data-controller="notifications-marketing-feature-banner"] {
4141
color: #{$slate-shade-100}
4242
}
4343
}
44-
45-
.feature1, .feature2, .feature3 {
46-
border-radius: $border-radius-xl;
47-
}
4844

4945
.message-area {
5046
max-width: 75vw;

pgml-dashboard/src/components/notifications/marketing/feature_banner/template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<%- content %>
2626

2727
<% if notification.dismissible {%>
28-
<a class="w-0 btn btn-tertiary overflow-visible d-flex align-items-start p-2" style="height: fit-content" href="/dashboard/notifications/remove_banner?id=<%- notification.id%>&alert=false">
28+
<a class="w-0 btn btn-tertiary overflow-visible d-flex align-items-start p-2" style="height: fit-content" href="/dashboard/notifications/remove_banner?id=<%- notification.id%>&notification_type=feature">
2929
<span class="material-symbols-outlined close">
3030
close
3131
</span></a>

pgml-dashboard/src/components/notifications/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33

44
// src/components/notifications/marketing
55
pub mod marketing;
6+
7+
// src/components/notifications/product
8+
pub mod product;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// This file is automatically generated.
2+
// You shouldn't modify it manually.
3+
4+
// src/components/notifications/product/product_banner
5+
pub mod product_banner;
6+
pub use product_banner::ProductBanner;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use crate::utils::random_string;
2+
use crate::{Notification, NotificationLevel};
3+
use pgml_components::component;
4+
use sailfish::TemplateOnce;
5+
6+
#[derive(TemplateOnce, Default, Clone)]
7+
#[template(path = "notifications/product/product_banner/template.html")]
8+
pub struct ProductBanner {
9+
notification: Option<Notification>,
10+
location_id: String,
11+
url: String,
12+
show_modal_on_load: bool,
13+
}
14+
15+
impl ProductBanner {
16+
pub fn from_notification(notification: Option<&Notification>) -> ProductBanner {
17+
let mut unique_target = random_string(10);
18+
unique_target.insert(0, 'a');
19+
let location_id = ProductBanner::make_location_id(notification.clone(), unique_target.clone());
20+
let url = ProductBanner::make_url(notification.clone(), unique_target.clone());
21+
22+
ProductBanner {
23+
notification: notification.cloned(),
24+
location_id,
25+
url,
26+
show_modal_on_load: true,
27+
}
28+
}
29+
30+
pub fn get_location_id(&self) -> String {
31+
self.location_id.clone()
32+
}
33+
34+
pub fn get_url(&self) -> String {
35+
self.url.clone()
36+
}
37+
38+
pub fn set_show_modal_on_load(mut self, show_modal_on_load: bool) -> ProductBanner {
39+
self.show_modal_on_load = show_modal_on_load;
40+
self
41+
}
42+
43+
fn make_location_id(notification: Option<&Notification>, random_target: String) -> String {
44+
match notification {
45+
Some(notification) => match notification.level {
46+
NotificationLevel::ProductHigh => random_target,
47+
_ => {
48+
format!(
49+
"product-banner{}{}",
50+
notification.level.to_string(),
51+
notification
52+
.deployment
53+
.as_ref()
54+
.and_then(|id| Some(format!("-{}", id)))
55+
.unwrap_or(String::new())
56+
)
57+
}
58+
},
59+
_ => random_target,
60+
}
61+
}
62+
63+
fn make_url(notification: Option<&Notification>, random_target: String) -> String {
64+
let mut url = format!("/dashboard/notifications/product");
65+
66+
url.push_str(match notification {
67+
Some(notification) => match notification.level {
68+
NotificationLevel::ProductHigh => "/remove_banner",
69+
_ => "/replace_banner",
70+
},
71+
None => "/remove_banner",
72+
});
73+
74+
let query_params: Vec<Option<String>> = vec![
75+
notification.and_then(|n| Some(format!("id={}", n.id))),
76+
notification.and_then(|n| {
77+
n.deployment
78+
.as_ref()
79+
.and_then(|id| Some(format!("deployment_id={}", id)))
80+
}),
81+
Some(format!("target={}", random_target)),
82+
];
83+
84+
let all_params = query_params
85+
.iter()
86+
.filter_map(|x| x.clone())
87+
.collect::<Vec<String>>()
88+
.join("&");
89+
90+
url.push_str(&("?".to_owned() + &all_params));
91+
92+
url
93+
}
94+
}
95+
96+
component!(ProductBanner);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy