release 0.2.2 #30
14 changed files with 152 additions and 24 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -1211,7 +1211,7 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
|||
|
||||
[[package]]
|
||||
name = "jobboerse"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-multipart",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ members = [".", "packages/*"]
|
|||
|
||||
[package]
|
||||
name = "jobboerse"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
edition = "2021"
|
||||
rust-version = "1.58"
|
||||
repository = "https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse"
|
||||
|
|
|
|||
14
Changelog.md
14
Changelog.md
|
|
@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.2.2] (2022-06-26)
|
||||
|
||||
### Add
|
||||
- faq page
|
||||
|
||||
### Change
|
||||
- better highlight confirm/retract buttons
|
||||
|
||||
## [0.2.1] (2022-03-10)
|
||||
|
||||
### Add
|
||||
|
|
@ -14,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Change
|
||||
- some internal cleanup
|
||||
- reviewer notice email is now send when offer is not pre-approved
|
||||
- instead of when confirmation is not skipped
|
||||
- reviewer notice is now send before confirmation email
|
||||
- confirmation email failure is treated as an error which would prevent the reviewer notice from being sent,
|
||||
while reviewer notice failure is not
|
||||
|
||||
### Fix
|
||||
- confirmation emails now set the UserAgent and Auto-Submitted headers
|
||||
|
|
@ -106,6 +119,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Overview Page of Dependency licenses
|
||||
|
||||
[Unreleased]: https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse/src/main
|
||||
[0.2.2]: https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse/src/version-0.2.2
|
||||
[0.2.1]: https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse/src/version-0.2.1
|
||||
[0.2.0]: https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse/src/version-0.2.0
|
||||
[0.1.6]: https://www.fs-infmath.uni-kiel.de/git/FS-InfMath/Jobboerse/src/version-0.1.6
|
||||
|
|
|
|||
2
dist/arch/PKGBUILD
vendored
2
dist/arch/PKGBUILD
vendored
|
|
@ -9,7 +9,7 @@ _reponame=Jobboerse
|
|||
_pkgname="${_reponame,,}"
|
||||
_features=()
|
||||
pkgname="${_reponame,,}"
|
||||
pkgver=0.2.1
|
||||
pkgver=0.2.2
|
||||
pkgrel=1
|
||||
pkgdesc="FS-InfMath Job-Offer Page"
|
||||
arch=('x86_64') # Other architectures may work
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ pub(crate) async fn send_confirmation_email(
|
|||
|
||||
lettre::AsyncSendmailTransport::new().send(message).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn send_reviewer_notice(email_config: &EmailConfig) {
|
||||
// successfully send a confirmation e-mail now send a notice to our-self
|
||||
|
||||
let message = lettre::Message::builder()
|
||||
|
|
@ -76,7 +80,6 @@ pub(crate) async fn send_confirmation_email(
|
|||
|
||||
match message {
|
||||
Ok(msg) => {
|
||||
dbg!(&msg);
|
||||
if let Err(err) = lettre::AsyncSendmailTransport::new().send(msg).await {
|
||||
warn!("Failed to send remainder {}", err);
|
||||
}
|
||||
|
|
@ -85,6 +88,4 @@ pub(crate) async fn send_confirmation_email(
|
|||
warn!("Failed to construct reminder {}", err)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
21
src/route.rs
21
src/route.rs
|
|
@ -28,6 +28,7 @@ pub(crate) use job_offer::{
|
|||
pub(crate) use license::{LICENSES_ROUTE, LICENSE_BUNDLE};
|
||||
|
||||
use crate::error::PresentationError;
|
||||
use crate::route::job_offer::JOBOFFER_FAQ;
|
||||
use crate::server_config::OperationMode;
|
||||
use crate::server_config::ServerConfig;
|
||||
|
||||
|
|
@ -75,6 +76,7 @@ struct StaticRoutes {
|
|||
logout: Url,
|
||||
sync: Url,
|
||||
index: Url,
|
||||
faq: Url,
|
||||
joboffer_overview: Url,
|
||||
joboffer_create: Url,
|
||||
joboffer_summary: Url,
|
||||
|
|
@ -89,6 +91,7 @@ impl StaticRoutes {
|
|||
let logout_route = req.url_for_static(LOGOUT_ROUTE)?;
|
||||
let sync_route = req.url_for_static(JOBOFFER_SYNC_ROUTE)?;
|
||||
let index_route = req.url_for_static(INDEX_ROUTE)?;
|
||||
let faq_route = req.url_for_static(JOBOFFER_FAQ)?;
|
||||
let joboffer_overview_route = req.url_for_static(JOBOFFER_OVERVIEW_ROUTE)?;
|
||||
let joboffer_creation_route = req.url_for_static(JOBOFFER_CREATION_ROUTE)?;
|
||||
let joboffer_summary_route = req.url_for_static(JOBOFFER_SUMMARY_ROUTE)?;
|
||||
|
|
@ -96,6 +99,7 @@ impl StaticRoutes {
|
|||
let joboffers_bulk_delete_route = req.url_for_static(JOBOFFER_BULK_DELETE_ROUTE)?;
|
||||
|
||||
Ok(StaticRoutes {
|
||||
faq: faq_route,
|
||||
licenses: licenses_route,
|
||||
login: login_route,
|
||||
logout: logout_route,
|
||||
|
|
@ -113,7 +117,7 @@ impl StaticRoutes {
|
|||
#[derive(Serialize)]
|
||||
struct Link<'a> {
|
||||
title: &'a str,
|
||||
url: &'a str,
|
||||
url: Cow<'a, str>,
|
||||
}
|
||||
|
||||
fn base<'a>(
|
||||
|
|
@ -123,18 +127,21 @@ fn base<'a>(
|
|||
) -> Result<BaseData<'a>, UrlGenerationError> {
|
||||
let index_css = req.url_for_static(INDEX_CSS_ROUTE)?.into();
|
||||
|
||||
let static_routes = StaticRoutes::new(req)?;
|
||||
|
||||
let mut default_links = vec![(
|
||||
"Impressum",
|
||||
Some("https://www.fs-infmath.uni-kiel.de/wiki/Fachschaften_Informatik_%26_Mathematik:Impressum"),
|
||||
Some("https://www.fs-infmath.uni-kiel.de/wiki/Fachschaften_Informatik_%26_Mathematik:Impressum".into()),
|
||||
),
|
||||
(
|
||||
"Homepage",
|
||||
crate::PROJECT_HOMEPAGE
|
||||
crate::PROJECT_HOMEPAGE.map(Into::into)
|
||||
),
|
||||
(
|
||||
"Source Repository",
|
||||
crate::PROJECT_REPO,
|
||||
)
|
||||
crate::PROJECT_REPO.map(Into::into),
|
||||
),
|
||||
("FAQ", Some(static_routes.faq.to_string().into()))
|
||||
];
|
||||
|
||||
#[allow(clippy::needless_collect)]
|
||||
|
|
@ -147,7 +154,7 @@ fn base<'a>(
|
|||
default_links.retain(|&(title, _)| title != elem.title);
|
||||
(
|
||||
elem.title.as_str(),
|
||||
elem.url.as_ref().map(|elem| elem.as_str()),
|
||||
elem.url.as_ref().map(|elem| elem.as_str().into()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
|
@ -164,7 +171,7 @@ fn base<'a>(
|
|||
short_lang: "de".into(),
|
||||
styles: vec![index_css],
|
||||
links,
|
||||
routes: StaticRoutes::new(req)?,
|
||||
routes: static_routes,
|
||||
banner: config.config.banner.clone(),
|
||||
operation_mode: config.args.mode.clone(),
|
||||
dev_build: dev_available,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ pub fn configure(service: &mut ServiceConfig) {
|
|||
service
|
||||
.service(index)
|
||||
.service(summary)
|
||||
.service(faq)
|
||||
.service(create::create_joboffer_get)
|
||||
.service(create::create_joboffer_post)
|
||||
.service(confirmation::confirm_joboffer_get)
|
||||
|
|
@ -47,6 +48,38 @@ pub fn configure(service: &mut ServiceConfig) {
|
|||
.service(sync);
|
||||
}
|
||||
|
||||
pub const JOBOFFER_FAQ: &str = "joboffer_faq";
|
||||
|
||||
#[get("/faq", name = "joboffer_faq")]
|
||||
pub(crate) async fn faq(
|
||||
req: HttpRequest,
|
||||
session: Session,
|
||||
config: web::Data<ServerConfig>,
|
||||
hb: web::Data<Handlebars<'_>>,
|
||||
) -> Result<HttpResponse, PresentationError> {
|
||||
let user = User::current(&session).ok();
|
||||
|
||||
let base_data = super::base(&req, &config, "FAQ")?;
|
||||
|
||||
let mail = config
|
||||
.config
|
||||
.email
|
||||
.as_ref()
|
||||
.map(|econf| econf.from.email.to_string());
|
||||
|
||||
let data = json!({
|
||||
"base": base_data,
|
||||
"user": user,
|
||||
"mail": mail,
|
||||
});
|
||||
|
||||
let rendered = hb.render(template::JOBOFFER_FAQ, &data)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.insert_header((CONTENT_TYPE, HTML_CONTENT.clone()))
|
||||
.body(rendered))
|
||||
}
|
||||
|
||||
pub(crate) const JOBOFFER_OVERVIEW_ROUTE: &str = "joboffer_overview";
|
||||
|
||||
#[get("/overview", name = "joboffer_overview")]
|
||||
|
|
|
|||
|
|
@ -215,7 +215,9 @@ pub(crate) async fn create_job_offer<'data, 'config>(
|
|||
|
||||
let is_permanent = user.is_some() && job_offer_form.permanent;
|
||||
|
||||
let review_status = if user.is_some() && job_offer_form.pre_approved {
|
||||
let is_pre_approved = user.is_some() && job_offer_form.pre_approved;
|
||||
|
||||
let review_status = if is_pre_approved {
|
||||
ReviewStatus::Reviewed
|
||||
} else {
|
||||
ReviewStatus::AwaitingReview
|
||||
|
|
@ -246,8 +248,12 @@ pub(crate) async fn create_job_offer<'data, 'config>(
|
|||
|
||||
let created_offer = offers.create_new_offer(now_date, job_offer, config).await?;
|
||||
|
||||
if !skip_confirmation {
|
||||
if let Some(email_config) = &config.config.email {
|
||||
if let Some(email_config) = &config.config.email {
|
||||
if !is_pre_approved {
|
||||
email::send_reviewer_notice(&email_config).await;
|
||||
}
|
||||
|
||||
if !skip_confirmation {
|
||||
let confirm_url = req.url_for(JOBOFFER_CONFIRM_ROUTE, &[created_offer.id(), &token])?;
|
||||
|
||||
email::send_confirmation_email(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ pub(crate) const JOBOFFER_CONFIRM_SUBMISSION: &str = "job_offer/submission-confi
|
|||
pub(crate) const JOBOFFER_CONFIRM_SUBMISSION_SUCCESS: &str = "job_offer/submission-confirm-success";
|
||||
pub(crate) const JOBOFFER_REJECT_SUBMISSION_SUCCESS: &str = "job_offer/submission-rejected-success";
|
||||
pub(crate) const JOBOFFER_DELETE_EXPIRED: &str = "job_offer/delete-expired";
|
||||
pub(crate) const JOBOFFER_FAQ: &str = "job_offer/faq";
|
||||
pub(crate) const AUTH_LOGIN: &str = "auth/login";
|
||||
pub(crate) const LICENCES: &str = "licenses";
|
||||
|
||||
|
|
|
|||
|
|
@ -258,6 +258,10 @@ body main {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.modal-confirm-form {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.modal-confirm-box {
|
||||
display: inline-block;
|
||||
border-style: solid;
|
||||
|
|
@ -268,6 +272,18 @@ input.modal-open-check:not(:checked) + .modal-confirm-box {
|
|||
border-color: transparent;
|
||||
}
|
||||
|
||||
.modal-confirm-box > .modal-open-button.confirm {
|
||||
background-color: lightgreen;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.modal-confirm-box > .modal-open-button.retract {
|
||||
background-color: tomato;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
input.modal-open-check:checked + .modal-confirm-box > .modal-open-button {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<form action="{{> formaction}}" method="post" class="inline">
|
||||
<form class="modal-confirm-form {{> kind}}" action="{{> formaction}}" method="post" class="inline">
|
||||
<input id="{{> kind}}-{{> id}}" class="hidden modal-open-check" type="checkbox" name="pre-{{> kind}}" required>
|
||||
<div class="modal-confirm-box">
|
||||
<label for="{{> kind}}-{{> id}}" class="modal-open-button">{{> action}}</label>
|
||||
<label for="{{> kind}}-{{> id}}" class="modal-cancel-button">Cancel</label>
|
||||
<label for="{{> kind}}-{{> id}}" class="modal-open-button {{> kind}}">{{> action}}</label>
|
||||
<label for="{{> kind}}-{{> id}}" class="modal-cancel-button {{> kind}}">Cancel</label>
|
||||
<button type="submit" class="modal-submit-button">Confirm {{> action}}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
52
templates/job_offer/faq.hb
Normal file
52
templates/job_offer/faq.hb
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{{#> base}}
|
||||
<h1>FAQ</h1>
|
||||
<div>
|
||||
<h2>Was ist zu beachten?</h2>
|
||||
<p>Die Jobbörse wird durch einen Teil der freiwilligen aktiven Mitglieder der Fachschaften betreut,
|
||||
dies kann vor allem außerhalb der Vorlesungszeit und im Prüfungszeitraum zu längeren bearbeitungszeiten bei E-mail-Einreichungen und Reviews führen.</p>
|
||||
|
||||
<p>Die Aktuellen Semester- und Prüfungszeiträume sollten sich <a href="https://www.uni-kiel.de/gf-praesidium/de/termine/semesterzeiten">hier</a> finden.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Laufzeit</h2>
|
||||
<p>Einreichungen werden automatisch entfernt sobald das jeweilige Ablaufdatum verstrichen ist</p>
|
||||
<p>Einreichungen ohne explizit angegebenes Ablaufdatum haben ein implizites Ablaufdatum 6 Monate (180 Tage) nach Einreichung.</p>
|
||||
{{#if mail}}
|
||||
<p>Um eine Einreichung früher zu entfernen informieren sie uns bitte per E-Mail unter <a href="{{mail}}">{{mail}}</a></p>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Entstehen Kosten?</h2>
|
||||
<p>Nein. Die Jobbörse ist ein kostenloses Angebot der Fachschaften.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Wie kann eine Einreichung erfolgen?</h2>
|
||||
<p>Der bevorzugte Weg für Einreichungen ist das <a href="{{base.routes.joboffer_create}}" >Web-Formular</a>.<p/>
|
||||
<p>Eine zügige bearbeitung von Einreichungen per E-Mail kann nicht garantiert werden,
|
||||
insbesondere außerhalb des Vorlesungszeitraums und im Prüfungszeitraum.</p>
|
||||
</div>
|
||||
|
||||
{{#if mail}}
|
||||
<div>
|
||||
<h2>Ich habe keine Bestätigungsmail erhalten!</h2>
|
||||
Die Bestätigungsmail werden automatisch und unverzüglich versand sobald das Web-Formular erfolgreich auf dem Server eingegangen ist und die Einreichung gespeichert wurde.<br />
|
||||
Daraufhin sollten sie zu einer ersten Vorschau der eingereichten Stellenausschreibung gebracht worden sein, mit entsprechendem Text darüber das eine Bestätigungsmail versand wurde.<br />
|
||||
Diese sollten innerhalb weniger Minuten bei ihnen eingehen, meist jedoch schneller.
|
||||
|
||||
Sollten sie nicht Zeitnah eine Bestätigungsmail erhalten,
|
||||
schauen sie bitte erst in ihren Spam/Junk-Ordner und wenden sie sich dann an <a href="{{mail}}">{{mail}}</a>.
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div>
|
||||
<h2>Ich habe den Bestätigungslink geöffnet, aber die Stellenausschreibung ist noch nicht in der Übersicht zu sehen.</h2>
|
||||
Dies kann primär zwei Gründe haben:
|
||||
<ol>
|
||||
<li>Sie haben zwar den Link geöffnet, aber unter der Vorschau nicht auf bestätigen/veröffentlichen geklickt.</li>
|
||||
<li>Es ist unsererseits noch kein review der Einreichung erfolgt.</li>
|
||||
</ol>
|
||||
</div>
|
||||
{{/base}}
|
||||
|
|
@ -68,7 +68,6 @@
|
|||
<div>ID: {{job_offer.id}}</div>
|
||||
<div>Review Status: <span class="{{#unless job_offer.reviewed}}unreviewed{{/unless}}">{{job_offer.status.review_status}}</span></div>
|
||||
<div>Confirmation Status: <span class="{{#unless job_offer.confirmed}}unconfirmed{{/unless}}">{{job_offer.status.confirmation_status.type}}</span></div>
|
||||
{{log job_offer.actions}}
|
||||
{{#if job_offer.actions.confirmation_link}}
|
||||
<div><a href="mailto:{{job_offer.contact_data}}?body=Confirmation%20Link:%20{{job_offer.actions.confirmation_link}}" >Manual Confirmation Mail</a></div>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
{{#> base}}
|
||||
<div class="centered column">
|
||||
<div>
|
||||
<div class="preview">
|
||||
<div class="preview">
|
||||
<h2>Vorschau:</h2>
|
||||
|
||||
{{> job_offer/overview-entry}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="confirmation-actions">
|
||||
{{#> confirm-modal}}
|
||||
{{#*inline "id"}}{{job_offer.id}}{{/inline}}
|
||||
{{#*inline "kind"}}confirm{{/inline}}
|
||||
{{#*inline "action"}}Bestätigen{{#if job_offer.reviewed}} und veröffentlichen!{{/if}}{{/inline}}
|
||||
{{#*inline "formaction"}}{{job_offer.actions.confirm_url}}{{/inline}}
|
||||
{{/confirm-modal}}
|
||||
|
||||
{{#> confirm-modal}}
|
||||
{{#*inline "id"}}{{job_offer.id}}{{/inline}}
|
||||
{{#*inline "kind"}}retract{{/inline}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue