Merge branch 'ui-redesign' into 'main'
Field Validation See merge request vade/vade-mecum!4
This commit is contained in:
commit
b1c8342253
|
@ -1,6 +1,6 @@
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
COPY target/x86_64-unknown-linux-musl/release/vade /app/vade
|
COPY target/x86_64-unknown-linux-musl/release/vade /app/vade
|
||||||
EXPOSE 8088
|
EXPOSE 8089
|
||||||
WORKDIR app
|
WORKDIR app
|
||||||
RUN touch data.db
|
RUN mkdir data
|
||||||
CMD ["./vade"]
|
CMD ["./vade", "--db data/"]
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
|
@ -15,7 +15,7 @@ axios.interceptors.request.use(function (config) {
|
||||||
|
|
||||||
|
|
||||||
axios.defaults.baseURL = process.env.NODE_ENV === 'development'
|
axios.defaults.baseURL = process.env.NODE_ENV === 'development'
|
||||||
? 'http://localhost:8088'
|
? 'http://localhost:8089'
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
axios.interceptors.response.use(function (response) {
|
axios.interceptors.response.use(function (response) {
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -76,15 +76,24 @@ async fn main() {
|
||||||
let st = state.clone();
|
let st = state.clone();
|
||||||
actix_rt::spawn(async move {
|
actix_rt::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
|
|
||||||
let apps: Vec<entity::application::Model> = entity::application::Entity::find()
|
let apps: Vec<entity::application::Model> = entity::application::Entity::find()
|
||||||
.filter(entity::application::Column::EnableHealthcheck.eq(true))
|
.filter(entity::application::Column::EnableHealthcheck.eq(true))
|
||||||
.all(&st.db)
|
.all(&st.db)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.danger_accept_invalid_certs(true)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
for app in apps {
|
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 => {
|
Ok(res) if res.status() == 200 => {
|
||||||
st.healthcheck_status.lock().await.insert(app.id, true);
|
st.healthcheck_status.lock().await.insert(app.id, true);
|
||||||
let _ = events::EventBroker::from_registry()
|
let _ = events::EventBroker::from_registry()
|
||||||
|
@ -94,7 +103,18 @@ async fn main() {
|
||||||
})
|
})
|
||||||
.await;
|
.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);
|
st.healthcheck_status.lock().await.insert(app.id, false);
|
||||||
let _ = events::EventBroker::from_registry()
|
let _ = events::EventBroker::from_registry()
|
||||||
.send(events::Event::HealthcheckChange {
|
.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 || {
|
HttpServer::new(move || {
|
||||||
let cors = actix_cors::Cors::permissive();
|
let cors = actix_cors::Cors::permissive();
|
||||||
App::new()
|
App::new()
|
||||||
|
.wrap(cors)
|
||||||
.app_data(state.clone())
|
.app_data(state.clone())
|
||||||
.wrap(tracing_actix_web::TracingLogger::default())
|
.wrap(tracing_actix_web::TracingLogger::default())
|
||||||
.wrap(cors)
|
|
||||||
.service(web::resource("/events/{token}").to(socket_session::event_session_index))
|
.service(web::resource("/events/{token}").to(socket_session::event_session_index))
|
||||||
.service(api::routes())
|
.service(api::routes())
|
||||||
.service(dist)
|
.service(dist)
|
||||||
|
|
|
@ -83,6 +83,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
let resp = await axios.post("/api/applications", {
|
let resp = await axios.post("/api/applications", {
|
||||||
active: true,
|
active: true,
|
||||||
|
enableHealthcheck: !!this.app.enableHealthcheck,
|
||||||
...this.app,
|
...this.app,
|
||||||
});
|
});
|
||||||
if (resp.status == 200) {
|
if (resp.status == 200) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default {
|
||||||
}
|
}
|
||||||
.tile:hover {
|
.tile:hover {
|
||||||
transition: all 0.1s;
|
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;
|
box-shadow: rgba(0, 0, 0, 0.5) 0px 20px 30px -10px;
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
|
|
|
@ -19,6 +19,8 @@ export default {
|
||||||
<style>
|
<style>
|
||||||
.bookmark-tile {
|
.bookmark-tile {
|
||||||
padding: 5px 25px;
|
padding: 5px 25px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-tile, .bookmark-tile svg {
|
.bookmark-tile, .bookmark-tile svg {
|
||||||
|
@ -28,6 +30,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-tile:hover, .bookmark-tile:hover svg {
|
.bookmark-tile:hover, .bookmark-tile:hover svg {
|
||||||
|
transition: all 0.2s;
|
||||||
|
background: rgba(0,0,0,0.25);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ export default {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, 0%);
|
transform: translate(-50%, 0%);
|
||||||
display: none;
|
display: none;
|
||||||
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.open {
|
.modal.open {
|
||||||
|
|
|
@ -15,6 +15,6 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.tile.new {
|
.tile.new {
|
||||||
background: #444;
|
background: rgba(0,0,0,0.8);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -16,6 +16,50 @@
|
||||||
:appData="app"
|
:appData="app"
|
||||||
:key="app.id"
|
:key="app.id"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container" v-for="cat in applicationCategories" :key="cat.id">
|
||||||
|
<h1 @click="appCatClicked(cat)" class="editable">
|
||||||
|
<font-awesome-icon v-if="cat.glyph" :icon="cat.glyph" />
|
||||||
|
{{cat.categoryName}}
|
||||||
|
</h1>
|
||||||
|
<div class="app-tiles">
|
||||||
|
<application-tile
|
||||||
|
@clicked="appTileClicked"
|
||||||
|
v-for="app in appsForCategory(cat.id)"
|
||||||
|
:appData="app"
|
||||||
|
:key="app.id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" v-if="bookmarks.length">
|
||||||
|
<h1 class="bookmark">BOOKMARKS</h1>
|
||||||
|
<div class="bookmark-container">
|
||||||
|
<div class="bookmark-category" v-if="bookmarksForCategory(null).length">
|
||||||
|
<h2>UNCATEGORZED</h2>
|
||||||
|
<bookmark-tile
|
||||||
|
v-for="bm in bookmarksForCategory(null)"
|
||||||
|
:key="bm.id"
|
||||||
|
:bookmark="bm"
|
||||||
|
@clicked="bookmarkClicked"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="bookmark-category" v-for="cat in bookmarkCategories" :key="cat.id">
|
||||||
|
<h2 @click="bookmarkCatClicked(cat)" class="editable">
|
||||||
|
<font-awesome-icon v-if="cat.glyph" :icon="cat.glyph" />
|
||||||
|
{{cat.categoryName}}
|
||||||
|
</h2>
|
||||||
|
<bookmark-tile
|
||||||
|
@clicked="bookmarkClicked"
|
||||||
|
v-for="bm in bookmarksForCategory(cat.id)"
|
||||||
|
:key="bm.id"
|
||||||
|
:bookmark="bm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<edit-mode-button :editMode="editMode" @click="toggleEdit" />
|
||||||
<application-modal
|
<application-modal
|
||||||
:open="appOpen"
|
:open="appOpen"
|
||||||
:data="editApp"
|
:data="editApp"
|
||||||
|
@ -43,51 +87,6 @@
|
||||||
@update="reload"
|
@update="reload"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="container" v-for="cat in applicationCategories" :key="cat.id">
|
|
||||||
<h1 @click="appCatClicked(cat)" class="editable">
|
|
||||||
<font-awesome-icon v-if="cat.glyph" :icon="cat.glyph" />
|
|
||||||
{{cat.categoryName}}
|
|
||||||
</h1>
|
|
||||||
<div class="app-tiles">
|
|
||||||
<application-tile
|
|
||||||
@clicked="appTileClicked"
|
|
||||||
v-for="app in appsForCategory(cat.id)"
|
|
||||||
:appData="app"
|
|
||||||
:key="app.id"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container" v-if="bookmarks.length">
|
|
||||||
<h1 class="bookmark">BOOKMARKS</h1>
|
|
||||||
<div class="bookmark-container">
|
|
||||||
<div class="bookmark-category">
|
|
||||||
<h2>UNCATEGORZED</h2>
|
|
||||||
<bookmark-tile
|
|
||||||
v-for="bm in bookmarksForCategory(null)"
|
|
||||||
:key="bm.id"
|
|
||||||
:bookmark="bm"
|
|
||||||
@clicked="bookmarkClicked"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="bookmark-category" v-for="cat in bookmarkCategories" :key="cat.id">
|
|
||||||
<h2 @click="bookmarkCatClicked(cat)" class="editable">
|
|
||||||
<font-awesome-icon v-if="cat.glyph" :icon="cat.glyph" />
|
|
||||||
{{cat.categoryName}}
|
|
||||||
</h2>
|
|
||||||
<bookmark-tile
|
|
||||||
@clicked="bookmarkClicked"
|
|
||||||
v-for="bm in bookmarksForCategory(cat.id)"
|
|
||||||
:key="bm.id"
|
|
||||||
:bookmark="bm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<edit-mode-button :editMode="editMode" @click="toggleEdit" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -252,16 +251,22 @@ h1 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
padding-left: 25px;
|
font-size: 18px;
|
||||||
font-size: 24px;
|
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 {
|
h2 {
|
||||||
color: #fff;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
color: rgba(255,255,255,0.25);
|
||||||
|
text-shadow: 1px 1px rgba(0,0,0,0.25);
|
||||||
}
|
}
|
||||||
.edit-mode .editable {
|
.edit-mode .editable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -275,12 +280,25 @@ h2 svg {
|
||||||
grid-template-columns: repeat(4, 25%);
|
grid-template-columns: repeat(4, 25%);
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
padding: 10px 50px;
|
padding: 25px;
|
||||||
width: 1000px;
|
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 {
|
.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 {
|
.editmode-tiles {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
Loading…
Reference in New Issue