templates
This commit is contained in:
parent
33a7a1882c
commit
bc63926d18
42 changed files with 1224 additions and 90 deletions
2
Makefile
2
Makefile
|
@ -30,9 +30,9 @@ frontend: ## Build frontend assets
|
|||
@yarn install
|
||||
@-rm -rf ./static/cache/bundle/
|
||||
@-mkdir ./static/cache/bundle/css/
|
||||
@yarn sass
|
||||
@yarn build
|
||||
@./scripts/bundle.sh
|
||||
#@yarn run dart-sass -s compressed templates/main.scss ./static/cache/bundle/css/main.css
|
||||
|
||||
lint: ## Lint codebase
|
||||
cargo fmt -v --all -- --emit files
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"sass": "yarn run dart-sass",
|
||||
"sass": "dart-sass -s compressed templates/main.scss ./static/cache/bundle/css/main.css",
|
||||
"start": "webpack-dev-server --mode development --progress --color",
|
||||
"test": "jest"
|
||||
},
|
||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -29,7 +29,7 @@ mod api;
|
|||
mod data;
|
||||
mod errors;
|
||||
mod middleware;
|
||||
//mod pages;
|
||||
mod pages;
|
||||
mod settings;
|
||||
mod static_assets;
|
||||
#[cfg(test)]
|
||||
|
@ -39,7 +39,7 @@ mod tests;
|
|||
pub use crate::data::Data;
|
||||
pub use api::v1::ROUTES as V1_API_ROUTES;
|
||||
pub use middleware::auth::CheckLogin;
|
||||
//pub use pages::routes::ROUTES as PAGES;
|
||||
pub use pages::routes::ROUTES as PAGES;
|
||||
pub use settings::Settings;
|
||||
pub use static_assets::static_files::assets;
|
||||
|
||||
|
@ -48,9 +48,9 @@ use static_assets::FileMap;
|
|||
lazy_static! {
|
||||
pub static ref SETTINGS: Settings = Settings::new().unwrap();
|
||||
pub static ref FILES: FileMap = FileMap::new();
|
||||
//
|
||||
// pub static ref CSS: &'static str =
|
||||
// FILES.get("./static/cache/bundle/css/main.css").unwrap();
|
||||
|
||||
pub static ref CSS: &'static str =
|
||||
FILES.get("./static/cache/bundle/css/main.css").unwrap();
|
||||
pub static ref JS: &'static str =
|
||||
FILES.get("./static/cache/bundle/bundle.js").unwrap();
|
||||
|
||||
|
@ -157,7 +157,7 @@ pub fn get_identity_service() -> IdentityService<CookieIdentityPolicy> {
|
|||
}
|
||||
|
||||
pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
|
||||
//pages::services(cfg);
|
||||
pages::services(cfg);
|
||||
api::v1::services(cfg);
|
||||
static_assets::services(cfg);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use actix_web::{error::ResponseError, http::header, web, HttpResponse, Responder
|
|||
use lazy_static::lazy_static;
|
||||
use sailfish::TemplateOnce;
|
||||
|
||||
use crate::api::v1::auth::runners;
|
||||
use crate::api::v1::admin::auth::runners;
|
||||
use crate::errors::*;
|
||||
use crate::pages::errors::ErrorPage;
|
||||
use crate::AppData;
|
||||
|
@ -92,10 +92,10 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
use crate::api::v1::account::{
|
||||
use crate::api::v1::admin::account::{
|
||||
username::runners::username_exists, AccountCheckPayload,
|
||||
};
|
||||
use crate::api::v1::auth::runners::Register;
|
||||
use crate::api::v1::admin::auth::runners::Register;
|
||||
use crate::data::Data;
|
||||
use crate::tests::*;
|
||||
use crate::*;
|
||||
|
|
|
@ -21,7 +21,7 @@ use lazy_static::lazy_static;
|
|||
use my_codegen::{get, post};
|
||||
use sailfish::TemplateOnce;
|
||||
|
||||
use crate::api::v1::auth::runners;
|
||||
use crate::api::v1::admin::auth::runners;
|
||||
use crate::errors::*;
|
||||
use crate::pages::errors::ErrorPage;
|
||||
use crate::AppData;
|
||||
|
@ -95,7 +95,7 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
use crate::api::v1::auth::runners::{Login, Register};
|
||||
use crate::api::v1::admin::auth::runners::{Login, Register};
|
||||
use crate::data::Data;
|
||||
use crate::tests::*;
|
||||
use crate::*;
|
||||
|
@ -120,7 +120,7 @@ mod tests {
|
|||
};
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&msg, V1_API_ROUTES.auth.register).to_request(),
|
||||
post_request!(&msg, V1_API_ROUTES.admin.auth.register).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
|
|
@ -18,6 +18,8 @@ pub mod join;
|
|||
pub mod login;
|
||||
pub mod sudo;
|
||||
|
||||
pub use crate::api::v1::admin::get_admin_check_login;
|
||||
|
||||
pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
|
||||
cfg.service(login::login);
|
||||
cfg.service(login::login_submit);
|
||||
|
@ -33,8 +35,8 @@ pub mod routes {
|
|||
impl Auth {
|
||||
pub const fn new() -> Auth {
|
||||
Auth {
|
||||
login: "/login",
|
||||
join: "/join",
|
||||
login: "/api/v1/admin/page/login",
|
||||
join: "/api/v1/admin/page/join",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,11 +60,14 @@ mod tests {
|
|||
let app = get_app!(data).await;
|
||||
|
||||
let urls = vec![
|
||||
PAGES.home.into(),
|
||||
//PAGES.home.into(),
|
||||
PAGES.panel.campaigns.home.into(),
|
||||
PAGES.panel.campaigns.new.into(),
|
||||
PAGES.panel.campaigns.get_feedback_route(&campaign.uuid),
|
||||
PAGES.panel.campaigns.get_delete_route(&campaign.uuid),
|
||||
// PAGES.panel.campaigns.get_feedback_route(&campaign.uuid),
|
||||
PAGES
|
||||
.panel
|
||||
.campaigns
|
||||
.get_delete_route(&campaign.campaign_id),
|
||||
];
|
||||
|
||||
for url in urls.iter() {
|
||||
|
|
|
@ -25,8 +25,9 @@ use my_codegen::{get, post};
|
|||
use sailfish::TemplateOnce;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::api::v1::auth::runners::{login_runner, Login, Password};
|
||||
use crate::api::v1::campaign::runners;
|
||||
use super::get_admin_check_login;
|
||||
use crate::api::v1::admin::auth::runners::{login_runner, Login, Password};
|
||||
use crate::api::v1::admin::campaigns::runners;
|
||||
use crate::errors::*;
|
||||
use crate::pages::auth::sudo::SudoPage;
|
||||
use crate::AppData;
|
||||
|
@ -43,11 +44,11 @@ async fn get_title(
|
|||
let campaign = sqlx::query_as!(
|
||||
Name,
|
||||
"SELECT name
|
||||
FROM kaizen_campaign
|
||||
FROM survey_campaigns
|
||||
WHERE
|
||||
uuid = $1
|
||||
id = $1
|
||||
AND
|
||||
user_id = (SELECT ID from kaizen_users WHERE name = $2)",
|
||||
user_id = (SELECT ID from survey_admins WHERE name = $2)",
|
||||
&uuid,
|
||||
&username
|
||||
)
|
||||
|
@ -57,7 +58,10 @@ async fn get_title(
|
|||
Ok(format!("Delete camapign \"{}\"?", campaign.name))
|
||||
}
|
||||
|
||||
#[get(path = "PAGES.panel.campaigns.delete", wrap = "crate::CheckLogin")]
|
||||
#[get(
|
||||
path = "PAGES.panel.campaigns.delete",
|
||||
wrap = "get_admin_check_login()"
|
||||
)]
|
||||
pub async fn delete_campaign(
|
||||
id: Identity,
|
||||
path: web::Path<String>,
|
||||
|
@ -80,7 +84,10 @@ pub async fn delete_campaign(
|
|||
.body(page))
|
||||
}
|
||||
|
||||
#[post(path = "PAGES.panel.campaigns.delete", wrap = "crate::CheckLogin")]
|
||||
#[post(
|
||||
path = "PAGES.panel.campaigns.delete",
|
||||
wrap = "get_admin_check_login()"
|
||||
)]
|
||||
pub async fn delete_campaign_submit(
|
||||
id: Identity,
|
||||
path: web::Path<String>,
|
||||
|
@ -102,7 +109,7 @@ pub async fn delete_campaign_submit(
|
|||
let status = e.status_code();
|
||||
let heading = status.canonical_reason().unwrap_or("Error");
|
||||
|
||||
let form_route = crate::V1_API_ROUTES.campaign.get_delete_route(&path);
|
||||
let form_route = crate::V1_API_ROUTES.admin.campaign.get_delete_route(&path);
|
||||
let title = get_title(&username, &uuid, &data).await?;
|
||||
let mut ctx = SudoPage::new(&form_route, &title);
|
||||
let err = format!("{}", e);
|
||||
|
@ -179,7 +186,7 @@ mod tests {
|
|||
&app,
|
||||
post_request!(
|
||||
&creds,
|
||||
&PAGES.panel.campaigns.get_delete_route(&uuid.uuid),
|
||||
&PAGES.panel.campaigns.get_delete_route(&uuid.campaign_id),
|
||||
FORM
|
||||
)
|
||||
.cookie(cookies.clone())
|
||||
|
|
|
@ -14,48 +14,49 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use my_codegen::get;
|
||||
use sailfish::TemplateOnce;
|
||||
|
||||
use crate::api::v1::campaign::{runners, GetFeedbackResp};
|
||||
use crate::AppData;
|
||||
use crate::PAGES;
|
||||
|
||||
#[derive(TemplateOnce)]
|
||||
#[template(path = "panel/campaigns/get/index.html")]
|
||||
struct ViewFeedback<'a> {
|
||||
campaign: GetFeedbackResp,
|
||||
uuid: &'a str,
|
||||
}
|
||||
|
||||
const PAGE: &str = "New Campaign";
|
||||
|
||||
impl<'a> ViewFeedback<'a> {
|
||||
pub fn new(campaign: GetFeedbackResp, uuid: &'a str) -> Self {
|
||||
Self { campaign, uuid }
|
||||
}
|
||||
}
|
||||
|
||||
#[get(
|
||||
path = "PAGES.panel.campaigns.get_feedback",
|
||||
wrap = "crate::CheckLogin"
|
||||
)]
|
||||
pub async fn get_feedback(
|
||||
id: Identity,
|
||||
data: AppData,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let username = id.identity().unwrap();
|
||||
let path = path.into_inner();
|
||||
let feedback_resp = runners::get_feedback(&username, &path, &data)
|
||||
.await
|
||||
.unwrap();
|
||||
let page = ViewFeedback::new(feedback_resp, &path)
|
||||
.render_once()
|
||||
.unwrap();
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(page)
|
||||
}
|
||||
//use actix_identity::Identity;
|
||||
//use actix_web::{web, HttpResponse, Responder};
|
||||
//use my_codegen::get;
|
||||
//use sailfish::TemplateOnce;
|
||||
//
|
||||
//use crate::api::v1::admin::campaigns::{runners, GetFeedbackResp};
|
||||
//use crate::AppData;
|
||||
//use crate::PAGES;
|
||||
//use super::get_admin_check_login;
|
||||
//
|
||||
//#[derive(TemplateOnce)]
|
||||
//#[template(path = "panel/campaigns/get/index.html")]
|
||||
//struct ViewFeedback<'a> {
|
||||
// campaign: GetFeedbackResp,
|
||||
// uuid: &'a str,
|
||||
//}
|
||||
//
|
||||
//const PAGE: &str = "New Campaign";
|
||||
//
|
||||
//impl<'a> ViewFeedback<'a> {
|
||||
// pub fn new(campaign: GetFeedbackResp, uuid: &'a str) -> Self {
|
||||
// Self { campaign, uuid }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//#[get(
|
||||
// path = "PAGES.panel.campaigns.get_feedback",
|
||||
// wrap = "get_admin_check_login()"
|
||||
//)]
|
||||
//pub async fn get_feedback(
|
||||
// id: Identity,
|
||||
// data: AppData,
|
||||
// path: web::Path<String>,
|
||||
//) -> impl Responder {
|
||||
// let username = id.identity().unwrap();
|
||||
// let path = path.into_inner();
|
||||
// let feedback_resp = runners::get_feedback(&username, &path, &data)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// let page = ViewFeedback::new(feedback_resp, &path)
|
||||
// .render_once()
|
||||
// .unwrap();
|
||||
// HttpResponse::Ok()
|
||||
// .content_type("text/html; charset=utf-8")
|
||||
// .body(page)
|
||||
//}
|
||||
|
|
|
@ -18,10 +18,14 @@ use actix_web::{HttpResponse, Responder};
|
|||
use my_codegen::get;
|
||||
use sailfish::TemplateOnce;
|
||||
|
||||
use crate::api::v1::campaign::{runners::list_campaign_runner, ListCampaignResp};
|
||||
use crate::api::v1::admin::campaigns::{
|
||||
runners::list_campaign_runner, ListCampaignResp,
|
||||
};
|
||||
use crate::AppData;
|
||||
use crate::PAGES;
|
||||
|
||||
use super::get_admin_check_login;
|
||||
|
||||
pub mod delete;
|
||||
pub mod get;
|
||||
pub mod new;
|
||||
|
@ -36,10 +40,10 @@ pub mod routes {
|
|||
impl Campaigns {
|
||||
pub const fn new() -> Campaigns {
|
||||
Campaigns {
|
||||
home: "/campaigns",
|
||||
new: "/campaigns/new",
|
||||
get_feedback: "/campaigns/{uuid}/feedback",
|
||||
delete: "/campaigns/{uuid}/delete",
|
||||
home: "/api/v1/admin/page/campaigns",
|
||||
new: "/api/v1/admin/page/campaigns/new",
|
||||
get_feedback: "/api/v1/admin/page/campaigns/{uuid}/feedback",
|
||||
delete: "/api/v1/admin/page/campaigns/{uuid}/delete",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +66,7 @@ pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
|
|||
cfg.service(home);
|
||||
cfg.service(new::new_campaign);
|
||||
cfg.service(new::new_campaign_submit);
|
||||
cfg.service(get::get_feedback);
|
||||
// cfg.service(get::get_feedback);
|
||||
cfg.service(delete::delete_campaign);
|
||||
cfg.service(delete::delete_campaign_submit);
|
||||
}
|
||||
|
@ -81,7 +85,7 @@ impl HomePage {
|
|||
|
||||
const PAGE: &str = "Campaigns";
|
||||
|
||||
#[get(path = "PAGES.panel.campaigns.home", wrap = "crate::CheckLogin")]
|
||||
#[get(path = "PAGES.panel.campaigns.home", wrap = "get_admin_check_login()")]
|
||||
pub async fn home(data: AppData, id: Identity) -> impl Responder {
|
||||
let username = id.identity().unwrap();
|
||||
let campaigns = list_campaign_runner(&username, &data).await.unwrap();
|
||||
|
|
|
@ -21,12 +21,14 @@ use lazy_static::lazy_static;
|
|||
use my_codegen::{get, post};
|
||||
use sailfish::TemplateOnce;
|
||||
|
||||
use crate::api::v1::campaign::{runners, CreateReq};
|
||||
use crate::api::v1::admin::campaigns::{runners, AddCapmaign};
|
||||
use crate::errors::*;
|
||||
use crate::pages::errors::ErrorPage;
|
||||
use crate::AppData;
|
||||
use crate::PAGES;
|
||||
|
||||
use super::get_admin_check_login;
|
||||
|
||||
#[derive(Clone, TemplateOnce)]
|
||||
#[template(path = "panel/campaigns/new/index.html")]
|
||||
struct NewCampaign<'a> {
|
||||
|
@ -53,20 +55,23 @@ lazy_static! {
|
|||
static ref INDEX: String = NewCampaign::default().render_once().unwrap();
|
||||
}
|
||||
|
||||
#[get(path = "PAGES.panel.campaigns.new", wrap = "crate::CheckLogin")]
|
||||
#[get(path = "PAGES.panel.campaigns.new", wrap = "get_admin_check_login()")]
|
||||
pub async fn new_campaign() -> impl Responder {
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(&*INDEX)
|
||||
}
|
||||
|
||||
#[post(path = "PAGES.panel.campaigns.new", wrap = "crate::CheckLogin")]
|
||||
#[post(path = "PAGES.panel.campaigns.new", wrap = "get_admin_check_login()")]
|
||||
pub async fn new_campaign_submit(
|
||||
id: Identity,
|
||||
payload: web::Form<CreateReq>,
|
||||
payload: web::Json<AddCapmaign>,
|
||||
data: AppData,
|
||||
) -> PageResult<impl Responder> {
|
||||
match runners::new(&payload.into_inner(), &data, &id).await {
|
||||
let username = id.identity().unwrap();
|
||||
let mut payload = payload.into_inner();
|
||||
|
||||
match runners::add_runner(&username, &mut payload, &data).await {
|
||||
Ok(_) => {
|
||||
Ok(HttpResponse::Found()
|
||||
//TODO show stats of new campaign
|
||||
|
@ -113,17 +118,19 @@ mod tests {
|
|||
let (_, _, signin_resp) = register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||
let cookies = get_cookie!(signin_resp);
|
||||
|
||||
let new = CreateReq {
|
||||
let new = AddCapmaign {
|
||||
name: CAMPAIGN_NAME.into(),
|
||||
difficulties: DIFFICULTIES.into(),
|
||||
};
|
||||
|
||||
let new_resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&new, PAGES.panel.campaigns.new, FORM)
|
||||
.cookie(cookies.clone())
|
||||
post_request!(&new, crate::PAGES.panel.campaigns.new)
|
||||
.cookie(cookies)
|
||||
.to_request(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(new_resp.status(), StatusCode::FOUND);
|
||||
let headers = new_resp.headers();
|
||||
assert_eq!(
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
use actix_web::{http, HttpResponse, Responder};
|
||||
use my_codegen::get;
|
||||
|
||||
pub use crate::api::v1::admin::get_admin_check_login;
|
||||
|
||||
use crate::PAGES;
|
||||
|
||||
mod campaigns;
|
||||
|
@ -30,7 +32,7 @@ pub mod routes {
|
|||
impl Panel {
|
||||
pub const fn new() -> Panel {
|
||||
Panel {
|
||||
home: "/",
|
||||
home: "/api/v1/admin/home/",
|
||||
campaigns: Campaigns::new(),
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +49,7 @@ pub fn services(cfg: &mut actix_web::web::ServiceConfig) {
|
|||
campaigns::services(cfg);
|
||||
}
|
||||
|
||||
#[get(path = "PAGES.panel.home", wrap = "crate::CheckLogin")]
|
||||
#[get(path = "PAGES.panel.home", wrap = "get_admin_check_login()")]
|
||||
pub async fn home() -> impl Responder {
|
||||
HttpResponse::Found()
|
||||
.insert_header((http::header::LOCATION, PAGES.panel.campaigns.home))
|
||||
|
|
|
@ -127,6 +127,7 @@ mod tests {
|
|||
assets::LOGO.path,
|
||||
assets::HEADSETS.path,
|
||||
*crate::JS,
|
||||
*crate::CSS,
|
||||
*crate::GLUE,
|
||||
]
|
||||
.iter()
|
||||
|
|
11
templates/auth/demo-user-banner.html
Normal file
11
templates/auth/demo-user-banner.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<. if crate::SETTINGS.allow_demo && crate::SETTINGS.allow_registration { .>
|
||||
<p class="auth__demo-user__banner">
|
||||
Try Kaizen without joining<br />
|
||||
<span class="auth__demo-user__cred" >
|
||||
<b>user:</b> <.= crate::demo::DEMO_USER .>
|
||||
</span>
|
||||
<span class="auth__demo-user__cred">
|
||||
<b>password:</b> <.= crate::demo::DEMO_PASSWORD .>
|
||||
</span>
|
||||
</p>
|
||||
<. } .>
|
69
templates/auth/join/index.html
Normal file
69
templates/auth/join/index.html
Normal file
|
@ -0,0 +1,69 @@
|
|||
<. include!("../../components/base/top.html"); .>
|
||||
<body class="auth__body">
|
||||
<main class="auth__container">
|
||||
<img src="<.= crate::assets::LOGO.path .>" alt="logo" class="auth__logo" />
|
||||
<h1>Join Kaizen</h1>
|
||||
<. include!("../../components/error/index.html"); .>
|
||||
<form
|
||||
action="<.= crate::PAGES.auth.join .>"
|
||||
method="POST"
|
||||
class="form"
|
||||
accept-charset="utf-8"
|
||||
>
|
||||
<label class="form__label" for="username">
|
||||
Username
|
||||
<input
|
||||
class="form__input"
|
||||
name="username"
|
||||
required
|
||||
id="username"
|
||||
type="text"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="form__label" for="email">
|
||||
Email(optional)
|
||||
<input
|
||||
class="form__input"
|
||||
name="email"
|
||||
id="email"
|
||||
type="email"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="form__label" for="password">
|
||||
password
|
||||
<input
|
||||
class="form__input"
|
||||
name="password"
|
||||
required
|
||||
id="password"
|
||||
type="password"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="form__label" for="confirm_password">
|
||||
Re-enter Password
|
||||
<input
|
||||
class="form__input"
|
||||
name="confirm_password"
|
||||
required
|
||||
id="confirm_password"
|
||||
type="password"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div class="form__action-container">
|
||||
<a href="/forgot-password">Forgot password?</a>
|
||||
<button class="form__submit" type="submit">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="form__alt-action">
|
||||
Already have an account?
|
||||
<a href="<.= crate::PAGES.auth.login .>"> Login </a>
|
||||
</p>
|
||||
</main>
|
||||
<. include!("../../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../../components/base/bottom.html"); .>
|
48
templates/auth/login/index.html
Normal file
48
templates/auth/login/index.html
Normal file
|
@ -0,0 +1,48 @@
|
|||
<. include!("../../components/base/top.html"); .>
|
||||
<body class="auth__body">
|
||||
<main class="auth__container">
|
||||
<img src="<.= crate::assets::LOGO.path .>" alt="logo" class="auth__logo" />
|
||||
<h1>Sign in</h1>
|
||||
<. include!("../../components/error/index.html"); .>
|
||||
<form
|
||||
action="<.= crate::PAGES.auth.login .>"
|
||||
method="POST"
|
||||
class="form"
|
||||
accept-charset="utf-8"
|
||||
>
|
||||
<label class="form__label" for="login">
|
||||
Username or Email
|
||||
<input
|
||||
class="form__input"
|
||||
name="login"
|
||||
required
|
||||
id="login"
|
||||
type="text"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="form__label" for="password">
|
||||
password
|
||||
<input
|
||||
class="form__input"
|
||||
name="password"
|
||||
required
|
||||
id="password"
|
||||
type="password"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div class="form__action-container">
|
||||
<a href="/forgot-password">Forgot password?</a>
|
||||
<button class="form__submit" type="submit">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="form__alt-action">
|
||||
New to Kaizen?
|
||||
<a href="<.= crate::PAGES.auth.join .>">Create an account </a>
|
||||
</p>
|
||||
</main>
|
||||
<. include!("../../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../../components/base/bottom.html"); .>
|
50
templates/auth/main.scss
Normal file
50
templates/auth/main.scss
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
.auth__body {
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.auth__container {
|
||||
width: 380px;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.auth__logo {
|
||||
width: 150px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.auth__demo-user__banner {
|
||||
margin: auto;
|
||||
margin-top: 5px;
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.auth__demo-user__cred {
|
||||
font-family: monospace, monospace;
|
||||
}
|
||||
|
||||
.sudo__message {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
34
templates/auth/sudo/index.html
Normal file
34
templates/auth/sudo/index.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<. include!("../../components/base/top.html"); .>
|
||||
<body class="auth__body">
|
||||
<main class="auth__container">
|
||||
<img src="<.= crate::assets::LOGO.path .>" alt="logo" class="auth__logo" />
|
||||
<h1>Confirm Access</h1>
|
||||
|
||||
<p class="sudo__message"><b><.= title .></b></p>
|
||||
<. include!("../../components/error/index.html"); .>
|
||||
<form
|
||||
action="<.= url .>"
|
||||
class="form"
|
||||
method="POST"
|
||||
accept-charset="utf-8"
|
||||
>
|
||||
<label class="form__label" for="password">
|
||||
password
|
||||
<input
|
||||
class="form__input"
|
||||
name="password"
|
||||
required
|
||||
id="password"
|
||||
type="password"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div class="form__action-container">
|
||||
<a href="/forgot-password">Forgot password?</a>
|
||||
<button class="form__submit" type="submit">Authorize</button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
<. include!("../../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../../components/base/bottom.html"); .>
|
38
templates/components/_button.scss
Normal file
38
templates/components/_button.scss
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
@mixin button {
|
||||
border: none;
|
||||
|
||||
// margin: 10px 0;
|
||||
// background-color: none;
|
||||
background-color: #b4345b;
|
||||
color: #fff;
|
||||
// text-align: center;
|
||||
|
||||
border-radius: 0px;
|
||||
|
||||
padding: 0.1rem 0.75rem;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
line-height: 1.2rem;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
user-select: none;
|
||||
border: 1px solid transparent;
|
||||
}
|
1
templates/components/base/bottom.html
Normal file
1
templates/components/base/bottom.html
Normal file
|
@ -0,0 +1 @@
|
|||
</html>
|
8
templates/components/base/top.html
Normal file
8
templates/components/base/top.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><.= PAGE .> | <.= crate::pages::NAME .></title>
|
||||
<link rel="stylesheet" href="<.= &*crate::CSS .>" />
|
||||
</head>
|
6
templates/components/error/index.html
Normal file
6
templates/components/error/index.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<. if let Some(error) = error { .>
|
||||
<div class="error__container">
|
||||
<p class="error__title"><b><.= error.title .></b></p>
|
||||
<p class="error__msg"><.= error.message .></p>
|
||||
</div>
|
||||
<. } .>
|
36
templates/components/error/main.scss
Normal file
36
templates/components/error/main.scss
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.error__container {
|
||||
width: 350px;
|
||||
background-color: #d63f3f;
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
opacity: 0.9;
|
||||
font-size: 0.8rem;
|
||||
font-family: monospace, monospace;
|
||||
}
|
||||
|
||||
.error__title {
|
||||
color: #fff;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.error__msg {
|
||||
color: #fff;
|
||||
margin-left: 10px;
|
||||
}
|
24
templates/components/footer/index.html
Normal file
24
templates/components/footer/index.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<footer class="footer">
|
||||
<. use crate::PAGES; .>
|
||||
<ul class="footer__section">
|
||||
<li class="footer__item">
|
||||
<a class="footer__link" href="<.= PAGES.about .>">About</a>
|
||||
</li>
|
||||
<li class="footer__item">
|
||||
<a class="footer__link" href="<.= PAGES.donate .>">Donate</a>
|
||||
</li>
|
||||
<li class="footer__item">
|
||||
<a class="footer__link" href="<.= PAGES.privacy .>">Privacy</a>
|
||||
</li>
|
||||
<li class="footer__item">
|
||||
<a class="footer__link" href="<.= PAGES.security .>">Security</a>
|
||||
</li>
|
||||
<li class="footer__item">
|
||||
<a class="footer__link" href="<.= PAGES.thanks .>">Thanks</a>
|
||||
</li>
|
||||
<li class="footer__item">
|
||||
<a class="footer__link" href="<.= &*crate::SOURCE_FILES_OF_INSTANCE .>">
|
||||
v<.= crate::VERSION .>-<.= crate::GIT_COMMIT_HASH[0..8] .>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
36
templates/components/footer/main.scss
Normal file
36
templates/components/footer/main.scss
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.footer {
|
||||
font-size: 0.8rem;
|
||||
padding: 0px 20px;
|
||||
|
||||
position: relative;
|
||||
bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer__section {
|
||||
display: inline;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.footer__item {
|
||||
display: inline;
|
||||
list-style: none;
|
||||
padding: 10px;
|
||||
}
|
55
templates/components/form/_partials.scss
Normal file
55
templates/components/form/_partials.scss
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@import "../button";
|
||||
|
||||
@mixin form {
|
||||
margin: 15px auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@mixin label {
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
@mixin input {
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
border-radius: 0px;
|
||||
border: 1px solid grey;
|
||||
}
|
||||
|
||||
@mixin action_container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@mixin alt_action {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@mixin submit {
|
||||
@include button;
|
||||
}
|
||||
|
||||
@mixin submit_hover {
|
||||
cursor: pointer;
|
||||
}
|
45
templates/components/form/main.scss
Normal file
45
templates/components/form/main.scss
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@import "partials";
|
||||
|
||||
.form {
|
||||
@include form;
|
||||
}
|
||||
|
||||
.form__label {
|
||||
@include label;
|
||||
}
|
||||
|
||||
.form__input {
|
||||
@include input;
|
||||
}
|
||||
|
||||
.form__action-container {
|
||||
@include action_container;
|
||||
}
|
||||
|
||||
.form__alt-action {
|
||||
@include alt_action;
|
||||
}
|
||||
|
||||
.form__submit {
|
||||
@include submit;
|
||||
}
|
||||
|
||||
.form__submit:hover {
|
||||
@include submit_hover;
|
||||
}
|
0
templates/components/header.html
Normal file
0
templates/components/header.html
Normal file
9
templates/errors/index.html
Normal file
9
templates/errors/index.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<. include!("../components/base/top.html"); .>
|
||||
<body class="panel__body">
|
||||
<main class="panel__container">
|
||||
<h1 class="error-title"><.= title .></h1>
|
||||
<p class="error-message"><.= message .></p>
|
||||
</main>
|
||||
<. include!("../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../components/base/bottom.html"); .>
|
23
templates/errors/main.scss
Normal file
23
templates/errors/main.scss
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
.error-title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
text-align: center;
|
||||
}
|
63
templates/index.html
Normal file
63
templates/index.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
<. include!("./components/base/top.html"); .>
|
||||
<body class="panel__body">
|
||||
<main class="panel__container">
|
||||
<h1>mCaptcha device benchmark survey</h1>
|
||||
<h2>Why should I participate</h2>
|
||||
<p>
|
||||
<a href="https://mcaptcha.org" target="_blank">mCaptcha</a>
|
||||
is a cutting edge, privacy respecting CAPTCHA system. We use a
|
||||
<a href="https://en.wikipedia.org/wiki/Proof_of_work" target="_blank"
|
||||
>proof of work</a
|
||||
>
|
||||
based mechanism to defend against
|
||||
<a href="https://en.wikipedia.org/wiki/Proof_of_work" target="_blank"
|
||||
>denial-of-service attacks</a
|
||||
>
|
||||
which allows for a non-interactive CAPTCHA experience. We require
|
||||
performance metrics measured on a wide range of devices to fine-tune the
|
||||
system for optimal user experience, see for yourself!
|
||||
</p>
|
||||
<div style="width: 304px; height: 78px">
|
||||
<iframe
|
||||
title="mCaptcha"
|
||||
src="https://demo.mcaptcha.org/widget/?sitekey=6o3p1Fx94hJRFm8g8IHBB7sv8D0em20k"
|
||||
role="presentation"
|
||||
name="mcaptcha-widget__iframe"
|
||||
id="mcaptcha-widget__iframe"
|
||||
scrolling="no"
|
||||
sandbox="allow-same-origin allow-scripts"
|
||||
width="304"
|
||||
height="78"
|
||||
data-mcaptcha_host="https://demo.mcaptcha.org"
|
||||
frameborder="0"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<h2>What do I get?</h2>
|
||||
<p>
|
||||
We are conducting a lucky draw. Two lucky participants, selected at
|
||||
random, will win a pair of
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://www.amazon.in/JBL-Detachable-Directional-Headphones-Conference/dp/B0948TG7H8"
|
||||
>JBL headsets worth over ₹2,500</a
|
||||
>! Also, you will be helping us make the internet healthier :)
|
||||
</p>
|
||||
|
||||
<h2>Privacy policy</h2>
|
||||
<p>This survey collects the following information:</p>
|
||||
<ul>
|
||||
<li>Device name</li>
|
||||
<li>Operating system</li>
|
||||
<li>Processor information</li>
|
||||
<li>Benchmark results</li>
|
||||
</ul>
|
||||
<b>No Personally identifying information is collected</b>
|
||||
</main>
|
||||
<. include!("../components/footer/index.html"); .>
|
||||
<a href="<.= crate::V1_API_ROUTES.benches.register .>" target="_blank"
|
||||
>Get started</a
|
||||
>
|
||||
</body>
|
||||
<script src="./dist/bundle.js"></script>
|
||||
<. include!("./components/base/bottom.html"); .>
|
51
templates/main.scss
Normal file
51
templates/main.scss
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@import "./components/footer/main";
|
||||
@import "./components/form/main";
|
||||
@import "./components/error/main";
|
||||
|
||||
@import "./auth/main";
|
||||
@import "./panel/main";
|
||||
@import "./panel/campaigns/new/main";
|
||||
@import "./panel/campaigns/get/main";
|
||||
@import "./errors/main";
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
|
||||
font-family: "Inter UI", -apple-system, BlinkMacSystemFont, "Roboto",
|
||||
"Segoe UI", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: rgb(0, 86, 179);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
58
templates/panel/campaigns/get/index.html
Normal file
58
templates/panel/campaigns/get/index.html
Normal file
|
@ -0,0 +1,58 @@
|
|||
<. include!("../../../components/base/top.html"); .>
|
||||
<body class="panel__body">
|
||||
<. include!("../../nav/index.html"); .>
|
||||
<main class="panel__container">
|
||||
<h1><.= campaign.name .></h1>
|
||||
<a href="<.= crate::PAGES.panel.campaigns.get_delete_route(&uuid) .>" >
|
||||
<img src="<.= crate::assets::TRASH.path .>" alt="<.= crate::assets::TRASH.name .>" class="feedback__trash-logo" />
|
||||
</a>
|
||||
|
||||
<div class="asset__container">
|
||||
<span class="asset__name">Campaign ID</span>
|
||||
<code id="campaign-id" class="asset__value"><.= uuid .></code>
|
||||
</div>
|
||||
|
||||
<. if campaign.feedbacks.is_empty() { .>
|
||||
<p>
|
||||
Looks like you don't have any feedback on this campaign.
|
||||
</p>
|
||||
<. } else { .>
|
||||
<table class="feedback__table">
|
||||
<thead class="feedback__heading">
|
||||
<tr>
|
||||
<th class="feedback__title-text--normal">Time</th>
|
||||
<th class="feedback__title-text--small">Helpful</th>
|
||||
<th class="feedback__title-text--large">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="feedback__body">
|
||||
<. for feedback in campaign.feedbacks.iter() { .>
|
||||
<tr class="feedback__item">
|
||||
<td>
|
||||
<.= feedback.time .>
|
||||
</td>
|
||||
<td>
|
||||
<.= feedback.helpful .>
|
||||
</td>
|
||||
<td class="feedback__description">
|
||||
<. if feedback.description.len() > 60 { .>
|
||||
<details>
|
||||
<. let (summary, rest) = feedback.description.split_at(60); .>
|
||||
<summary>
|
||||
<.= summary .>
|
||||
</summary> >>
|
||||
<.= rest .>
|
||||
</details>
|
||||
<. } else { .>
|
||||
<.= feedback.description .>
|
||||
<. } .>
|
||||
<. } .>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<. } .>
|
||||
</main>
|
||||
<. include!("../../../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../../../components/base/bottom.html"); .>
|
37
templates/panel/campaigns/get/main.scss
Normal file
37
templates/panel/campaigns/get/main.scss
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
.feedback__table {
|
||||
width: 80%;
|
||||
margin: 40px;
|
||||
}
|
||||
|
||||
.feedback__title-text--small {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.feedback__title-text--large {
|
||||
width: 350px;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.feedback__title-text--normal {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.feedback__description{
|
||||
text-align: start;
|
||||
}
|
42
templates/panel/campaigns/index.html
Normal file
42
templates/panel/campaigns/index.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
<. include!("../../components/base/top.html"); .>
|
||||
<body class="panel__body">
|
||||
<. include!("../nav/index.html"); .>
|
||||
<main class="panel__container">
|
||||
<. if data.is_empty() { .>
|
||||
<p>
|
||||
Looks like you don't have any campaings registered,
|
||||
<a class="link__btn" href="<.= crate::PAGES.panel.campaigns.new .>"> click here </a>
|
||||
to create a new campaign!
|
||||
</p>
|
||||
|
||||
<. } else { .>
|
||||
<table class="campaign__table">
|
||||
<thead class="campaign__heading">
|
||||
<tr>
|
||||
<th class="campaign__title-text">Name</th>
|
||||
<th class="campaign__title-text">UUID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="campaign__body">
|
||||
<. for campaign in data.iter() { .>
|
||||
<. let route = crate::PAGES.panel.campaigns.get_feedback_route(&campaign.uuid); .>
|
||||
<tr class="campaign__item">
|
||||
<td>
|
||||
<a href="<.= &route .>">
|
||||
<p class="campaign__item-heading"><.= campaign.name .></p>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="<.= &route .>">
|
||||
<p class="campaign__item-text"><.= campaign.uuid .></p></a
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<. } .>
|
||||
</tbody>
|
||||
</table>
|
||||
<. } .>
|
||||
</main>
|
||||
<. include!("../../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../../components/base/bottom.html"); .>
|
21
templates/panel/campaigns/new/form.html
Normal file
21
templates/panel/campaigns/new/form.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<h1>Create new campaigns</h1>
|
||||
<. include!("../../../components/error/index.html"); .>
|
||||
<form
|
||||
action="<.= crate::PAGES.panel.campaigns.new .>"
|
||||
method="POST"
|
||||
class="new-campaign__form"
|
||||
accept-charset="utf-8"
|
||||
>
|
||||
<label class="form__label" for="name">
|
||||
Name
|
||||
<input
|
||||
class="form__input"
|
||||
name="name"
|
||||
placeholder=" Joe's website or https://example.com/docs/"
|
||||
required
|
||||
id="name"
|
||||
type="text"
|
||||
/>
|
||||
</label>
|
||||
<button class="form__submit" type="submit">Create Campaign</button>
|
||||
</form>
|
7
templates/panel/campaigns/new/index.html
Normal file
7
templates/panel/campaigns/new/index.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<. include!("../../../components/base/top.html"); .>
|
||||
<body class="panel__body">
|
||||
<. include!("../../nav/index.html"); .>
|
||||
<main class="panel__container"><. include!("./form.html"); .></main>
|
||||
<. include!("../../../components/footer/index.html"); .>
|
||||
</body>
|
||||
<. include!("../../../components/base/bottom.html"); .>
|
22
templates/panel/campaigns/new/main.scss
Normal file
22
templates/panel/campaigns/new/main.scss
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@import "../../../components/form/partials";
|
||||
|
||||
.new-campaign__form {
|
||||
@include form;
|
||||
width: 480px;
|
||||
}
|
91
templates/panel/main.scss
Normal file
91
templates/panel/main.scss
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@import "./nav/main.scss";
|
||||
@import "../components/button";
|
||||
|
||||
.panel__body {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.panel__container {
|
||||
width: 80%;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.link__btn {
|
||||
@include button;
|
||||
margin: 0px 5px;
|
||||
padding: 0.3rem 0.3rem;
|
||||
padding-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
caption-side: bottom;
|
||||
border-color: #e9ecef;
|
||||
text-align: center;
|
||||
min-width: 50%;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
table > thead {
|
||||
vertical-align: bottom;
|
||||
border-bottom: 1px solid #cdc8ca;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table {
|
||||
th {
|
||||
text-align: center;
|
||||
}
|
||||
td {
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #edddd1;
|
||||
}
|
||||
}
|
||||
|
||||
.asset__container {
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.asset__name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.asset__value {
|
||||
margin: 10px 0;
|
||||
display: inline;
|
||||
width: auto;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
font-family: monospace, monospace;
|
||||
|
||||
background-color: #f2f2f2;
|
||||
padding: 0.125rem 0.25rem;
|
||||
margin: 0 0.25rem;
|
||||
border-radius: 3px;
|
||||
font-size: 1em;
|
||||
color: #1a1a1a;
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
}
|
45
templates/panel/nav/index.html
Normal file
45
templates/panel/nav/index.html
Normal file
|
@ -0,0 +1,45 @@
|
|||
<nav class="nav__container">
|
||||
<input type="checkbox" class="nav__toggle" id="nav__toggle" />
|
||||
|
||||
<div class="nav__header">
|
||||
<a class="nav__logo-container" href="<.= crate::PAGES.home .>">
|
||||
<img src="<.= crate::assets::LOGO.path .>" alt="<.= crate::assets::LOGO.name .>" class="nav__logo" />
|
||||
<p class="nav__logo-text">KAIZEN</p>
|
||||
</a>
|
||||
<label class="nav__hamburger-menu" for="nav__toggle">
|
||||
<span class="nav__hamburger-inner"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="nav__spacer"></div>
|
||||
|
||||
<div class="nav__link-group">
|
||||
<div class="nav__link-container">
|
||||
<a class="nav__link" rel="noreferrer" href="<.= crate::PAGES.home .>"
|
||||
>Home</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="nav__link-container">
|
||||
<a
|
||||
class="nav__link"
|
||||
rel="noreferrer"
|
||||
href="<.= crate::PAGES.panel.campaigns.home .>"
|
||||
>Campaigns</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="nav__link-container">
|
||||
<a class="nav__link" rel="noreferrer" href="/settings">Settings</a>
|
||||
</div>
|
||||
|
||||
<div class="nav__link-container">
|
||||
<a
|
||||
class="nav__link"
|
||||
rel="noreferrer"
|
||||
href="<.= crate::V1_API_ROUTES.admin.auth.logout .>"
|
||||
>Log out</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
75
templates/panel/nav/main.scss
Normal file
75
templates/panel/nav/main.scss
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.nav__container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav__hamburger-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav__spacer {
|
||||
flex: 3;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.nav__logo-container {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.nav__toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav__logo {
|
||||
display: inline-flex;
|
||||
margin: auto;
|
||||
padding: 5px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.nav__logo-text {
|
||||
margin: auto;
|
||||
letter-spacing: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.nav__link-group {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav__link-container {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.nav__link {
|
||||
text-decoration: none;
|
||||
}
|
102
templates/panel/nav/mobile.scss
Normal file
102
templates/panel/nav/mobile.scss
Normal file
|
@ -0,0 +1,102 @@
|
|||
$hamburger-menu-animation: 0.4s ease-out;
|
||||
$nav__hamburger-inner-height: 1.3px;
|
||||
|
||||
.nav__container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nav__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
min-width: 100%;
|
||||
height: 55px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav__link-group {
|
||||
position: sticky;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nav__hamburger-menu {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.nav__spacer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav__toggle:not(:checked) ~ .nav__link-group {
|
||||
max-height: 0;
|
||||
transition: max-height $hamburger-menu-animation;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav__toggle:checked ~ .nav__link-group {
|
||||
max-height: 500px;
|
||||
transition: max-height $hamburger-menu-animation;
|
||||
}
|
||||
|
||||
.nav__toggle:checked ~ .nav__header {
|
||||
.nav__hamburger-inner::after {
|
||||
width: 24px;
|
||||
bottom: $nav__hamburger-inner-height;
|
||||
transform: rotate(-90deg);
|
||||
transition: bottom 0.1s ease-out,
|
||||
transform 0.22s cubic-bezier(0.215, 0.61, 0.355, 1) 0.12s,
|
||||
width 0.1s ease-out;
|
||||
}
|
||||
|
||||
.nav__hamburger-inner::before {
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
transition: top 0.1s ease-out, opacity 0.1s ease-out 0.12s;
|
||||
}
|
||||
|
||||
.nav__hamburger-inner {
|
||||
transform: rotate(225deg);
|
||||
transition-delay: 0.12s;
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.nav__hamburger-inner::after {
|
||||
bottom: -7px;
|
||||
transition: bottom 0.1s ease-in 0.25s,
|
||||
transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19),
|
||||
width 0.1s ease-in 0.25s;
|
||||
}
|
||||
|
||||
.nav__hamburger-inner::after,
|
||||
.nav__hamburger-inner::before {
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav__hamburger-inner::before {
|
||||
top: -7px;
|
||||
transition: top 0.1s ease-in 0.25s, opacity 0.1s ease-in;
|
||||
}
|
||||
|
||||
.nav__hamburger-inner {
|
||||
top: 50%;
|
||||
margin: auto;
|
||||
transition-duration: 0.22s;
|
||||
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
||||
}
|
||||
|
||||
.nav__hamburger-inner,
|
||||
.nav__hamburger-inner::after,
|
||||
.nav__hamburger-inner::before {
|
||||
width: 24px;
|
||||
height: $nav__hamburger-inner-height;
|
||||
position: relative;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.nav__hamburger-menu,
|
||||
.nav__hamburger-inner {
|
||||
display: block;
|
||||
}
|
Loading…
Reference in a new issue