Browse Source

Current state

master
Keanu D?lle 2 years ago
parent
commit
7b7f320896
  1. 4
      Cargo.toml
  2. 4
      ERMS-config.toml
  3. 3
      src/database/profile.rs
  4. 254
      src/database/profile_communication.rs
  5. 0
      src/errors/error.rs
  6. 9
      src/lang/lang.rs
  7. 98
      src/lang/mod.rs
  8. 35
      src/lang/setup.rs
  9. 2
      src/main.rs
  10. 22
      src/modules/profile.rs
  11. 10
      src/sitebuilder/profile_communication.rs
  12. 3
      static/html/templates/error.html
  13. 5
      static/html/templates/internal-site.html
  14. 16
      static/html/templates/profile/communication_entry.html
  15. 2
      static/js/portal.js

4
Cargo.toml

@ -14,4 +14,6 @@ rust-argon2="0.5.1"
rand="0.7.2"
mysql = "*"
config = "*"
chrono = "0.4"
chrono = "0.4"
fluent = "0.9.1"
unic-langid = "0.7.1"

4
ERMS-config.toml

@ -2,4 +2,6 @@ mysql_host = "localhost"
mysql_username = "mysql"
mysql_password = "qwertz"
mysql_port = 3306
mysql_database = "ERMS"
mysql_database = "ERMS"
default_language = "de-DE"
fallback_language = "en-US"

3
src/database/profile.rs

@ -148,11 +148,12 @@ pub fn get_profile_data(id : i32) -> Option<ProfileData>{
}).unwrap()
}
pub fn insert_profile_data(id : i32, user_permissions : &UserPermissions, data : Form<ProfileFormData>) -> bool{
pub fn update_profile_data(id : i32, user_permissions : &UserPermissions, data : Form<ProfileFormData>) -> bool{
let pool = connect();
let old_data = get_profile_data(id).unwrap();
let data = check_profile_data_permissions(user_permissions, data, old_data);
debug!("Form: {}", data.firstname);
let mut stmt = pool.prepare(r"UPDATE users SET firstname = :firstname, lastname = :lastname, email = :email, birthplace = :birthplace, date_of_birth = :date_of_birth, sex = :sex, academic_title = :academic_title, salutation = :salutation, formal_salutation = :formal_salutation, personnel_number = :personnel_number, street = :street, street_number = :street_number, postcode = :postcode, place = :place WHERE id = :id").unwrap();
stmt.execute(params!{

254
src/database/profile_communication.rs

@ -3,7 +3,11 @@
use std::collections::HashMap;
use crate::database::connection::connect;
use crate::database::profile::StringConvert;
use rocket::request::Form;
use mysql::Pool;
use crate::modules::permissions::{UserPermissions, check_for_permission};
#[derive(Debug, Clone, Copy)]
pub enum UserCommunicationVisibility{
Private,
Limited,
@ -13,7 +17,7 @@ pub enum UserCommunicationVisibility{
#[derive(FromForm)]
pub struct UserCommunicationFormEntry{
pub profile_communication_id : i32,
pub profile_communication_description : String,
pub profile_communication_description : Option<String>,
pub profile_communication_type : String,
pub profile_communication_visibility : String,
pub profile_communication_value : String
@ -42,13 +46,21 @@ pub struct UserCommunicationData{
impl StringConvert<UserCommunicationVisibility> for UserCommunicationVisibility{
fn string_convert(&self) -> String{
match self{
UserCommunicationVisibility::Private => String::from("privat"),
UserCommunicationVisibility::Limited => String::from("bedingt sichtbar"),
UserCommunicationVisibility::Public => String::from("öffentlich")
UserCommunicationVisibility::Private => String::from("0"),
UserCommunicationVisibility::Limited => String::from("1"),
UserCommunicationVisibility::Public => String::from("2")
}
}
}
pub fn visibility_generate_label(visibility : UserCommunicationVisibility) -> String{
match visibility{
UserCommunicationVisibility::Private => String::from("privat"),
UserCommunicationVisibility::Limited => String::from("bedingt sichtbar"),
UserCommunicationVisibility::Public => String::from("öffentlich")
}
}
fn visibility_from_i8(visibility : i8) -> UserCommunicationVisibility{
match visibility{
0 => UserCommunicationVisibility::Private,
@ -58,6 +70,14 @@ fn visibility_from_i8(visibility : i8) -> UserCommunicationVisibility{
}
}
fn visibility_to_i8(visibility : UserCommunicationVisibility) -> i8{
match visibility{
UserCommunicationVisibility::Private => 0,
UserCommunicationVisibility::Limited => 1,
UserCommunicationVisibility::Public => 2
}
}
pub fn get_communication_data(userid : i32) -> UserCommunicationData{
let mut communication_data = UserCommunicationData{
emails: HashMap::new(),
@ -66,39 +86,235 @@ pub fn get_communication_data(userid : i32) -> UserCommunicationData{
let pool = connect();
//Grep phone data
pool.prep_exec(r"SELECT id, country_prefix, number, description, visibility FROM communication_phone_numbers WHERE f_users_id = :user_id", params!{"user_id" => userid}).map(|mut result|{
//Grep phone and email data
communication_data.phone_numbers = get_communication_data_phone_numbers(&pool, userid);
communication_data.emails = get_communication_data_emails(&pool, userid);
//Return collected data
communication_data
}
fn get_communication_data_emails(pool : &Pool, userid : i32) -> HashMap<i32, UserCommunicationEmail>{
let mut emails : HashMap<i32, UserCommunicationEmail> = HashMap::new();
pool.prep_exec(r"SELECT id, email, description, visibility FROM communication_email_addresses WHERE f_users_id = :user_id", params!{"user_id" => userid}).map(|mut result|{
while let Some(row) = result.next() {
let mut row = row.unwrap().clone();
let id = row.take("id").unwrap();
let number = UserCommunicationPhoneNumber{
let email = UserCommunicationEmail{
id,
country_prefix: row.take("country_prefix").unwrap(),
number: row.take("number").unwrap(),
description: row.take("description"),
email: row.take("email").unwrap(),
description: row.take("description").unwrap_or(None),
visibility: visibility_from_i8(row.take("visibility").unwrap())
};
communication_data.phone_numbers.insert(id, number);
emails.insert(id, email);
}
}).unwrap();
emails
}
//Grep email data
pool.prep_exec(r"SELECT id, email, description, visibility FROM communication_email_addresses WHERE f_users_id = :user_id", params!{"user_id" => userid}).map(|mut result|{
fn get_communication_data_phone_numbers(pool : &Pool, userid : i32) -> HashMap<i32, UserCommunicationPhoneNumber>{
let mut numbers : HashMap<i32, UserCommunicationPhoneNumber> = HashMap::new();
pool.prep_exec(r"SELECT id, country_prefix, number, description, visibility FROM communication_phone_numbers WHERE f_users_id = :user_id", params!{"user_id" => userid}).map(|mut result|{
while let Some(row) = result.next() {
let mut row = row.unwrap().clone();
let id = row.take("id").unwrap();
let email = UserCommunicationEmail{
let number = UserCommunicationPhoneNumber{
id,
email: row.take("email").unwrap(),
description: row.take("description"),
country_prefix: row.take("country_prefix").unwrap(),
number: row.take("number").unwrap(),
description: row.take("description").unwrap_or(None),
visibility: visibility_from_i8(row.take("visibility").unwrap())
};
communication_data.emails.insert(id, email);
numbers.insert(id, number);
}
}).unwrap();
numbers
}
//Return collected data
communication_data
pub fn add_communication_data_email (user_id : i32, user_permissions : &UserPermissions, data : Form<UserCommunicationFormEntry>) {
if !check_for_permission("modules.add.profile.own.communication.email", user_permissions){
return;
}
let pool = connect();
let visibility :i8 = data.profile_communication_visibility.parse().unwrap();
let mut stmt = pool.prepare(r"INSERT INTO communication_email_addresses (f_users_id, email, description, visibility) VALUES (:user_id, :email, :description, :visibility)").unwrap();
stmt.execute(params!{
"user_id" => user_id,
"email" => data.profile_communication_value.clone(),
"description" => data.profile_communication_description.clone(),
"visibility" => visibility
}).unwrap();
}
/*pub fn add_communication_data_phone_number (user_id : i32, user_permissions : &UserPermissions, data : Form<UserCommunicationFormEntry>){
if !check_for_permission("modules.add.profile.own.communication.phone_number", user_permissions){
return;
}
let pool = connect();
let mut stmt = pool.prepare(r"INSERT INTO communication_phone_numbers (f_users_id, country_prefix, number, description, visibility) VALUES (:user_id, :country_prefix, :number, :description, :visibility)").unwrap();
stmt.execute(params!{
"user_id" => user_id,
"country_prefix" => data.country_prefix.clone(),
"number" => data.number,
"description" => data.description.clone(),
"visibility" => visibility_to_i8(data.visibility.clone())
}).unwrap();
}*/
pub enum FormTypes{
Email(UserCommunicationEmail),
Phone(UserCommunicationPhoneNumber)
}
fn parse_phone_number_from_string(number : String) -> Option<((i16, i64))>{
let mut parts: Vec<&str> = number.split(' ').collect();
if parts.len() > 0{
let country_code: i16 = parts[0].parse().unwrap();
parts.remove(0);
let number : String = parts.iter().map(|string| string.to_string()).collect();
let number: i64 = number.parse().unwrap();
Some((country_code, number))
}else{
None
}
}
pub fn parse_communication_form_entry(data : Form<UserCommunicationFormEntry>) -> Option<FormTypes>{
let visibility :i8 = data.profile_communication_visibility.parse().unwrap();
if data.profile_communication_type == "email"{
let data = UserCommunicationEmail{
id: data.profile_communication_id,
email: data.profile_communication_value.clone(),
description: data.profile_communication_description.clone(),
visibility: visibility_from_i8(visibility)
};
Some(FormTypes::Email(data))
}else if data.profile_communication_type == "phone"{
let (country_prefix, number) = parse_phone_number_from_string(data.profile_communication_value.clone()).unwrap();
let data = UserCommunicationPhoneNumber{
id: data.profile_communication_id,
country_prefix,
description: data.profile_communication_description.clone(),
visibility: visibility_from_i8(visibility),
number
};
Some(FormTypes::Phone(data))
}else{
None
}
}
pub fn update_communication_data_email(user_id : i32, user_permissions : &UserPermissions, data : UserCommunicationEmail) {
let pool = connect();
let old_data = get_communication_data_emails(&pool, user_id);
if !old_data.contains_key(&data.id){
debug!("Submitted wrong communication data id: {}", &data.id);
return;
}
let old_data = old_data.get(&data.id).unwrap();
let data = check_communication_data_email_permissions(user_permissions, data, old_data);
let mut stmt = pool.prepare(r"UPDATE communication_email_addresses SET email = :email, description = :description, visibility = :visibility WHERE id = :id").unwrap();
stmt.execute(params!{
"id" => data.id,
"email" => data.email,
"description" => data.description,
"visibility" => visibility_to_i8(data.visibility)
}).unwrap();
}
fn check_communication_data_email_permissions(user_permissions : &UserPermissions, new_data: UserCommunicationEmail, old_data : &UserCommunicationEmail) -> UserCommunicationEmail {
let mut data : UserCommunicationEmail = UserCommunicationEmail{
id: old_data.id,
email: "".to_string(),
description: None,
visibility: UserCommunicationVisibility::Private
};
if !check_for_permission("modules.edit.profile.own.communication.email.email", &user_permissions) {
data.email = old_data.email.clone();
}else{
data.email = new_data.email.clone();
}
if !check_for_permission("modules.edit.profile.own.communication.email.description", &user_permissions) {
data.description = old_data.description.clone();
}else{
data.description = new_data.description.clone();
}
if !check_for_permission("modules.edit.profile.own.communication.email.visibility", &user_permissions) {
data.visibility = old_data.visibility.clone();
}else{
data.visibility = new_data.visibility.clone();
}
new_data
}
pub fn update_communication_data_phone_number(user_id : i32, user_permissions : &UserPermissions, data : UserCommunicationPhoneNumber) {
let pool = connect();
let old_data = get_communication_data_phone_numbers(&pool, user_id);
if !old_data.contains_key(&data.id){
debug!("Submitted wrong communication data id: {}", &data.id);
return;
}
let old_data = old_data.get(&data.id).unwrap();
let data = check_communication_data_phone_permissions(user_permissions, data, old_data);
let mut stmt = pool.prepare(r"UPDATE communication_phone_numbers SET number = :number, country_prefix = :country_prefix, description = :description, visibility = :visibility WHERE id = :id").unwrap();
stmt.execute(params!{
"id" => data.id,
"number" => data.number,
"country_prefix" => data.country_prefix,
"description" => data.description,
"visibility" => visibility_to_i8(data.visibility)
}).unwrap();
}
fn check_communication_data_phone_permissions(user_permissions : &UserPermissions, new_data: UserCommunicationPhoneNumber, old_data : &UserCommunicationPhoneNumber) -> UserCommunicationPhoneNumber {
let mut data : UserCommunicationPhoneNumber = UserCommunicationPhoneNumber{
id: old_data.id,
country_prefix: 0,
description: None,
visibility: UserCommunicationVisibility::Private,
number: 0
};
if !check_for_permission("modules.edit.profile.own.communication.phone_number.number", &user_permissions) {
data.number = old_data.number;
}else{
data.number = new_data.number;
}
if !check_for_permission("modules.edit.profile.own.communication.phone_number.country_prefix", &user_permissions) {
data.country_prefix = old_data.country_prefix;
}else{
data.country_prefix = new_data.country_prefix;
}
if !check_for_permission("modules.edit.profile.own.communication.phone_number.description", &user_permissions) {
data.description = old_data.description.clone();
}else{
data.description = new_data.description.clone();
}
if !check_for_permission("modules.edit.profile.own.communication.phone_number.visibility", &user_permissions) {
data.visibility = old_data.visibility.clone();
}else{
data.visibility = new_data.visibility.clone();
}
new_data
}

0
src/errors/error.rs

9
src/lang/lang.rs

@ -0,0 +1,9 @@
use fluent::{FluentBundle, FluentValue, FluentResource, FluentArgs};
pub fn get(id : String, args : Vec<String>) -> String{
String::from(id)
}
pub fn get_simple(id : String) -> String{
get(id, vec!())
}

98
src/lang/mod.rs

@ -0,0 +1,98 @@
use std::collections::HashMap;
use fluent::{FluentBundle, FluentResource, FluentArgs};
use unic_langid::LanguageIdentifier;
use std::sync::RwLock;
use crate::SETTINGS;
pub mod lang;
pub mod setup;
lazy_static!(
static ref LM: RwLock<LanguageManager> = {
RwLock::new(LanguageManager{
bundles: HashMap::new()
})
};
);
pub struct LanguageManager{
pub(crate) bundles : HashMap<LanguageIdentifier, FluentBundle<FluentResource>>
}
impl LanguageManager{
pub fn add_bundle(&mut self, langid : LanguageIdentifier, bundle : FluentBundle<FluentResource>){
self.bundles.insert(langid, bundle);
}
pub fn get(&self, key : &str, langid : LanguageIdentifier, args : FluentArgs) -> Option<String>{
match self.get_message(key, langid, args.clone()){
Some(msg) => Some(msg),
None => {
let langid: LanguageIdentifier = match SETTINGS.read().unwrap().get::<String>("fallback_language").unwrap().parse() {
Ok(langid) => langid,
Err(_) => {
warn!("Couldn't parse fallback_language {}", SETTINGS.read().unwrap().get::<String>("fallback_language").unwrap());
return None;
}
};
match self.get_message(key, langid.clone(), args) {
Some(msg) => Some(msg),
None => {
warn!("Couldn't find msg {} neither in {} nor in the fallback language.", key, langid);
None
}
}
}
}
}
fn get_message(&self, key : &str, langid : LanguageIdentifier, args : FluentArgs) -> Option<String> {
let bundle = match self.bundles.get(&langid){
Some(bundle) => bundle,
None => {
warn!("Couldn't find bundle for langid {}", langid);
return None;
}
};
match bundle.get_message(key) {
Some(msg) => match msg.value{
Some(pattern) => {
let mut errors = vec![];
return Some(bundle.format_pattern(&pattern, Some(&args), &mut errors).as_ref().to_string())},
None => {
warn!("Message {} is empty!", key);
return None;
}
},
None => {
warn!("Couldn't find message {} for langid {}", key, langid);
None
}
}
}
}
#[cfg(test)]
mod language_tests {
use fluent::{FluentBundle, FluentResource};
use unic_langid::LanguageIdentifier;
use super::*;
use crate::lang::setup::create_bundle;
#[test]
fn add_bundle(){
let langid: LanguageIdentifier = "en-US".parse().expect("Parsing failed.");
LM.write().unwrap().add_bundle(langid.clone(), FluentBundle::new(&[langid.clone()]));
assert!(LM.read().unwrap().bundles.contains_key(&langid))
}
#[test]
fn create_bundle_empty_string(){
let langid: LanguageIdentifier = "en-US".parse().expect("Parsing failed.");
let input = String::from("");
assert!(create_bundle(input, langid).is_none())
}
}

35
src/lang/setup.rs

@ -0,0 +1,35 @@
use fluent::{FluentBundle, FluentValue, FluentResource, FluentArgs};
use unic_langid::LanguageIdentifier;
use crate::lang::LanguageManager;
use std::collections::HashMap;
use fluent::FluentError;
/// Imports all language files from lang/
/// TODO: complete
pub fn load_languages(){
}
/// Creates bundle from string + langid
pub fn create_bundle(input : String, langid : LanguageIdentifier) -> Option<FluentBundle<FluentResource>>{
let (resource, errors) = match FluentResource::try_new(input){
Ok(resource) => (resource, vec!()),
Err((resource, errors)) => (resource, errors)
};
for error in errors{
warn!("ParserError for langid {} at {}:{}", langid, error.pos.0, error.pos.1);
}
let mut bundle = FluentBundle::new(&[langid.clone()]);
match bundle.add_resource(resource){
Ok(bundle) => bundle,
Err(errors) => {
for error in errors{
error!("ParserError for langid {}: {}", langid, error);
}
return None},
}
return Some(bundle);
}

2
src/main.rs

@ -17,6 +17,7 @@ use rocket_contrib::serve::StaticFiles;
pub mod database;
pub mod modules;
pub mod sitebuilder;
pub mod lang;
lazy_static! {
static ref SETTINGS: RwLock<Config> = RwLock::new(Config::default());
@ -24,7 +25,6 @@ lazy_static! {
#[get("/?<error>")]
pub fn site_main(error: Option<String>) -> Result<content::Html<String>, Status>{
//let header = sitebuilder::builder::build("static/html/templates/header.html", vec!(("title".to_string(), "ERMS".to_string()), sitebuilder::stylesheets::parse_pair(vec!("test1.css")))).unwrap();
let mut error = match error{
Some(error) => error,
None => String::from("")

22
src/modules/profile.rs

@ -8,7 +8,7 @@ use crate::sitebuilder::builder::build;
use crate::{database, sitebuilder};
use crate::database::profile::ProfileFormData;
use rocket::request::Form;
use crate::database::profile_communication::{UserCommunicationData, UserCommunicationFormEntry};
use crate::database::profile_communication::{UserCommunicationData, UserCommunicationFormEntry, parse_communication_form_entry, FormTypes, update_communication_data_email, update_communication_data_phone_number};
#[get("/portal/profile?<section>")]
pub fn profile_get(userdata : UserData, section : Option<String>) -> Result<content::Html<String>, Status>{
@ -28,21 +28,31 @@ pub fn profile_post(userdata : UserData, section : Option<String>, form_profile
}
if check_for_permission("modules.edit.profile.own", &user_permissions){
database::profile::insert_profile_data(userdata.id, &user_permissions, form_profile);
database::profile::update_profile_data(userdata.id, &user_permissions, form_profile);
}
return Ok(content::Html(format!("{}", profile(userdata, section, &user_permissions))))
}
#[post("/portal/profile?section=communication", data="<form_profile>")]
pub fn profile_communication_post(userdata : UserData, form_profile : Form<UserCommunicationFormEntry>) -> Result<content::Html<String>, Status>{
#[post("/portal/profile?section=communication&action=update", data="<form_entry>")]
pub fn profile_communication_post(userdata : UserData, form_entry : Form<UserCommunicationFormEntry>) -> Result<content::Html<String>, Status>{
let user_permissions = crate::database::permissions::get_permissions(userdata.id);
if !check_for_permission("modules.edit.communication.own", &user_permissions){
return Ok(content::Html(format!("No access!")));
}
if check_for_permission("modules.edit.communication.own", &user_permissions){
debug!("WORKS!!!!");
match parse_communication_form_entry(form_entry){
Some(entry) => {
match entry{
FormTypes::Email(email) => {
update_communication_data_email(userdata.id, &user_permissions, email)
},
FormTypes::Phone(phone) => {
update_communication_data_phone_number(userdata.id, &user_permissions, phone)
}
}
},
None => {}
}
return Ok(content::Html(format!("{}", profile(userdata, Some("communication".to_string()), &user_permissions))))

10
src/sitebuilder/profile_communication.rs

@ -1,4 +1,4 @@
use crate::database::profile_communication::{UserCommunicationData, UserCommunicationEmail, UserCommunicationPhoneNumber};
use crate::database::profile_communication::{UserCommunicationData, UserCommunicationEmail, UserCommunicationPhoneNumber, visibility_generate_label};
use std::collections::HashMap;
use crate::sitebuilder::builder::build;
use crate::database::profile::StringConvert;
@ -11,14 +11,18 @@ fn parse_email(emails : HashMap<i32, UserCommunicationEmail>) -> String {
let mut output = String::from("");
for (id, email) in emails{
output.push_str(&build("static/html/templates/profile/communication_entry.html", vec!(("id".to_string(), id.to_string()), ("type".to_string(), "E-Mail Adresse".to_string()), ("value".to_string(), email.email), ("description".to_string(), email.description.string_convert()), ("visibility".to_string(), email.visibility.string_convert()))).unwrap());
output.push_str(&build("static/html/templates/profile/communication_entry.html", vec!(("id".to_string(), id.to_string()), ("type".to_string(), "email".to_string()), ("type_label".to_string(), "E-Mail Adresse".to_string()), ("value".to_string(), email.email), ("description".to_string(), email.description.string_convert()), ("visibility_label".to_string(), visibility_generate_label(email.visibility)), ("visibility".to_string(), email.visibility.string_convert()))).unwrap());
}
output
}
fn parse_phone(numbers : HashMap<i32, UserCommunicationPhoneNumber>) -> String{
let output = String::from("");
let mut output = String::from("");
for (id, phone) in numbers{
output.push_str(&build("static/html/templates/profile/communication_entry.html", vec!(("id".to_string(), id.to_string()), ("type".to_string(), "phone".to_string()), ("type_label".to_string(), "Telefonnummer".to_string()), ("value".to_string(), format!("+{} {}", phone.country_prefix, phone.number)), ("description".to_string(), phone.description.string_convert()), ("visibility_label".to_string(), visibility_generate_label(phone.visibility)), ("visibility".to_string(), phone.visibility.string_convert()))).unwrap());
}
output
}

3
static/html/templates/error.html

@ -0,0 +1,3 @@
<div class="alert alert-danger" role="alert">
[[message]]
</div>

5
static/html/templates/internal-site.html

@ -1,6 +1,9 @@
<div class="container-fluid d-flex flex-column h-100 m-0 r-0">
<div class="row">[[headerbar]]</div>
<div class="row h-100">[[sidebar]]
<div class="col-lg-10 main">[[content]]</div>
<div class="col-lg-10 main">
[[error]]
[[content]]
</div>
</div>
</div>

16
static/html/templates/profile/communication_entry.html

@ -1,16 +1,16 @@
<form action="/portal/profile?section=communication" class="profile-communication-form" method="post">
<form action="/portal/profile?section=communication&action=update " class="profile-communication-form" method="post">
<div class="divTableRow">
<input name="profile_communication_id" type="hidden" value="[[id]]">
<div class="divTableCell"><span class="profile-communication-input-field-select-span">[[type]]</span><select class="form-control profile_communication_type profile-communication-input-field-select" name="profile_communication_type" value="[[type]]">
<option id="email">E-Mail Adresse</option>
<option id="phone">Telefonnummer</option>
<div class="divTableCell"><span class="profile-communication-input-field-select-span">[[type_label]]</span><select class="form-control profile_communication_type profile-communication-input-field-select" name="profile_communication_type" value="[[type]]">
<option value="email">E-Mail Adresse</option>
<option value="phone">Telefonnummer</option>
</select></div>
<div class="divTableCell"><input class="form-control profile-communication-input-field" name="profile_communication_value" readonly="readonly" type="text" value="[[value]]" /></div>
<div class="divTableCell"><input class="form-control profile-communication-input-field" name="profile_communication_description" readonly="readonly" type="text" value="[[description]]" /></div>
<div class="divTableCell"><span class="profile-communication-input-field-select-span">[[visibility]]</span><select class="form-control profile_communication_visibility profile-communication-input-field-select" name="profile_communication_visibility" value="[[visibility]]">
<option>privat</option>
<option>bedingt sichtbar</option>
<option>öffentlich</option>
<div class="divTableCell"><span class="profile-communication-input-field-select-span">[[visibility_label]]</span><select class="form-control profile_communication_visibility profile-communication-input-field-select" name="profile_communication_visibility" value="[[visibility]]">
<option value="0">privat</option>
<option value="1">bedingt sichtbar</option>
<option value="2">öffentlich</option>
</select></div>
<div class="divTableCell"><button class="profile-communication-edit profile-communication-button" type="button"><img alt="Bearbeiten" class="profile-communication-img" src="/img/edit.png" /></button> <button class="profile-communication-save profile-communication-button" style="display: none;" type="button"><img alt="Speichern" class="profile-communication-img" src="/img/save.png" /></button></div>
</div></form>

2
static/js/portal.js

@ -53,6 +53,6 @@ $( document ).ready(function() {
});
$('.profile-communication-save').click(function(){
$('.profile-communication-form').submit();
$(this).closest("form").submit();
})
});
Loading…
Cancel
Save