added notes
This commit is contained in:
@ -93,9 +93,7 @@ public class ContactController {
|
|||||||
@RolesAllowed("timetrack_user")
|
@RolesAllowed("timetrack_user")
|
||||||
@GetMapping(value = "/contact/delete/{id}")
|
@GetMapping(value = "/contact/delete/{id}")
|
||||||
public String doDelete(@PathVariable Integer id, Model model) {
|
public String doDelete(@PathVariable Integer id, Model model) {
|
||||||
LOGGER.info("up to delete bean {}", id);
|
|
||||||
Integer amount = contactService.doDelete(id);
|
Integer amount = contactService.doDelete(id);
|
||||||
LOGGER.info("deleted {} rows", amount);
|
|
||||||
return amount.equals(1) ? getList(model) : toItem(id, model);
|
return amount.equals(1) ? getList(model) : toItem(id, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.jottyfan.timetrack.spring.note;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author henkej
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface INoteService {
|
||||||
|
public List<NoteBean> getList();
|
||||||
|
public Integer doUpsert(NoteBean bean);
|
||||||
|
public Integer doDelete(Integer pk);
|
||||||
|
public Integer getAmount();
|
||||||
|
public String getCurrentUser(HttpServletRequest request);
|
||||||
|
public NoteBean getBean(Integer id);
|
||||||
|
}
|
106
src/main/java/de/jottyfan/timetrack/spring/note/NoteBean.java
Normal file
106
src/main/java/de/jottyfan/timetrack/spring/note/NoteBean.java
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package de.jottyfan.timetrack.spring.note;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import de.jottyfan.timetrack.db.note.enums.EnumCategory;
|
||||||
|
import de.jottyfan.timetrack.db.note.enums.EnumNotetype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author henkej
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class NoteBean implements Serializable, Comparable<NoteBean> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Integer pk;
|
||||||
|
private String title;
|
||||||
|
private EnumCategory category;
|
||||||
|
private String content;
|
||||||
|
private EnumNotetype type;
|
||||||
|
|
||||||
|
public NoteBean() {
|
||||||
|
super();
|
||||||
|
this.pk = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoteBean(Integer pk) {
|
||||||
|
super();
|
||||||
|
this.pk = pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(NoteBean o) {
|
||||||
|
return o == null ? 0 : getPk().compareTo(o.getPk());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the pk
|
||||||
|
*/
|
||||||
|
public Integer getPk() {
|
||||||
|
return pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pk the pk to set
|
||||||
|
*/
|
||||||
|
public void setPk(Integer pk) {
|
||||||
|
this.pk = pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the title
|
||||||
|
*/
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param title the title to set
|
||||||
|
*/
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the category
|
||||||
|
*/
|
||||||
|
public EnumCategory getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param category the category to set
|
||||||
|
*/
|
||||||
|
public void setCategory(EnumCategory category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the content
|
||||||
|
*/
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param content the content to set
|
||||||
|
*/
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the type
|
||||||
|
*/
|
||||||
|
public EnumNotetype getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type the type to set
|
||||||
|
*/
|
||||||
|
public void setType(EnumNotetype type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package de.jottyfan.timetrack.spring.note;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.security.RolesAllowed;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
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.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
import de.jottyfan.timetrack.db.note.enums.EnumCategory;
|
||||||
|
import de.jottyfan.timetrack.db.note.enums.EnumNotetype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author henkej
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class NoteController {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(NoteController.class);
|
||||||
|
|
||||||
|
private final HttpServletRequest request;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private INoteService noteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public NoteController(HttpServletRequest request) {
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@RequestMapping(value = "/note/list")
|
||||||
|
public String getList(Model model) {
|
||||||
|
List<NoteBean> list = noteService.getList();
|
||||||
|
model.addAttribute("noteList", list);
|
||||||
|
return "note/list";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@RequestMapping(value = "/note/add", method = RequestMethod.GET)
|
||||||
|
public String toAdd(Model model) {
|
||||||
|
return toItem(null, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@GetMapping("/note/edit/{id}")
|
||||||
|
public String toItem(@PathVariable Integer id, Model model) {
|
||||||
|
NoteBean bean = noteService.getBean(id);
|
||||||
|
if (bean == null) {
|
||||||
|
bean = new NoteBean(); // the add case
|
||||||
|
}
|
||||||
|
model.addAttribute("noteBean", bean);
|
||||||
|
model.addAttribute("types", Arrays.asList(EnumNotetype.values()));
|
||||||
|
model.addAttribute("categories", Arrays.asList(EnumCategory.values()));
|
||||||
|
return "note/item";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@RequestMapping(value = "/note/upsert", method = RequestMethod.POST)
|
||||||
|
public String doUpsert(Model model, @ModelAttribute NoteBean bean) {
|
||||||
|
Integer amount = noteService.doUpsert(bean);
|
||||||
|
return amount.equals(1) ? getList(model) : toItem(bean.getPk(), model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@GetMapping(value = "/note/delete/{id}")
|
||||||
|
public String doDelete(@PathVariable Integer id, Model model) {
|
||||||
|
Integer amount = noteService.doDelete(id);
|
||||||
|
return amount.equals(1) ? getList(model) : toItem(id, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,194 @@
|
|||||||
|
package de.jottyfan.timetrack.spring.note.impl;
|
||||||
|
|
||||||
|
import static de.jottyfan.timetrack.db.note.Tables.T_NOTE;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jooq.DSLContext;
|
||||||
|
import org.jooq.DeleteConditionStep;
|
||||||
|
import org.jooq.InsertValuesStep4;
|
||||||
|
import org.jooq.Record1;
|
||||||
|
import org.jooq.Record5;
|
||||||
|
import org.jooq.SelectConditionStep;
|
||||||
|
import org.jooq.SelectJoinStep;
|
||||||
|
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 de.jottyfan.timetrack.db.note.enums.EnumCategory;
|
||||||
|
import de.jottyfan.timetrack.db.note.enums.EnumNotetype;
|
||||||
|
import de.jottyfan.timetrack.db.note.tables.records.TNoteRecord;
|
||||||
|
import de.jottyfan.timetrack.spring.note.NoteBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class NoteGateway {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(NoteGateway.class);
|
||||||
|
private final DSLContext jooq;
|
||||||
|
|
||||||
|
public NoteGateway(@Autowired DSLContext jooq) throws Exception {
|
||||||
|
this.jooq = jooq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DSLContext getJooq() {
|
||||||
|
return this.jooq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get sorted list of notes
|
||||||
|
*
|
||||||
|
* @return a list (an empty one at least)
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws DataAccessException
|
||||||
|
*/
|
||||||
|
public List<NoteBean> getAll() throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
SelectJoinStep<Record5<Integer, String, EnumCategory, String, EnumNotetype>> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.select(T_NOTE.PK,
|
||||||
|
T_NOTE.TITLE,
|
||||||
|
T_NOTE.CATEGORY,
|
||||||
|
T_NOTE.CONTENT,
|
||||||
|
T_NOTE.NOTETYPE)
|
||||||
|
.from(T_NOTE);
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
List<NoteBean> list = new ArrayList<>();
|
||||||
|
for (Record5<Integer, String, EnumCategory, String, EnumNotetype> r : sql.fetch()) {
|
||||||
|
NoteBean bean = new NoteBean(r.get(T_NOTE.PK));
|
||||||
|
bean.setTitle(r.get(T_NOTE.TITLE));
|
||||||
|
bean.setCategory(r.get(T_NOTE.CATEGORY));
|
||||||
|
bean.setContent(r.get(T_NOTE.CONTENT));
|
||||||
|
bean.setType(r.get(T_NOTE.NOTETYPE));
|
||||||
|
list.add(bean);
|
||||||
|
}
|
||||||
|
list.sort((o1, o2) -> o1 == null ? 0 : o1.compareTo(o2));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete a note from the database
|
||||||
|
*
|
||||||
|
* @param pk the id of the contact
|
||||||
|
* @return the number of affected database rows, should be 1
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws DataAccessException
|
||||||
|
*/
|
||||||
|
public Integer delete(Integer pk) throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
DeleteConditionStep<TNoteRecord> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.deleteFrom(T_NOTE)
|
||||||
|
.where(T_NOTE.PK.eq(pk));
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
return sql.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a note to the database
|
||||||
|
*
|
||||||
|
* @param bean the contact information
|
||||||
|
* @return the number of affected database rows, should be 1
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws DataAccessException
|
||||||
|
*/
|
||||||
|
public Integer add(NoteBean bean) throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
InsertValuesStep4<TNoteRecord, String, EnumCategory, String, EnumNotetype> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.insertInto(T_NOTE,
|
||||||
|
T_NOTE.TITLE,
|
||||||
|
T_NOTE.CATEGORY,
|
||||||
|
T_NOTE.CONTENT,
|
||||||
|
T_NOTE.NOTETYPE)
|
||||||
|
.values(bean.getTitle(), bean.getCategory(), bean.getContent(), bean.getType());
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
return sql.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update a note in the database, referencing its pk
|
||||||
|
*
|
||||||
|
* @param bean the contact information
|
||||||
|
* @return the number of affected database rows, should be 1
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws DataAccessException
|
||||||
|
*/
|
||||||
|
public Integer update(NoteBean bean) throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
UpdateConditionStep<TNoteRecord> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.update(T_NOTE)
|
||||||
|
.set(T_NOTE.TITLE, bean.getTitle())
|
||||||
|
.set(T_NOTE.CATEGORY, bean.getCategory())
|
||||||
|
.set(T_NOTE.CONTENT, bean.getContent())
|
||||||
|
.set(T_NOTE.NOTETYPE, bean.getType())
|
||||||
|
.where(T_NOTE.PK.eq(bean.getPk()));
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
return sql.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get number of entries in t_note
|
||||||
|
*
|
||||||
|
* @return number of entries
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws DataAccessException
|
||||||
|
*/
|
||||||
|
public Integer getAmount() throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
SelectJoinStep<Record1<Integer>> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.selectCount()
|
||||||
|
.from(T_NOTE);
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
return sql.fetchOne(DSL.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get all enum types
|
||||||
|
*
|
||||||
|
* @return list of enum types
|
||||||
|
*/
|
||||||
|
public List<EnumNotetype> getTypes() {
|
||||||
|
return new ArrayList<>(Arrays.asList(EnumNotetype.values()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoteBean getBean(Integer id) {
|
||||||
|
SelectConditionStep<Record5<Integer, String, EnumCategory, String, EnumNotetype>> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.select(T_NOTE.PK,
|
||||||
|
T_NOTE.TITLE,
|
||||||
|
T_NOTE.CATEGORY,
|
||||||
|
T_NOTE.CONTENT,
|
||||||
|
T_NOTE.NOTETYPE)
|
||||||
|
.from(T_NOTE)
|
||||||
|
.where(T_NOTE.PK.eq(id));
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
for (Record5<Integer, String, EnumCategory, String, EnumNotetype> r : sql.fetch()) {
|
||||||
|
NoteBean bean = new NoteBean(r.get(T_NOTE.PK));
|
||||||
|
bean.setTitle(r.get(T_NOTE.TITLE));
|
||||||
|
bean.setCategory(r.get(T_NOTE.CATEGORY));
|
||||||
|
bean.setContent(r.get(T_NOTE.CONTENT));
|
||||||
|
bean.setType(r.get(T_NOTE.NOTETYPE));
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package de.jottyfan.timetrack.spring.note.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jooq.DSLContext;
|
||||||
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import de.jottyfan.timetrack.spring.note.INoteService;
|
||||||
|
import de.jottyfan.timetrack.spring.note.NoteBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author henkej
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Transactional(transactionManager = "transactionManager")
|
||||||
|
public class NoteService implements INoteService {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(NoteService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DSLContext dsl;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrentUser(HttpServletRequest request) {
|
||||||
|
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||||
|
return ksc == null ? "" : ksc.getIdToken().getPreferredUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NoteBean> getList() {
|
||||||
|
try {
|
||||||
|
return new NoteGateway(dsl).getAll();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer doUpsert(NoteBean bean) {
|
||||||
|
try {
|
||||||
|
NoteGateway gw = new NoteGateway(dsl);
|
||||||
|
return bean.getPk() == null ? gw.add(bean) : gw.update(bean);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer doDelete(Integer pk) {
|
||||||
|
try {
|
||||||
|
return new NoteGateway(dsl).delete(pk);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getAmount() {
|
||||||
|
return getList().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NoteBean getBean(Integer id) {
|
||||||
|
try {
|
||||||
|
return new NoteGateway(dsl).getBean(id);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,13 +4,17 @@ html {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: #99c1f1;
|
background-color: #99c1f1;
|
||||||
height: calc(100% - 76px);
|
height: calc(100% - 56px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.float-right {
|
.float-right {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.noty {
|
||||||
|
background-image: linear-gradient(to bottom, #ffc, #ee0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.glassy {
|
.glassy {
|
||||||
background-color: rgba(1,1,1,0.1);
|
background-color: rgba(1,1,1,0.1);
|
||||||
}
|
}
|
||||||
@ -128,6 +132,10 @@ body {
|
|||||||
.version {
|
.version {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
color: silver;
|
color: silver;
|
||||||
|
position: absolute;
|
||||||
|
padding-top: 36px;
|
||||||
|
padding-left: 22px;
|
||||||
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fc-content {
|
.fc-content {
|
||||||
|
@ -20,9 +20,8 @@
|
|||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light static-top">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light static-top">
|
||||||
<div class="container-fluid" style="width: 98%">
|
<div class="container-fluid" style="width: 98%">
|
||||||
<a class="navbar-brand" th:href="@{/}"> <i class="fa fa-calendar-alt"></i> Timetrack
|
<i class="fa fa-calendar-alt"></i> <a class="navbar-brand" style="margin-left: 8px; z-index: 1" th:href="@{/}">Timetrack</a><br />
|
||||||
<div class="version" th:text="${@manifestBean.getVersion()}"></div>
|
<div class="version" th:text="${@manifestBean.getVersion()}"></div>
|
||||||
</a>
|
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
|
||||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
@ -33,6 +32,7 @@
|
|||||||
data-bs-toggle="dropdown" aria-expanded="false"> Module </a>
|
data-bs-toggle="dropdown" aria-expanded="false"> Module </a>
|
||||||
<ul class="dropdown-menu dropdown-menu-light" aria-labelledby="navbarScrollingDropdown">
|
<ul class="dropdown-menu dropdown-menu-light" aria-labelledby="navbarScrollingDropdown">
|
||||||
<li><a class="dropdown-item" th:href="@{/contact/list}">Kontakte</a></li>
|
<li><a class="dropdown-item" th:href="@{/contact/list}">Kontakte</a></li>
|
||||||
|
<li><a class="dropdown-item" th:href="@{/note/list}">Notizen</a></li>
|
||||||
<li><hr /></li>
|
<li><hr /></li>
|
||||||
<li><a class="dropdown-item" th:href="@{/logout}">[[${currentUser}]] abmelden</a></li>
|
<li><a class="dropdown-item" th:href="@{/logout}">[[${currentUser}]] abmelden</a></li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
64
src/main/resources/templates/note/item.html
Normal file
64
src/main/resources/templates/note/item.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
xmlns:sec="http://www.thymeleaf.org/extras/spring-security" layout:decorate="~{layout/main.html}">
|
||||||
|
<head>
|
||||||
|
<title>Notiz aktualisieren</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ul layout:fragment="menu">
|
||||||
|
</ul>
|
||||||
|
<main layout:fragment="content">
|
||||||
|
<div class="container formpane">
|
||||||
|
<form th:action="@{/note/upsert}" th:object="${noteBean}" method="post">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputPk" class="col-sm-2 col-form-label">Inhalt von Eintrag</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input id="inputPk" type="text" th:field="*{pk}" class="form-control" readonly="readonly" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputTitle" class="col-sm-2 col-form-label">Titel</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input id="inputTitle" type="text" th:field="*{title}" class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputCategory" class="col-sm-2 col-form-label">Kategorie</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select id="inputCategory" class="form-control select2-single" th:field="*{category}">
|
||||||
|
<option th:each="i : ${categories}" th:value="${i}" th:text="${i.literal}"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputContent" class="col-sm-2 col-form-label">Inhalt</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input id="inputContent" type="text" th:field="*{content}" class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputType" class="col-sm-2 col-form-label">Typ</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select id="inputType" class="form-control select2-single" th:field="*{type}">
|
||||||
|
<option th:each="i : ${types}" th:value="${i}" th:text="${i.literal}"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-sm-2">Änderung</div>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-success">speichern</button>
|
||||||
|
<button type="submit" class="btn btn-secondary" th:formaction="@{/note/list}">abbrechen</button>
|
||||||
|
<div class="dropdown float-right" th:if="${noteBean.pk != null}" sec:authorize="hasRole('timetrack_user')">
|
||||||
|
<button class="btn btn-danger dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Eintrag löschen</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a class="dropdown-item" th:href="@{/note/delete/{id}(id=${noteBean.pk})}">endgültig löschen</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
76
src/main/resources/templates/note/list.html
Normal file
76
src/main/resources/templates/note/list.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
xmlns:sec="http://www.thymeleaf.org/extras/spring-security" layout:decorate="~{layout/main.html}">
|
||||||
|
<head>
|
||||||
|
<title>Notizen</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ul layout:fragment="menu">
|
||||||
|
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/note/add}">Neue Notiz
|
||||||
|
anlegen</a></li>
|
||||||
|
</ul>
|
||||||
|
<main layout:fragment="content">
|
||||||
|
<div class="accordion" id="acdiv">
|
||||||
|
<div class="accordion-item noty">
|
||||||
|
<h2 class="accordion-header" id="headingDashboard">
|
||||||
|
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#dashboard" aria-expanded="true"
|
||||||
|
aria-controls="dashboard">Dashboard</button>
|
||||||
|
</h2>
|
||||||
|
<div id="dashboard" class="accordion-collapse collapse show" aria-labelledby="headingDashboard" data-bs-parent="#acdiv">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<div class="row row-cols-12 ro-cols-lg-3 ro-cols-md-2 ro-cols-sd-1 g-4" style="margin: 8px">
|
||||||
|
<div class="col" th:each="note : ${noteList}">
|
||||||
|
<div class="card text-dark bg-light shadow" style="width: 100%">
|
||||||
|
<div class="card-header text-center">
|
||||||
|
<font th:text="${note.category}" style="font-size: larger">:</font> <font th:text="${note.title}"
|
||||||
|
style="font-size: larger; font-weight: bolder"></font>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
|
<pre th:text="${note.content}"></pre>
|
||||||
|
<a th:href="@{/note/edit/{id}(id=${note.pk})}" sec:authorize="hasRole('timetrack_user')" style="margin-left: 8px;">
|
||||||
|
<i class="fa fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<span th:text="${note.type}"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item glassy">
|
||||||
|
<h2 class="accordion-header" id="headingTable">
|
||||||
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#list"
|
||||||
|
aria-expanded="false" aria-controls="list">Liste</button>
|
||||||
|
</h2>
|
||||||
|
<div id="list" class="accordion-collapse collapse" aria-labelledby="headingTable" data-bs-parent="#acdiv">
|
||||||
|
<div class="accordion-body" style="background-color: white">
|
||||||
|
<table class="table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Titel</th>
|
||||||
|
<th>Kategorie</th>
|
||||||
|
<th>Inhalt</th>
|
||||||
|
<th>Typ</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="note : ${noteList}">
|
||||||
|
<td><a th:href="@{/note/edit/{id}(id=${note.pk})}"><span th:text="${note.title}"></span></a></td>
|
||||||
|
<td><a th:href="@{/note/edit/{id}(id=${note.pk})}"><span th:text="${note.category}"></span></a></td>
|
||||||
|
<td><a th:href="@{/note/edit/{id}(id=${note.pk})}"><span th:text="${note.content}"></span></a></td>
|
||||||
|
<td><a th:href="@{/note/edit/{id}(id=${note.pk})}"><span th:text="${note.type}"></span></a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user