prepared file upload
This commit is contained in:
parent
e6e625306d
commit
9e7850a4a1
@ -18,7 +18,7 @@ apply plugin: 'war'
|
||||
apply plugin: 'application'
|
||||
|
||||
group = 'de.jottyfan.camporganizer'
|
||||
version = '0.2.8'
|
||||
version = '0.2.9'
|
||||
sourceCompatibility = 17
|
||||
mainClassName = "de.jottyfan.camporganizer.Main"
|
||||
|
||||
|
@ -13,6 +13,7 @@ import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
@ -34,6 +35,17 @@ public class AdminController extends CommonController {
|
||||
@Value("${spring.mail.username}")
|
||||
private String from;
|
||||
|
||||
@GetMapping("/admin")
|
||||
public String getMain(Model model, HttpServletRequest request) {
|
||||
super.setupSession(model, request);
|
||||
return "/admin/main";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/main")
|
||||
public String getMainDirectly() {
|
||||
return "redirect:/admin/main";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/mail")
|
||||
public String getMail(Model model, HttpServletRequest request) {
|
||||
super.setupSession(model, request);
|
||||
@ -50,21 +62,44 @@ public class AdminController extends CommonController {
|
||||
super.setupSession(model, request);
|
||||
if (bindingResult.hasErrors()) {
|
||||
for (ObjectError error : bindingResult.getAllErrors())
|
||||
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
|
||||
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
|
||||
return "/admin/mail";
|
||||
}
|
||||
service.sendMail(bean);
|
||||
return "redirect:/admin";
|
||||
}
|
||||
|
||||
@GetMapping("/admin")
|
||||
public String getMain(Model model, HttpServletRequest request) {
|
||||
@GetMapping("/admin/document")
|
||||
public String getDocuments(Model model, HttpServletRequest request) {
|
||||
super.setupSession(model, request);
|
||||
return "/admin/main";
|
||||
model.addAttribute("documents", service.getAllDocuments());
|
||||
return "/admin/document";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/main")
|
||||
public String getMainDirectly() {
|
||||
return "redirect:/admin/main";
|
||||
@GetMapping("/admin/document/add")
|
||||
public String prepareAddDocument(Model model, HttpServletRequest request) {
|
||||
super.setupSession(model, request);
|
||||
model.addAttribute("bean", new DocumentBean());
|
||||
return "/admin/document_edit";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/document/edit/{id}")
|
||||
public String prepareAddDocument(@PathVariable Integer id, Model model, HttpServletRequest request) {
|
||||
super.setupSession(model, request);
|
||||
model.addAttribute("bean", service.getDocument(id));
|
||||
return "/admin/document_edit";
|
||||
}
|
||||
|
||||
@PostMapping("/admin/document/update")
|
||||
public String updateDocument(@Valid @ModelAttribute("bean") DocumentBean bean,
|
||||
final BindingResult bindingResult, Model model, HttpServletRequest request) {
|
||||
super.setupSession(model, request);
|
||||
if (bindingResult.hasErrors()) {
|
||||
for (ObjectError error : bindingResult.getAllErrors())
|
||||
LOGGER.error("error {}: {}", error.getCode(), error.getDefaultMessage());
|
||||
return "/admin/document_edit";
|
||||
}
|
||||
service.updateDocument(bean);
|
||||
return "redirect:/admin/document";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,186 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENT;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENTROLE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DeleteConditionStep;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.InsertResultStep;
|
||||
import org.jooq.InsertReturningStep;
|
||||
import org.jooq.Record5;
|
||||
import org.jooq.SelectSeekStep1;
|
||||
import org.jooq.UpdateConditionStep;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentroleRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class AdminRepository {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(AdminRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
||||
|
||||
/**
|
||||
* get the document with that ID
|
||||
*
|
||||
* @param id the ID of the document
|
||||
* @return the document
|
||||
*/
|
||||
public DocumentBean getDocument(Integer id) {
|
||||
Field<EnumCamprole[]> ROLES = DSL.field("roles", EnumCamprole[].class);
|
||||
SelectSeekStep1<Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]>, Integer> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_DOCUMENT.PK,
|
||||
T_DOCUMENT.NAME,
|
||||
T_DOCUMENT.DOCTYPE,
|
||||
T_DOCUMENT.FILETYPE,
|
||||
DSL.arrayAgg(T_DOCUMENTROLE.CAMPROLE).as(ROLES))
|
||||
.from(T_DOCUMENT)
|
||||
.leftJoin(T_DOCUMENTROLE).on(T_DOCUMENTROLE.FK_DOCUMENT.eq(T_DOCUMENT.PK))
|
||||
.where(T_DOCUMENT.PK.eq(id))
|
||||
.groupBy(T_DOCUMENT.PK, T_DOCUMENT.NAME, T_DOCUMENT.DOCTYPE, T_DOCUMENT.FILETYPE)
|
||||
.orderBy(T_DOCUMENT.PK);
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r = sql.fetchOne();
|
||||
if (r != null ) {
|
||||
DocumentBean bean = new DocumentBean();
|
||||
bean.setPk(r.get(T_DOCUMENT.PK));
|
||||
bean.setName(r.get(T_DOCUMENT.NAME));
|
||||
bean.setDoctype(r.get(T_DOCUMENT.DOCTYPE));
|
||||
bean.setFiletype(r.get(T_DOCUMENT.FILETYPE));
|
||||
bean.setRoles(r.get(ROLES));
|
||||
return bean;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all documents from the database
|
||||
*
|
||||
* @return all documents
|
||||
*/
|
||||
public List<DocumentBean> getAllDocuments() {
|
||||
Field<EnumCamprole[]> ROLES = DSL.field("roles", EnumCamprole[].class);
|
||||
SelectSeekStep1<Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]>, Integer> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_DOCUMENT.PK,
|
||||
T_DOCUMENT.NAME,
|
||||
T_DOCUMENT.DOCTYPE,
|
||||
T_DOCUMENT.FILETYPE,
|
||||
DSL.arrayAgg(T_DOCUMENTROLE.CAMPROLE).as(ROLES))
|
||||
.from(T_DOCUMENT)
|
||||
.leftJoin(T_DOCUMENTROLE).on(T_DOCUMENTROLE.FK_DOCUMENT.eq(T_DOCUMENT.PK))
|
||||
.groupBy(T_DOCUMENT.PK, T_DOCUMENT.NAME, T_DOCUMENT.DOCTYPE, T_DOCUMENT.FILETYPE)
|
||||
.orderBy(T_DOCUMENT.PK);
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
List<DocumentBean> list = new ArrayList<>();
|
||||
for (Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r : sql.fetch()) {
|
||||
DocumentBean bean = new DocumentBean();
|
||||
bean.setPk(r.get(T_DOCUMENT.PK));
|
||||
bean.setName(r.get(T_DOCUMENT.NAME));
|
||||
bean.setDoctype(r.get(T_DOCUMENT.DOCTYPE));
|
||||
bean.setFiletype(r.get(T_DOCUMENT.FILETYPE));
|
||||
bean.setRoles(r.get(ROLES));
|
||||
list.add(bean);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* upsert document in t_document
|
||||
*
|
||||
* @param document
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
public Integer upsert(DocumentBean bean) throws DataAccessException {
|
||||
LambdaResultWrapper lrw = new LambdaResultWrapper();
|
||||
jooq.transaction(c -> {
|
||||
Integer pk = bean.getPk();
|
||||
if (bean.getPk() != null) {
|
||||
UpdateConditionStep<TDocumentRecord> sql = DSL.using(c)
|
||||
// @formatter:off
|
||||
.update(T_DOCUMENT)
|
||||
.set(T_DOCUMENT.NAME, bean.getName())
|
||||
.set(T_DOCUMENT.DOCTYPE, bean.getDoctype())
|
||||
.set(T_DOCUMENT.DOCUMENT, bean.getDocument())
|
||||
.set(T_DOCUMENT.FILETYPE, bean.getFiletype())
|
||||
.where(T_DOCUMENT.PK.eq(bean.getPk()));
|
||||
// @formatter:on
|
||||
LOGGER.debug("{}", sql.toString());
|
||||
lrw.add(sql.execute());
|
||||
} else {
|
||||
InsertResultStep<TDocumentRecord> sql = DSL.using(c)
|
||||
// @formatter:off
|
||||
.insertInto(T_DOCUMENT,
|
||||
T_DOCUMENT.NAME,
|
||||
T_DOCUMENT.DOCTYPE,
|
||||
T_DOCUMENT.DOCUMENT,
|
||||
T_DOCUMENT.FILETYPE)
|
||||
.values(bean.getName(), bean.getDoctype(), bean.getDocument(), bean.getFiletype())
|
||||
.returning(T_DOCUMENT.PK);
|
||||
// @formatter:on
|
||||
LOGGER.debug("{}", sql.toString());
|
||||
pk = sql.fetchOne().get(T_DOCUMENT.PK);
|
||||
lrw.add(1);
|
||||
}
|
||||
List<EnumCamprole> allEnums = Arrays.asList(EnumCamprole.values());
|
||||
Set<EnumCamprole> removeCandidates = new HashSet<>();
|
||||
removeCandidates.addAll(allEnums);
|
||||
for (EnumCamprole role : bean.getRoles()) {
|
||||
try {
|
||||
InsertReturningStep<TDocumentroleRecord> sql = DSL.using(c)
|
||||
// @formatter:off
|
||||
.insertInto(T_DOCUMENTROLE,
|
||||
T_DOCUMENTROLE.FK_DOCUMENT,
|
||||
T_DOCUMENTROLE.CAMPROLE)
|
||||
.values(pk, role)
|
||||
.onConflict(T_DOCUMENTROLE.FK_DOCUMENT, T_DOCUMENTROLE.CAMPROLE)
|
||||
.doNothing();
|
||||
// @formatter:on
|
||||
LOGGER.debug("{}", sql.toString());
|
||||
lrw.add(sql.execute());
|
||||
removeCandidates.remove(role);
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
}
|
||||
DeleteConditionStep<TDocumentroleRecord> sql = DSL.using(c)
|
||||
// @formatter:off
|
||||
.deleteFrom(T_DOCUMENTROLE)
|
||||
.where(T_DOCUMENTROLE.FK_DOCUMENT.eq(pk))
|
||||
.and(T_DOCUMENTROLE.CAMPROLE.in(removeCandidates));
|
||||
// @formatter:on
|
||||
LOGGER.debug("{}", sql.toString());
|
||||
lrw.add(sql.execute());
|
||||
});
|
||||
return lrw.getCounter();
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -19,8 +21,39 @@ public class AdminService {
|
||||
@Autowired
|
||||
private MailRepository mailRepository;
|
||||
|
||||
@Autowired
|
||||
private AdminRepository adminRepository;
|
||||
|
||||
public void sendMail(@Valid MailBean bean) {
|
||||
mailRepository.sendMail(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all documents
|
||||
*
|
||||
* @return a list of documents; an empty one at least
|
||||
*/
|
||||
public List<DocumentBean> getAllDocuments() {
|
||||
return adminRepository.getAllDocuments();
|
||||
}
|
||||
|
||||
/**
|
||||
* get document from the database
|
||||
*
|
||||
* @param id the ID of the document
|
||||
* @return the document or null
|
||||
*/
|
||||
public DocumentBean getDocument(Integer id) {
|
||||
return adminRepository.getDocument(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* upsert the document bean
|
||||
*
|
||||
* @param bean the bean
|
||||
* @return the number of affected database lines
|
||||
*/
|
||||
public Integer updateDocument(@Valid DocumentBean bean) {
|
||||
return adminRepository.upsert(bean);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,107 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.servlet.http.Part;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public class DocumentBean implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer pk;
|
||||
@NotNull
|
||||
private EnumDocument doctype;
|
||||
@NotBlank
|
||||
private String name;
|
||||
private String document;
|
||||
@NotNull
|
||||
private EnumFiletype filetype;
|
||||
@NotNull
|
||||
private Part uploadfile;
|
||||
private EnumCamprole[] roles;
|
||||
|
||||
public void encodeUpload() throws IOException {
|
||||
if (uploadfile != null) {
|
||||
InputStream inputStream = uploadfile.getInputStream();
|
||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||
if (bytes.length > 0) {
|
||||
document = Base64.getEncoder().encodeToString(bytes);
|
||||
} // not uploaded files should not be changed, so document must be kept as is
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setDoctype(EnumDocument doctype) {
|
||||
this.doctype = doctype;
|
||||
}
|
||||
|
||||
public EnumDocument getDoctype() {
|
||||
return doctype;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setDocument(String document) {
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public String getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
public void setFiletype(EnumFiletype filetype) {
|
||||
this.filetype = filetype;
|
||||
}
|
||||
|
||||
public EnumFiletype getFiletype() {
|
||||
return filetype;
|
||||
}
|
||||
|
||||
public Part getUploadfile() {
|
||||
return uploadfile;
|
||||
}
|
||||
|
||||
public void setUploadfile(Part uploadfile) {
|
||||
this.uploadfile = uploadfile;
|
||||
}
|
||||
|
||||
public EnumCamprole[] getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(EnumCamprole[] roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pk the pk to set
|
||||
*/
|
||||
public void setPk(Integer pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
}
|
@ -34,8 +34,8 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class BookingsGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(BookingsGateway.class);
|
||||
public class BookingsRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(BookingsRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -16,7 +16,7 @@ import de.jottyfan.camporganizer.module.business.bookings.IBookingsService;
|
||||
public class BookingsService implements IBookingsService {
|
||||
|
||||
@Autowired
|
||||
private BookingsGateway bookingsGateway;
|
||||
private BookingsRepository bookingsGateway;
|
||||
|
||||
@Override
|
||||
public List<BookerBean> getBookers(String username) {
|
||||
|
@ -33,8 +33,8 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class BusinessGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(BusinessGateway.class);
|
||||
public class BusinessRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(BusinessRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -19,7 +19,7 @@ import de.jottyfan.camporganizer.module.business.business.IBusinessService;
|
||||
@Service
|
||||
public class BusinessService implements IBusinessService {
|
||||
@Autowired
|
||||
private BusinessGateway gateway;
|
||||
private BusinessRepository gateway;
|
||||
|
||||
@Override
|
||||
public String getCurrentUser(HttpServletRequest request) {
|
||||
|
@ -32,8 +32,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class CampGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(CampGateway.class);
|
||||
public class CampRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(CampRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -17,7 +17,7 @@ import de.jottyfan.camporganizer.module.business.camp.ICampService;
|
||||
public class CampService implements ICampService {
|
||||
|
||||
@Autowired
|
||||
private CampGateway campGateway;
|
||||
private CampRepository campGateway;
|
||||
|
||||
@Override
|
||||
public CampBean getCamp(Integer id, String username) {
|
||||
|
@ -29,8 +29,8 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesprofileRecord;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class PrivilegesGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(PrivilegesGateway.class);
|
||||
public class PrivilegesRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(PrivilegesRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -18,7 +18,7 @@ import de.jottyfan.camporganizer.module.business.privileges.IPrivilegesService;
|
||||
@Service
|
||||
public class PrivilegesService implements IPrivilegesService {
|
||||
@Autowired
|
||||
private PrivilegesGateway gateway;
|
||||
private PrivilegesRepository gateway;
|
||||
|
||||
@Override
|
||||
public Map<Integer, CampBean> getPrivileges() {
|
||||
|
@ -13,7 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
|
||||
import de.jottyfan.camporganizer.module.dashboard.DashboardGateway;
|
||||
import de.jottyfan.camporganizer.module.dashboard.DashboardRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -27,7 +27,7 @@ public class CamplistService {
|
||||
private CamplistGateway gateway;
|
||||
|
||||
@Autowired
|
||||
private DashboardGateway dashboardGateway;
|
||||
private DashboardRepository dashboardGateway;
|
||||
|
||||
/**
|
||||
* get all camps from the database and prepare them for the view
|
||||
|
@ -38,8 +38,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class ConfirmationGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ConfirmationGateway.class);
|
||||
public class ConfirmationRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ConfirmationRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -19,7 +19,7 @@ import de.jottyfan.camporganizer.module.confirmation.confirmation.IConfirmationS
|
||||
@Service
|
||||
public class ConfirmationService implements IConfirmationService {
|
||||
@Autowired
|
||||
private ConfirmationGateway gateway;
|
||||
private ConfirmationRepository gateway;
|
||||
|
||||
@Override
|
||||
public String getCurrentUser(HttpServletRequest request) {
|
||||
|
@ -46,8 +46,8 @@ import de.jottyfan.camporganizer.module.mail.MailRepository;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class PersonGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(PersonGateway.class);
|
||||
public class PersonRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(PersonRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -15,7 +15,7 @@ import de.jottyfan.camporganizer.module.confirmation.person.IPersonService;
|
||||
@Service
|
||||
public class PersonService implements IPersonService {
|
||||
@Autowired
|
||||
private PersonGateway gateway;
|
||||
private PersonRepository gateway;
|
||||
|
||||
@Override
|
||||
public PersonBean getPerson(String username, Integer pk) {
|
||||
|
@ -31,8 +31,8 @@ import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class DashboardGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(DashboardGateway.class);
|
||||
public class DashboardRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(DashboardRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -30,8 +30,8 @@ import biweekly.property.Summary;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class ICalGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ICalGateway.class);
|
||||
public class ICalRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ICalRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -20,7 +20,7 @@ import de.jottyfan.camporganizer.module.ical.IICalService;
|
||||
public class ICalService implements IICalService {
|
||||
|
||||
@Autowired
|
||||
private ICalGateway gateway;
|
||||
private ICalRepository gateway;
|
||||
|
||||
@Override
|
||||
public Boolean generate(HttpServletResponse response) throws IOException {
|
||||
|
@ -53,8 +53,8 @@ import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(transactionManager = "transactionManager")
|
||||
public class RegistrationGateway {
|
||||
private static final Logger LOGGER = LogManager.getLogger(RegistrationGateway.class);
|
||||
public class RegistrationRepository {
|
||||
private static final Logger LOGGER = LogManager.getLogger(RegistrationRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
@ -17,7 +17,7 @@ public class RegistrationService {
|
||||
private final static Logger LOGGER = LogManager.getLogger(RegistrationService.class);
|
||||
|
||||
@Autowired
|
||||
private RegistrationGateway gateway;
|
||||
private RegistrationRepository gateway;
|
||||
|
||||
@Autowired
|
||||
private KeycloakRepository keycloak;
|
||||
|
@ -6,7 +6,7 @@ import javax.validation.ConstraintValidatorContext;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import de.jottyfan.camporganizer.module.registration.RegistrationGateway;
|
||||
import de.jottyfan.camporganizer.module.registration.RegistrationRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -19,7 +19,7 @@ public class UnusedUsernameValidator implements ConstraintValidator<UnusedUserna
|
||||
private String message;
|
||||
|
||||
@Autowired
|
||||
private RegistrationGateway gateway;
|
||||
private RegistrationRepository gateway;
|
||||
|
||||
public void initialize(UnusedUsername uu) {
|
||||
this.field = uu.field();
|
||||
|
@ -1,28 +1,38 @@
|
||||
@font-face {
|
||||
font-family: 'Cabin Sketch';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Cabin-Sketch-700.eot'); /* IE9 */
|
||||
src: url('../fonts/Cabin-Sketch-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('../fonts/Cabin-Sketch-700.woff2') format('woff2'), /* Modern Browsers */
|
||||
url('../fonts/Cabin-Sketch-700.woff') format('woff'), /* Modern Browsers */
|
||||
url('../fonts/Cabin-Sketch-700.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('../fonts/Cabin-Sketch-700.svg#CabinSketch') format('svg'); /* Legacy iOS */
|
||||
font-family: 'Cabin Sketch';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Cabin-Sketch-700.eot'); /* IE9 */
|
||||
src: url('../fonts/Cabin-Sketch-700.eot?#iefix')
|
||||
format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('../fonts/Cabin-Sketch-700.woff2') format('woff2'),
|
||||
/* Modern Browsers */
|
||||
url('../fonts/Cabin-Sketch-700.woff') format('woff'),
|
||||
/* Modern Browsers */
|
||||
url('../fonts/Cabin-Sketch-700.ttf') format('truetype'),
|
||||
/* Safari, Android, iOS */
|
||||
url('../fonts/Cabin-Sketch-700.svg#CabinSketch') format('svg');
|
||||
/* Legacy iOS */
|
||||
}
|
||||
|
||||
/* fira-sans-regular - latin */
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/fira-sans-v16-latin-regular.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('../fonts/fira-sans-v16-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('../fonts/fira-sans-v16-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('../fonts/fira-sans-v16-latin-regular.woff') format('woff'), /* Modern Browsers */
|
||||
url('../fonts/fira-sans-v16-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('../fonts/fira-sans-v16-latin-regular.svg#FiraSans') format('svg'); /* Legacy iOS */
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/fira-sans-v16-latin-regular.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src: local(''), url('../fonts/fira-sans-v16-latin-regular.eot?#iefix')
|
||||
format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('../fonts/fira-sans-v16-latin-regular.woff2') format('woff2'),
|
||||
/* Super Modern Browsers */
|
||||
url('../fonts/fira-sans-v16-latin-regular.woff') format('woff'),
|
||||
/* Modern Browsers */
|
||||
url('../fonts/fira-sans-v16-latin-regular.ttf')
|
||||
format('truetype'), /* Safari, Android, iOS */
|
||||
url('../fonts/fira-sans-v16-latin-regular.svg#FiraSans')
|
||||
format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
html {
|
||||
@ -34,6 +44,11 @@ body {
|
||||
background-image: url('../images/background.jpg');
|
||||
}
|
||||
|
||||
.navbar-background {
|
||||
background-image: url('../images/background.jpg');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
a {
|
||||
font-family: 'Fira Sans';
|
||||
}
|
||||
@ -96,19 +111,23 @@ div {
|
||||
}
|
||||
|
||||
.acc_over {
|
||||
background-image: linear-gradient(to bottom right, #ccc, #aaa) !important;
|
||||
background-image: linear-gradient(to bottom right, #ccc, #aaa)
|
||||
!important;
|
||||
}
|
||||
|
||||
.acc_true {
|
||||
background-image: linear-gradient(to bottom right, #cfc, #afa) !important;
|
||||
background-image: linear-gradient(to bottom right, #cfc, #afa)
|
||||
!important;
|
||||
}
|
||||
|
||||
.acc_false {
|
||||
background-image: linear-gradient(to bottom right, #fcc, #faa) !important;
|
||||
background-image: linear-gradient(to bottom right, #fcc, #faa)
|
||||
!important;
|
||||
}
|
||||
|
||||
.acc_null {
|
||||
background-image: linear-gradient(to bottom right, #fdb, #fca) !important;
|
||||
background-image: linear-gradient(to bottom right, #fdb, #fca)
|
||||
!important;
|
||||
}
|
||||
|
||||
.right-dist {
|
||||
@ -183,7 +202,7 @@ div {
|
||||
background: transparent;
|
||||
border: 2px solid transparent;
|
||||
padding: 8px;
|
||||
font-family: 'Cabin Sketch';
|
||||
font-family: 'Cabin Sketch';
|
||||
}
|
||||
|
||||
.linkbtn:hover {
|
||||
@ -360,3 +379,19 @@ div {
|
||||
text-align: center;
|
||||
padding-top: 45vh;
|
||||
}
|
||||
|
||||
.roleflag {
|
||||
border-radius: 24px;
|
||||
border: 1px solid gray;
|
||||
padding: 4px;
|
||||
margin: 2px;
|
||||
background-image: linear-gradient(to right bottom, silver, white);
|
||||
}
|
||||
|
||||
.tablebox {
|
||||
margin: 8px;
|
||||
background-color: rgba(255, 255, 255, 0.5) !important;
|
||||
padding: 6px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid gray;
|
||||
}
|
58
src/main/resources/templates/admin/document.html
Normal file
58
src/main/resources/templates/admin/document.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/rss/admin}" class="btn btn-seconary btn-icon-silent"><i class="fas fa-rss"></i></a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/admin}" class="btn btn-secondary btn-icon-silent">Administration</a></li>
|
||||
</ul>
|
||||
</th:block>
|
||||
<th:block layout:fragment="content">
|
||||
<div class="tablebox" sec:authorize="hasRole('admin')">
|
||||
<table id="docs" class="table table-striped" style="width: 100% !important">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Dokumententyp</td>
|
||||
<td>Zielgruppe</td>
|
||||
<th>Inhalt</th>
|
||||
<th>Dateityp</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="d : ${documents}">
|
||||
<td><a th:href="@{/admin/document/edit/{id}(id=${d.pk})}"><span th:text="${d.name}"></span></a></td>
|
||||
<td><span th:if="${d.doctype.literal == 'location'}">Wegbeschreibung</span> <span th:if="${d.doctype.literal == 'camp'}">Bestätigung</span><span
|
||||
th:if="${d.doctype.literal == 'camppass'}">Freizeitpass</span></td>
|
||||
<td><th:block th:each="r : ${d.roles}">
|
||||
<span th:if="${r.literal == 'student'}" class="roleflag">Teilnehmer</span>
|
||||
<span th:if="${r.literal == 'teacher'}" class="roleflag">Mitarbeiter</span>
|
||||
<span th:if="${r.literal == 'director'}" class="roleflag">Leiter</span>
|
||||
<span th:if="${r.literal == 'feeder'}" class="roleflag">Küche</span>
|
||||
</th:block></td>
|
||||
<td><a th:href="@{/document/{id}(id=${d.pk})}"><i class="fas fa-download"></i></a></td>
|
||||
<td><span th:text="${d.filetype.literal}" th:if="${d.filetype}"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" style="text-align: center"><a th:href="@{/admin/document/add}" class="btn btn-outline-primary">neues Dokument anlegen</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#docs").DataTable({
|
||||
language : locale_de
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
92
src/main/resources/templates/admin/document_edit.html
Normal file
92
src/main/resources/templates/admin/document_edit.html
Normal file
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/rss/admin}" class="btn btn-seconary btn-icon-silent"><i class="fas fa-rss"></i></a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/admin}" class="btn btn-secondary btn-icon-silent">Administration</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/admin/document}" class="btn btn-secondary btn-icon-silent">Dokumente</a></li>
|
||||
</ul>
|
||||
</th:block>
|
||||
<th:block layout:fragment="content">
|
||||
<div sec:authorize="hasRole('admin')">
|
||||
<form th:action="@{/admin/document/update}" th:object="${bean}" method="post" enctype="multipart/form-data">
|
||||
<div class="tablebox">
|
||||
<div class="container">
|
||||
<input type="hidden" th:field="*{pk}" />
|
||||
<div class="row mb-2">
|
||||
<label for="inputName" class="col-sm-2 col-form-label">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('name')}">[[${error}]]<br /></span> <input id="inputName" type="text" th:field="*{name}"
|
||||
th:class="${'form-control ' + (#fields.hasErrors('name') ? 'inputerror' : '')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputDoctype" class="col-sm-2 col-form-label">Dokumententyp</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('doctype')}">[[${error}]]<br /></span> <select id="inputDoctype" th:field="*{doctype}"
|
||||
th:class="${'form-select ' + (#fields.hasErrors('doctype') ? 'inputerror' : '')}">
|
||||
<option value="">--- bitte wählen ---</option>
|
||||
<option value="location">Wegbeschreibung</option>
|
||||
<option value="camp">Bestätigung</option>
|
||||
<option value="camppass">Freizeitpass</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputRole" class="col-sm-2 col-form-label">Zielgruppe</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('roles')}">[[${error}]]<br /></span> <select id="inputRole" th:field="*{roles}"
|
||||
th:class="${'form-control ' + (#fields.hasErrors('roles') ? 'inputerror' : '')}" multiple>
|
||||
<option value="student">Teilnehmer</option>
|
||||
<option value="teacher">Mitarbeiter</option>
|
||||
<option value="director">Leiter</option>
|
||||
<option value="feeder">Küche</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputFile" class="col-sm-2 col-form-label">Dokument</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('uploadfile')}">[[${error}]]<br /></span>
|
||||
<input type="file" id="inputFile" th:field="*{uploadfile}" th:class="${'form-control ' + (#fields.hasErrors('uploadfile') ? 'inputerror' : '')}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputFiletype" class="col-sm-2 col-form-label">Dateityp</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('filetype')}">[[${error}]]<br /></span> <select id="inputFiletype" th:field="*{filetype}"
|
||||
th:class="${'form-select ' + (#fields.hasErrors('filetype') ? 'inputerror' : '')}">
|
||||
<option value="">--- bitte wählen ---</option>
|
||||
<option value="pdf">PDF</option>
|
||||
<option value="png">PNG</option>
|
||||
<option value="jpg">JPG</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<input type="submit" class="btn btn-success" value="Ok" />
|
||||
<a th:href="@{/admin/document}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO:
|
||||
|
||||
delete from db th:if="${bean.pk}"
|
||||
-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/admin}" class="btn btn-seconary btn-icon-silent">Admin</a></li>
|
||||
|
@ -10,15 +10,18 @@
|
||||
<li class="nav-item"><a th:href="@{/rss/admin}" class="btn btn-seconary btn-icon-silent"><i class="fas fa-rss"></i></a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/admin/mail}" class="btn btn-secondary btn-icon-silent">Testmail</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0" sec:authorize="hasRole('admin')">
|
||||
<li class="nav-item"><a th:href="@{/admin/document}" class="btn btn-secondary btn-icon-silent">Dokumente</a></li>
|
||||
</ul>
|
||||
</th:block>
|
||||
<th:block layout:fragment="content">
|
||||
<div sec:authorize="hasRole('admin')">
|
||||
TODO: implement
|
||||
TODO: implement; list number of camps, registrations and documents or such
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent">Finanzübersicht</a></li>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent">Finanzübersicht</a></li>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/business/bookings}" class="btn btn-secondary btn-icon-silent" sec:authorize="hasRole('business_booking')">Buchungsübersicht</a></li>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent">Finanzübersicht</a></li>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent">Finanzübersicht</a></li>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<li class="nav-item"><a th:href="@{/rss/registrator}" class="btn btn-seconary btn-icon-silent"><i class="fas fa-rss"></i></a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
</th:block>
|
||||
<th:block layout:fragment="content">
|
||||
|
@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<th:block layout:fragment="header">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
<li class="nav-item"><a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent">Hauptseite</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a th:href="@{/confirmation}" class="btn btn-secondary btn-icon-silent">Anmeldungen</a></li>
|
||||
|
@ -18,10 +18,10 @@
|
||||
<script th:src="@{/js/mytoggle.js}"></script>
|
||||
<script th:src="@{/js/myAjax.js}"></script>
|
||||
<script th:src="@{/js/progress.js}"></script>
|
||||
<th:block layout:fragment="libs"></th:block>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg bg-light">
|
||||
<nav class="navbar navbar-expand-lg bg-light navbar-background">
|
||||
<span class="navbar-brand"><img th:src="@{/images/logo.png}" width="128px" /></span>
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@ -41,7 +41,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div layout:fragment="content">Layout content</div>
|
||||
<div layout:fragment="content">content</div>
|
||||
<div class="versionclip">
|
||||
<a href="https://gitlab.com/jottyfan/camporganizer2/-/issues" class="versionlink" target="_blank" th:text="${'Version ' + @manifestBean.getVersion()}"></a>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user