diff --git a/Dockerfile b/Dockerfile index 0c0e8eb..6585cde 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:latest COPY target/x86_64-unknown-linux-musl/release/vade /app/vade -EXPOSE 8088 +EXPOSE 8089 WORKDIR app -RUN touch data.db -CMD ["./vade"] +RUN mkdir data +CMD ["./vade", "--db data/"] diff --git a/public/bg.jpg b/public/bg.jpg new file mode 100644 index 0000000..5a8ece3 Binary files /dev/null and b/public/bg.jpg differ diff --git a/src/main.js b/src/main.js index b016488..c5816bc 100644 --- a/src/main.js +++ b/src/main.js @@ -15,7 +15,7 @@ axios.interceptors.request.use(function (config) { axios.defaults.baseURL = process.env.NODE_ENV === 'development' - ? 'http://localhost:8088' + ? 'http://localhost:8089' : ''; axios.interceptors.response.use(function (response) { diff --git a/src/main.rs b/src/main.rs index 61cf9f6..a8f747e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,15 +76,24 @@ async fn main() { let st = state.clone(); actix_rt::spawn(async move { loop { - tokio::time::sleep(tokio::time::Duration::from_secs(60)).await; let apps: Vec = entity::application::Entity::find() .filter(entity::application::Column::EnableHealthcheck.eq(true)) .all(&st.db) .await .unwrap(); + let client = reqwest::Client::builder() + .danger_accept_invalid_certs(true) + .build() + .unwrap(); + for app in apps { - match reqwest::get(app.url).await { + match client + .request(reqwest::Method::GET, app.url) + .timeout(std::time::Duration::from_secs(5)) + .send() + .await + { Ok(res) if res.status() == 200 => { st.healthcheck_status.lock().await.insert(app.id, true); let _ = events::EventBroker::from_registry() @@ -94,7 +103,18 @@ async fn main() { }) .await; } - _ => { + Err(e) => { + tracing::warn!("Error performing healthcheck: {}", e); + st.healthcheck_status.lock().await.insert(app.id, false); + let _ = events::EventBroker::from_registry() + .send(events::Event::HealthcheckChange { + app_id: app.id, + alive: false, + }) + .await; + } + Ok(res) => { + tracing::warn!("Non 200 status code: {}", res.status()); st.healthcheck_status.lock().await.insert(app.id, false); let _ = events::EventBroker::from_registry() .send(events::Event::HealthcheckChange { @@ -105,6 +125,7 @@ async fn main() { } } } + tokio::time::sleep(tokio::time::Duration::from_secs(60)).await; } }); @@ -113,9 +134,9 @@ async fn main() { HttpServer::new(move || { let cors = actix_cors::Cors::permissive(); App::new() + .wrap(cors) .app_data(state.clone()) .wrap(tracing_actix_web::TracingLogger::default()) - .wrap(cors) .service(web::resource("/events/{token}").to(socket_session::event_session_index)) .service(api::routes()) .service(dist) diff --git a/src/ui/components/ApplicationModal.vue b/src/ui/components/ApplicationModal.vue index bb484c9..0e062f3 100644 --- a/src/ui/components/ApplicationModal.vue +++ b/src/ui/components/ApplicationModal.vue @@ -83,6 +83,7 @@ export default { } else { let resp = await axios.post("/api/applications", { active: true, + enableHealthcheck: !!this.app.enableHealthcheck, ...this.app, }); if (resp.status == 200) { diff --git a/src/ui/components/ApplicationTile.vue b/src/ui/components/ApplicationTile.vue index 84e3393..db2718a 100644 --- a/src/ui/components/ApplicationTile.vue +++ b/src/ui/components/ApplicationTile.vue @@ -33,7 +33,7 @@ export default { } .tile:hover { transition: all 0.1s; - background-color: #333; + background-color: rgba(50,50,50, 0.5); box-shadow: rgba(0, 0, 0, 0.5) 0px 20px 30px -10px; } .label { diff --git a/src/ui/components/BookmarkTile.vue b/src/ui/components/BookmarkTile.vue index ea87c06..83072d9 100644 --- a/src/ui/components/BookmarkTile.vue +++ b/src/ui/components/BookmarkTile.vue @@ -19,6 +19,8 @@ export default { diff --git a/src/ui/views/Dashboard.vue b/src/ui/views/Dashboard.vue index 8bd5bb2..d4f00c4 100644 --- a/src/ui/views/Dashboard.vue +++ b/src/ui/views/Dashboard.vue @@ -16,32 +16,6 @@ :appData="app" :key="app.id" /> - - - -
@@ -62,7 +36,7 @@

BOOKMARKS

-
+

UNCATEGORZED

- + + + +
@@ -252,16 +251,22 @@ h1 { font-weight: bold; line-height: 1; margin-bottom: 5px; - padding-left: 25px; - font-size: 24px; + font-size: 18px; + padding-bottom: 10px; + color: rgba(255,255,255,0.25); + text-shadow: 1px 1px rgba(0,0,0,0.25); + text-transform: uppercase; + text-align: right; } + h2 { - color: #fff; font-size: 18px; text-transform: uppercase; padding-left: 25px; font-weight: bold; margin-bottom: 5px; + color: rgba(255,255,255,0.25); + text-shadow: 1px 1px rgba(0,0,0,0.25); } .edit-mode .editable { cursor: pointer; @@ -275,12 +280,25 @@ h2 svg { grid-template-columns: repeat(4, 25%); } .container { - padding: 10px 50px; + padding: 25px; width: 1000px; - margin: auto auto; + margin: 20px auto; + -webkit-backdrop-filter: blur(6px); + backdrop-filter: blur(6px); + background-color: rgba(0,0,0,0.4); + border-radius: 15px; +} +.container svg { + color: rgba(255,255,255,0.25); } .dashboard { - margin-top: 150px; + user-select: none; + min-height: calc(100vh - 150px); + min-width: 100vw; + padding-top: 150px; + background: url('/bg.jpg'); + background-position: center center; + background-size: cover; } .editmode-tiles { display: flex;