added notes
This commit is contained in:
		| @@ -93,9 +93,7 @@ public class ContactController { | ||||
| 	@RolesAllowed("timetrack_user") | ||||
| 	@GetMapping(value = "/contact/delete/{id}") | ||||
| 	public String doDelete(@PathVariable Integer id, Model model) { | ||||
| 		LOGGER.info("up to delete bean {}", id); | ||||
| 		Integer amount = contactService.doDelete(id); | ||||
| 		LOGGER.info("deleted {} rows", amount); | ||||
| 		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 { | ||||
| 	background-color: #99c1f1; | ||||
| 	height: calc(100% - 76px); | ||||
| 	height: calc(100% - 56px); | ||||
| } | ||||
|  | ||||
| .float-right { | ||||
| 	float: right; | ||||
| } | ||||
|  | ||||
| .noty { | ||||
| 	background-image: linear-gradient(to bottom, #ffc, #ee0) !important; | ||||
| } | ||||
|  | ||||
| .glassy { | ||||
| 	background-color: rgba(1,1,1,0.1); | ||||
| } | ||||
| @@ -128,6 +132,10 @@ body { | ||||
| .version { | ||||
| 	font-size: small; | ||||
| 	color: silver; | ||||
| 	position: absolute; | ||||
| 	padding-top: 36px; | ||||
| 	padding-left: 22px; | ||||
| 	z-index: 0; | ||||
| } | ||||
|  | ||||
| .fc-content { | ||||
|   | ||||
| @@ -20,9 +20,8 @@ | ||||
| 	<!-- Navigation --> | ||||
| 	<nav class="navbar navbar-expand-lg navbar-light bg-light static-top"> | ||||
| 		<div class="container-fluid" style="width: 98%"> | ||||
| 			<a class="navbar-brand" th:href="@{/}"> <i class="fa fa-calendar-alt"></i> Timetrack | ||||
| 				<div class="version" th:text="${@manifestBean.getVersion()}"></div> | ||||
| 			</a> | ||||
| 			<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> | ||||
| 			<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive" | ||||
| 				aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> | ||||
| 				<span class="navbar-toggler-icon"></span> | ||||
| @@ -33,6 +32,7 @@ | ||||
| 						data-bs-toggle="dropdown" aria-expanded="false"> Module </a> | ||||
| 						<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="@{/note/list}">Notizen</a></li> | ||||
| 							<li><hr /></li> | ||||
| 							<li><a class="dropdown-item" th:href="@{/logout}">[[${currentUser}]] abmelden</a></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