diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b14df3f..2b2fe64 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,6 +15,7 @@ before_script: - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null - mkdir -p ~/.ssh - chmod 700 ~/.ssh + - git log --pretty="%cn;%cd;%s" > src/main/resources/commits.log build: stage: build diff --git a/README.md b/README.md index ca4db83..f4f6ddd 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ 2. Создать новую функцию автоматизированной системы управления задчами - интеллектуальную постановку задач исполнителям. 3. Получить платформу для обкатки научных проектов магистрантов по созданию интеллектуальны систем. 4. Получить проект для обучения бакалавров современым технологиям разработки. +5. Создать систему хранения и трансляции опыта между участниками научной группы. [Демо версия доступна здесь](http://193.110.3.124:8080) diff --git a/src/main/java/ru/ulstu/conference/controller/ConferenceController.java b/src/main/java/ru/ulstu/conference/controller/ConferenceController.java new file mode 100644 index 0000000..aa871ba --- /dev/null +++ b/src/main/java/ru/ulstu/conference/controller/ConferenceController.java @@ -0,0 +1,19 @@ +package ru.ulstu.conference.controller; + + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import ru.ulstu.conference.service.ConferenceService; +import springfox.documentation.annotations.ApiIgnore; + +@Controller() +@RequestMapping(value = "/conferences") +@ApiIgnore +public class ConferenceController { + + private final ConferenceService conferenceService; + + public ConferenceController(ConferenceService paperService) { + this.conferenceService = paperService; + } +} diff --git a/src/main/java/ru/ulstu/conference/model/Conference.java b/src/main/java/ru/ulstu/conference/model/Conference.java new file mode 100644 index 0000000..b2851ed --- /dev/null +++ b/src/main/java/ru/ulstu/conference/model/Conference.java @@ -0,0 +1,11 @@ +package ru.ulstu.conference.model; + +import ru.ulstu.core.model.BaseEntity; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name = "conference") +public class Conference extends BaseEntity { +} diff --git a/src/main/java/ru/ulstu/conference/model/ConferenceDto.java b/src/main/java/ru/ulstu/conference/model/ConferenceDto.java new file mode 100644 index 0000000..e3f757e --- /dev/null +++ b/src/main/java/ru/ulstu/conference/model/ConferenceDto.java @@ -0,0 +1,4 @@ +package ru.ulstu.conference.model; + +public class ConferenceDto { +} diff --git a/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java b/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java new file mode 100644 index 0000000..379c8b6 --- /dev/null +++ b/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java @@ -0,0 +1,4 @@ +package ru.ulstu.conference.model; + +public class ConferenceFilterDto { +} diff --git a/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java b/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java new file mode 100644 index 0000000..4325633 --- /dev/null +++ b/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java @@ -0,0 +1,7 @@ +package ru.ulstu.conference.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.conference.model.Conference; + +public interface ConferenceRepository extends JpaRepository { +} diff --git a/src/main/java/ru/ulstu/conference/service/ConferenceNotificationService.java b/src/main/java/ru/ulstu/conference/service/ConferenceNotificationService.java new file mode 100644 index 0000000..ff9f69a --- /dev/null +++ b/src/main/java/ru/ulstu/conference/service/ConferenceNotificationService.java @@ -0,0 +1,7 @@ +package ru.ulstu.conference.service; + +import org.springframework.stereotype.Service; + +@Service +public class ConferenceNotificationService { +} diff --git a/src/main/java/ru/ulstu/conference/service/ConferenceService.java b/src/main/java/ru/ulstu/conference/service/ConferenceService.java new file mode 100644 index 0000000..a8147c9 --- /dev/null +++ b/src/main/java/ru/ulstu/conference/service/ConferenceService.java @@ -0,0 +1,17 @@ +package ru.ulstu.conference.service; + +import org.springframework.stereotype.Service; +import ru.ulstu.conference.repository.ConferenceRepository; +import ru.ulstu.deadline.service.DeadlineService; + +@Service +public class ConferenceService { + private final ConferenceRepository conferenceRepository; + private final DeadlineService deadlineService; + + public ConferenceService(ConferenceRepository conferenceRepository, + DeadlineService deadlineService) { + this.conferenceRepository = conferenceRepository; + this.deadlineService = deadlineService; + } +} diff --git a/src/main/java/ru/ulstu/configuration/MvcConfiguration.java b/src/main/java/ru/ulstu/configuration/MvcConfiguration.java index f9e887f..35e9ad2 100644 --- a/src/main/java/ru/ulstu/configuration/MvcConfiguration.java +++ b/src/main/java/ru/ulstu/configuration/MvcConfiguration.java @@ -10,10 +10,11 @@ public class MvcConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/{articlename:\\w+}"); - //registry.addViewController("/admin/{articlename:\\w+}"); + registry.addViewController("/admin/{articlename:\\w+}"); registry.addViewController("/papers/{articlename:\\w+}"); registry.addViewController("/grants/{articlename:\\w+}"); registry.addViewController("/conferences/{articlename:\\w+}"); + registry.addViewController("/students/{articlename:\\w+}"); registry.addRedirectViewController("/", "/index"); registry.addRedirectViewController("/default", "/index"); } diff --git a/src/main/java/ru/ulstu/file/FileController.java b/src/main/java/ru/ulstu/file/FileController.java index e60626b..ac08ac1 100644 --- a/src/main/java/ru/ulstu/file/FileController.java +++ b/src/main/java/ru/ulstu/file/FileController.java @@ -13,6 +13,7 @@ import org.springframework.web.multipart.MultipartFile; import ru.ulstu.configuration.Constants; import ru.ulstu.core.model.response.Response; import ru.ulstu.file.model.FileData; +import ru.ulstu.file.model.FileDataDto; import ru.ulstu.file.service.FileService; import java.io.IOException; @@ -51,7 +52,7 @@ public class FileController { } @PostMapping("/uploadTmpFile") - public Response upload(@RequestParam("file") MultipartFile multipartFile) throws IOException { - return new Response(fileService.uploadToTmpDir(multipartFile)); + public Response upload(@RequestParam("file") MultipartFile multipartFile) throws IOException { + return new Response(fileService.createFromMultipartFile(multipartFile)); } } diff --git a/src/main/java/ru/ulstu/file/model/FileDataDto.java b/src/main/java/ru/ulstu/file/model/FileDataDto.java new file mode 100644 index 0000000..919cd80 --- /dev/null +++ b/src/main/java/ru/ulstu/file/model/FileDataDto.java @@ -0,0 +1,76 @@ +package ru.ulstu.file.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class FileDataDto { + private Integer id; + private String name; + private String fileName; + private String tmpFileName; + private boolean deleted; + + public FileDataDto() { + } + + @JsonCreator + public FileDataDto(@JsonProperty("id") Integer id, + @JsonProperty("name") String name, + @JsonProperty("fileName") String fileName, + @JsonProperty("tmpFileName") String tmpFileName) { + this.id = id; + this.name = name; + this.fileName = fileName; + this.tmpFileName = tmpFileName; + } + + public FileDataDto(FileData fileData) { + this.id = fileData.getId(); + this.name = fileData.getName(); + } + + public FileDataDto(String fileName, String tmpFileName) { + this.fileName = fileName; + this.tmpFileName = tmpFileName; + } + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getTmpFileName() { + return tmpFileName; + } + + public void setTmpFileName(String tmpFileName) { + this.tmpFileName = tmpFileName; + } + + public boolean isDeleted() { + return deleted; + } + + public void setDeleted(boolean deleted) { + this.deleted = deleted; + } + +} diff --git a/src/main/java/ru/ulstu/file/service/FileService.java b/src/main/java/ru/ulstu/file/service/FileService.java index 3f9e603..85dd91c 100644 --- a/src/main/java/ru/ulstu/file/service/FileService.java +++ b/src/main/java/ru/ulstu/file/service/FileService.java @@ -1,15 +1,20 @@ package ru.ulstu.file.service; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import ru.ulstu.file.model.FileData; +import ru.ulstu.file.model.FileDataDto; import ru.ulstu.file.repostory.FileRepository; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Date; +import java.util.List; +import java.util.UUID; import static java.nio.charset.StandardCharsets.UTF_8; @@ -29,13 +34,13 @@ public class FileService { public FileData createFileFromTmp(String tmpFileName) throws IOException { FileData fileData = new FileData(); fileData.setData(getTmpFile(tmpFileName)); - fileData.setName(getTmpFileName(tmpFileName)); + fileData.setSize(getTmpFileSize(tmpFileName)); fileData.setCreateDate(new Date()); return fileRepository.save(fileData); } public String uploadToTmpDir(MultipartFile multipartFile) throws IOException { - String tmpFileName = String.valueOf(System.currentTimeMillis()); + String tmpFileName = String.valueOf(System.currentTimeMillis()) + UUID.randomUUID(); Files.write(getTmpFilePath(tmpFileName), multipartFile.getBytes()); String meta = multipartFile.getOriginalFilename() + "\n" + multipartFile.getSize(); Files.write(getTmpFileMetaPath(tmpFileName), meta.getBytes(UTF_8)); @@ -78,4 +83,39 @@ public class FileService { public void deleteFile(FileData fileData) { fileRepository.delete(fileData); } + + public List saveOrCreate(List fileDtos) throws IOException { + List files = new ArrayList<>(); + for (FileDataDto file : fileDtos) { + files.add(file.getId() != null ? update(file) : create(file)); + } + return files; + } + + @Transactional + public FileData update(FileDataDto fileDataDto) { + FileData file = fileRepository.findOne(fileDataDto.getId()); + return fileRepository.save(copyFromDto(file, fileDataDto)); + } + + @Transactional + public FileData create(FileDataDto fileDataDto) throws IOException { + FileData newFile = createFileFromTmp(fileDataDto.getTmpFileName()); + copyFromDto(newFile, fileDataDto); + return fileRepository.save(newFile); + } + + private FileData copyFromDto(FileData fileData, FileDataDto fileDataDto) { + fileData.setName(fileDataDto.getName()); + return fileData; + } + + @Transactional + public void delete(Integer fileId) { + fileRepository.delete(fileRepository.findOne(fileId)); + } + + public FileDataDto createFromMultipartFile(MultipartFile multipartFile) throws IOException { + return new FileDataDto(multipartFile.getOriginalFilename(), uploadToTmpDir(multipartFile)); + } } diff --git a/src/main/java/ru/ulstu/grant/controller/GrantController.java b/src/main/java/ru/ulstu/grant/controller/GrantController.java index c786ffa..65b11dc 100644 --- a/src/main/java/ru/ulstu/grant/controller/GrantController.java +++ b/src/main/java/ru/ulstu/grant/controller/GrantController.java @@ -13,6 +13,7 @@ import ru.ulstu.deadline.model.Deadline; import ru.ulstu.grant.model.Grant; import ru.ulstu.grant.model.GrantDto; import ru.ulstu.grant.service.GrantService; +import springfox.documentation.annotations.ApiIgnore; import javax.validation.Valid; import java.io.IOException; @@ -28,6 +29,7 @@ import static ru.ulstu.grant.controller.Navigation.hasErrors; @Controller() @RequestMapping(value = "/grants") +@ApiIgnore public class GrantController { private final GrantService grantService; diff --git a/src/main/java/ru/ulstu/index/controller/IndexController.java b/src/main/java/ru/ulstu/index/controller/IndexController.java index d964997..f6ab100 100644 --- a/src/main/java/ru/ulstu/index/controller/IndexController.java +++ b/src/main/java/ru/ulstu/index/controller/IndexController.java @@ -6,9 +6,11 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import ru.ulstu.core.controller.AdviceController; import ru.ulstu.user.service.UserService; +import springfox.documentation.annotations.ApiIgnore; @Controller() @RequestMapping(value = "/index") +@ApiIgnore public class IndexController extends AdviceController { public IndexController(UserService userService) { super(userService); diff --git a/src/main/java/ru/ulstu/paper/controller/PaperController.java b/src/main/java/ru/ulstu/paper/controller/PaperController.java index 31df0e3..9169bd9 100644 --- a/src/main/java/ru/ulstu/paper/controller/PaperController.java +++ b/src/main/java/ru/ulstu/paper/controller/PaperController.java @@ -15,6 +15,7 @@ import ru.ulstu.paper.model.PaperDto; import ru.ulstu.paper.model.PaperFilterDto; import ru.ulstu.paper.service.PaperService; import ru.ulstu.user.model.User; +import springfox.documentation.annotations.ApiIgnore; import javax.validation.Valid; import java.io.IOException; @@ -28,6 +29,7 @@ import static org.springframework.util.StringUtils.isEmpty; @Controller() @RequestMapping(value = "/papers") +@ApiIgnore public class PaperController { private final PaperService paperService; diff --git a/src/main/java/ru/ulstu/paper/model/Paper.java b/src/main/java/ru/ulstu/paper/model/Paper.java index 685a901..623d3fb 100644 --- a/src/main/java/ru/ulstu/paper/model/Paper.java +++ b/src/main/java/ru/ulstu/paper/model/Paper.java @@ -6,6 +6,7 @@ import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.UserContainer; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.file.model.FileData; +import ru.ulstu.timeline.model.Event; import ru.ulstu.user.model.User; import javax.persistence.CascadeType; @@ -16,7 +17,6 @@ import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.Temporal; @@ -75,11 +75,18 @@ public class Paper extends BaseEntity implements UserContainer { private String comment; + private String url; + private Boolean locked = false; - @ManyToOne - @JoinColumn(name = "file_id") - private FileData fileData; + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "paper_id") + private List events = new ArrayList<>(); + + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "paper_id", unique = true) + @Fetch(FetchMode.SUBSELECT) + private List files = new ArrayList<>(); @ManyToMany(fetch = FetchType.EAGER) private Set authors = new HashSet<>(); @@ -132,12 +139,12 @@ public class Paper extends BaseEntity implements UserContainer { this.locked = locked; } - public FileData getFileData() { - return fileData; + public List getFiles() { + return files; } - public void setFileData(FileData fileData) { - this.fileData = fileData; + public void setFiles(List files) { + this.files = files; } public String getTitle() { @@ -156,6 +163,22 @@ public class Paper extends BaseEntity implements UserContainer { this.authors = authors; } + public List getEvents() { + return events; + } + + public void setEvents(List events) { + this.events = events; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + @Override public Set getUsers() { return getAuthors(); diff --git a/src/main/java/ru/ulstu/paper/model/PaperDto.java b/src/main/java/ru/ulstu/paper/model/PaperDto.java index c828381..da6f5d0 100644 --- a/src/main/java/ru/ulstu/paper/model/PaperDto.java +++ b/src/main/java/ru/ulstu/paper/model/PaperDto.java @@ -3,6 +3,7 @@ package ru.ulstu.paper.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang3.StringUtils; +import ru.ulstu.file.model.FileDataDto; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.user.model.UserDto; @@ -29,11 +30,9 @@ public class PaperDto { @NotEmpty private List deadlines = new ArrayList<>(); private String comment; + private String url; private Boolean locked; - private String tmpFileName; - private Integer fileId; - private String fileName; - private Date fileCreateDate; + private List files = new ArrayList<>(); private Set authorIds; private Set authors; private Integer filterAuthorId; @@ -50,8 +49,9 @@ public class PaperDto { @JsonProperty("updateDate") Date updateDate, @JsonProperty("deadlines") List deadlines, @JsonProperty("comment") String comment, + @JsonProperty("url") String url, @JsonProperty("locked") Boolean locked, - @JsonProperty("tmpFileName") String tmpFileName, + @JsonProperty("files") List files, @JsonProperty("authorIds") Set authorIds, @JsonProperty("authors") Set authors) { this.id = id; @@ -61,11 +61,9 @@ public class PaperDto { this.updateDate = updateDate; this.deadlines = deadlines; this.comment = comment; + this.url = url; this.locked = locked; - this.tmpFileName = tmpFileName; - this.fileId = null; - this.fileName = null; - this.fileCreateDate = null; + this.files = files; this.authors = authors; } @@ -77,11 +75,9 @@ public class PaperDto { this.updateDate = paper.getUpdateDate(); this.deadlines = paper.getDeadlines(); this.comment = paper.getComment(); + this.url = paper.getUrl(); this.locked = paper.getLocked(); - this.tmpFileName = null; - this.fileId = paper.getFileData() == null ? null : paper.getFileData().getId(); - this.fileName = paper.getFileData() == null ? null : paper.getFileData().getName(); - this.fileCreateDate = paper.getFileData() == null ? null : paper.getFileData().getCreateDate(); + this.files = convert(paper.getFiles(), FileDataDto::new); this.authorIds = convert(paper.getAuthors(), user -> user.getId()); this.authors = convert(paper.getAuthors(), UserDto::new); } @@ -150,36 +146,12 @@ public class PaperDto { this.locked = locked; } - public String getTmpFileName() { - return tmpFileName; + public List getFiles() { + return files; } - public void setTmpFileName(String tmpFileName) { - this.tmpFileName = tmpFileName; - } - - public Integer getFileId() { - return fileId; - } - - public void setFileId(Integer fileId) { - this.fileId = fileId; - } - - public String getFileName() { - return fileName; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public Date getFileCreateDate() { - return fileCreateDate; - } - - public void setFileCreateDate(Date fileCreateDate) { - this.fileCreateDate = fileCreateDate; + public void setFiles(List files) { + this.files = files; } public Set getAuthors() { @@ -198,6 +170,14 @@ public class PaperDto { this.authorIds = authorIds; } + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + public String getAuthorsString() { return StringUtils.abbreviate(authors .stream() diff --git a/src/main/java/ru/ulstu/paper/service/PaperService.java b/src/main/java/ru/ulstu/paper/service/PaperService.java index f724bdb..328a52b 100644 --- a/src/main/java/ru/ulstu/paper/service/PaperService.java +++ b/src/main/java/ru/ulstu/paper/service/PaperService.java @@ -5,11 +5,13 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.service.DeadlineService; +import ru.ulstu.file.model.FileDataDto; import ru.ulstu.file.service.FileService; import ru.ulstu.paper.model.Paper; import ru.ulstu.paper.model.PaperDto; import ru.ulstu.paper.model.PaperFilterDto; import ru.ulstu.paper.repository.PaperRepository; +import ru.ulstu.timeline.service.EventService; import ru.ulstu.user.model.User; import ru.ulstu.user.service.UserService; @@ -19,8 +21,8 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; +import static java.util.stream.Collectors.toList; import static org.springframework.util.ObjectUtils.isEmpty; import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.paper.model.Paper.PaperStatus.ATTENTION; @@ -38,17 +40,20 @@ public class PaperService { private final UserService userService; private final DeadlineService deadlineService; private final FileService fileService; + private final EventService eventService; public PaperService(PaperRepository paperRepository, FileService fileService, PaperNotificationService paperNotificationService, UserService userService, - DeadlineService deadlineService) { + DeadlineService deadlineService, + EventService eventService) { this.paperRepository = paperRepository; this.fileService = fileService; this.paperNotificationService = paperNotificationService; this.userService = userService; this.deadlineService = deadlineService; + this.eventService = eventService; } public List findAll() { @@ -65,7 +70,7 @@ public class PaperService { return findAllDto() .stream() .filter(paper -> paper.getStatus() != COMPLETED && paper.getStatus() != FAILED) - .collect(Collectors.toList()); + .collect(toList()); } public PaperDto findOneDto(Integer id) { @@ -77,20 +82,22 @@ public class PaperService { Paper newPaper = copyFromDto(new Paper(), paperDto); newPaper = paperRepository.save(newPaper); paperNotificationService.sendCreateNotification(newPaper); + eventService.createFromPaper(newPaper); return newPaper.getId(); } private Paper copyFromDto(Paper paper, PaperDto paperDto) throws IOException { paper.setComment(paperDto.getComment()); + paper.setUrl(paperDto.getUrl()); paper.setCreateDate(paper.getCreateDate() == null ? new Date() : paper.getCreateDate()); paper.setLocked(paperDto.getLocked()); paper.setStatus(paperDto.getStatus() == null ? DRAFT : paperDto.getStatus()); paper.setTitle(paperDto.getTitle()); paper.setUpdateDate(new Date()); paper.setDeadlines(deadlineService.saveOrCreate(paperDto.getDeadlines())); - if (paperDto.getTmpFileName() != null) { - paper.setFileData(fileService.createFileFromTmp(paperDto.getTmpFileName())); - } + paper.setFiles(fileService.saveOrCreate(paperDto.getFiles().stream() + .filter(f -> !f.isDeleted()) + .collect(toList()))); paper.getAuthors().clear(); if (paperDto.getAuthorIds() != null && !paperDto.getAuthorIds().isEmpty()) { paperDto.getAuthorIds().forEach(authorIds -> paper.getAuthors().add(userService.findById(authorIds))); @@ -103,10 +110,14 @@ public class PaperService { Paper paper = paperRepository.getOne(paperDto.getId()); Paper.PaperStatus oldStatus = paper.getStatus(); Set oldAuthors = new HashSet<>(paper.getAuthors()); - if (paperDto.getTmpFileName() != null && paper.getFileData() != null) { - fileService.deleteFile(paper.getFileData()); + + for (FileDataDto file : paperDto.getFiles().stream() + .filter(f -> f.isDeleted() && f.getId() != null) + .collect(toList())) { + fileService.delete(file.getId()); } paperRepository.save(copyFromDto(paper, paperDto)); + eventService.updatePaperDeadlines(paper); paper.getAuthors().forEach(author -> { if (!oldAuthors.contains(author)) { @@ -124,9 +135,6 @@ public class PaperService { @Transactional public void delete(Integer paperId) throws IOException { Paper paper = paperRepository.getOne(paperId); - if (paper.getFileData() != null) { - fileService.deleteFile(paper.getFileData()); - } paperRepository.delete(paper); } @@ -146,6 +154,7 @@ public class PaperService { paper = paperRepository.save(paper); paperNotificationService.sendCreateNotification(paper); + eventService.createFromPaper(paper); return paper; } @@ -165,7 +174,7 @@ public class PaperService { return statusCompareResult; } return paper1.getTitle().compareTo(paper2.getTitle()); - }).collect(Collectors.toList()); + }).collect(toList()); } public PaperDto findPaper(int id) { @@ -179,7 +188,7 @@ public class PaperService { && (paper.getStatus() == ON_PREPARATION || paper.getStatus() == DRAFT || paper.getStatus() == ATTENTION)) - .collect(Collectors.toList()); + .collect(toList()); papers.forEach(paper -> { Paper.PaperStatus oldStatus = paper.getStatus(); paper.setStatus(Paper.PaperStatus.FAILED); diff --git a/src/main/java/ru/ulstu/timeline/model/Event.java b/src/main/java/ru/ulstu/timeline/model/Event.java index f64963d..ef0a4b8 100644 --- a/src/main/java/ru/ulstu/timeline/model/Event.java +++ b/src/main/java/ru/ulstu/timeline/model/Event.java @@ -1,6 +1,8 @@ package ru.ulstu.timeline.model; +import org.hibernate.validator.constraints.NotBlank; import ru.ulstu.core.model.BaseEntity; +import ru.ulstu.paper.model.Paper; import ru.ulstu.user.model.User; import javax.persistence.CascadeType; @@ -15,7 +17,6 @@ import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Temporal; import javax.persistence.TemporalType; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.util.Date; import java.util.List; @@ -71,6 +72,10 @@ public class Event extends BaseEntity { @JoinColumn(name = "child_id") private List parents; + @ManyToOne + @JoinColumn(name = "paper_id") + private Paper paper; + public String getTitle() { return title; } @@ -150,4 +155,12 @@ public class Event extends BaseEntity { public void setParents(List parents) { this.parents = parents; } + + public Paper getPaper() { + return paper; + } + + public void setPaper(Paper paper) { + this.paper = paper; + } } diff --git a/src/main/java/ru/ulstu/timeline/model/EventDto.java b/src/main/java/ru/ulstu/timeline/model/EventDto.java index b053d36..17e4623 100644 --- a/src/main/java/ru/ulstu/timeline/model/EventDto.java +++ b/src/main/java/ru/ulstu/timeline/model/EventDto.java @@ -2,9 +2,10 @@ package ru.ulstu.timeline.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import javax.validation.constraints.NotBlank; +import ru.ulstu.paper.model.PaperDto; import ru.ulstu.user.model.UserDto; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.util.Date; import java.util.List; @@ -23,6 +24,7 @@ public class EventDto { private final Date updateDate; private final String description; private final List recipients; + private PaperDto paperDto; @JsonCreator public EventDto(@JsonProperty("id") Integer id, @@ -33,6 +35,7 @@ public class EventDto { @JsonProperty("createDate") Date createDate, @JsonProperty("updateDate") Date updateDate, @JsonProperty("description") String description, + @JsonProperty("paperDto") PaperDto paperDto, @JsonProperty("recipients") List recipients) { this.id = id; this.title = title; @@ -43,6 +46,7 @@ public class EventDto { this.updateDate = updateDate; this.description = description; this.recipients = recipients; + this.paperDto = paperDto; } public EventDto(Event event) { @@ -54,6 +58,7 @@ public class EventDto { this.createDate = event.getCreateDate(); this.updateDate = event.getUpdateDate(); this.description = event.getDescription(); + this.paperDto = new PaperDto(event.getPaper()); this.recipients = convert(event.getRecipients(), UserDto::new); } @@ -92,4 +97,12 @@ public class EventDto { public Date getExecuteDate() { return executeDate; } + + public PaperDto getPaperDto() { + return paperDto; + } + + public void setPaperDto(PaperDto paperDto) { + this.paperDto = paperDto; + } } diff --git a/src/main/java/ru/ulstu/timeline/model/Timeline.java b/src/main/java/ru/ulstu/timeline/model/Timeline.java index 8e588cb..06e04bc 100644 --- a/src/main/java/ru/ulstu/timeline/model/Timeline.java +++ b/src/main/java/ru/ulstu/timeline/model/Timeline.java @@ -6,6 +6,7 @@ import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; +import java.util.ArrayList; import java.util.List; @Entity @@ -13,7 +14,7 @@ public class Timeline extends BaseEntity { @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "timeline_id") - private List events; + private List events = new ArrayList<>(); public List getEvents() { return events; diff --git a/src/main/java/ru/ulstu/timeline/repository/EventRepository.java b/src/main/java/ru/ulstu/timeline/repository/EventRepository.java index 4848e12..eb5c08b 100644 --- a/src/main/java/ru/ulstu/timeline/repository/EventRepository.java +++ b/src/main/java/ru/ulstu/timeline/repository/EventRepository.java @@ -2,6 +2,7 @@ package ru.ulstu.timeline.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import ru.ulstu.paper.model.Paper; import ru.ulstu.timeline.model.Event; import java.util.List; @@ -12,4 +13,6 @@ public interface EventRepository extends JpaRepository { @Query("SELECT e FROM Event e WHERE e.executeDate > CURRENT_DATE ORDER BY e.executeDate") List findAllFuture(); + + List findAllByPaper(Paper paper); } diff --git a/src/main/java/ru/ulstu/timeline/service/EventScheduler.java b/src/main/java/ru/ulstu/timeline/service/EventScheduler.java index 6df7fcb..7899aca 100644 --- a/src/main/java/ru/ulstu/timeline/service/EventScheduler.java +++ b/src/main/java/ru/ulstu/timeline/service/EventScheduler.java @@ -34,6 +34,10 @@ public class EventScheduler { Map variables = ImmutableMap.of("description", event.getDescription()); event.getRecipients() .forEach(recipient -> mailService.sendEmailFromTemplate(variables, recipient, "eventNotification", event.getTitle())); + if (event.getPeriod() == null) { + event.setStatus(Event.EventStatus.COMPLETED); + eventService.save(event); + } }); } diff --git a/src/main/java/ru/ulstu/timeline/service/EventService.java b/src/main/java/ru/ulstu/timeline/service/EventService.java index 7d0d251..2a8858f 100644 --- a/src/main/java/ru/ulstu/timeline/service/EventService.java +++ b/src/main/java/ru/ulstu/timeline/service/EventService.java @@ -1,15 +1,22 @@ package ru.ulstu.timeline.service; +import org.apache.commons.lang3.time.DateUtils; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.deadline.model.Deadline; +import ru.ulstu.paper.model.Paper; import ru.ulstu.timeline.model.Event; import ru.ulstu.timeline.model.EventDto; +import ru.ulstu.timeline.model.Timeline; import ru.ulstu.timeline.repository.EventRepository; import ru.ulstu.user.model.UserDto; import ru.ulstu.user.service.UserService; +import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; import static ru.ulstu.core.util.StreamApiUtils.convert; @@ -17,11 +24,14 @@ import static ru.ulstu.core.util.StreamApiUtils.convert; public class EventService { private final EventRepository eventRepository; + private final TimelineService timelineService; private final UserService userService; public EventService(EventRepository eventRepository, + @Lazy TimelineService timelineService, UserService userService) { this.eventRepository = eventRepository; + this.timelineService = timelineService; this.userService = userService; } @@ -56,6 +66,11 @@ public class EventService { return eventRepository.save(copyFromDto(event, eventDto)).getId(); } + @Transactional + public Event save(Event event) { + return eventRepository.save(event); + } + @Transactional public void delete(Integer eventId) { Event event = eventRepository.getOne(eventId); @@ -84,6 +99,36 @@ public class EventService { eventRepository.save(parentEvent); } + public void createFromPaper(Paper newPaper) { + List timelines = timelineService.findAll(); + Timeline timeline = timelines.isEmpty() ? new Timeline() : timelines.get(0); + + for (Deadline deadline : newPaper.getDeadlines() + .stream() + .filter(d -> d.getDate().after(new Date()) || DateUtils.isSameDay(d.getDate(), new Date())) + .collect(Collectors.toList())) { + Event newEvent = new Event(); + newEvent.setTitle("Дедлайн статьи"); + newEvent.setStatus(Event.EventStatus.NEW); + newEvent.setExecuteDate(deadline.getDate()); + newEvent.setCreateDate(new Date()); + newEvent.setUpdateDate(new Date()); + newEvent.setDescription("Дедлайн '" + deadline.getDescription() + "' cтатьи '" + newPaper.getTitle() + "'"); + newEvent.setRecipients(new ArrayList(newPaper.getAuthors())); + newEvent.setPaper(newPaper); + eventRepository.save(newEvent); + + timeline.getEvents().add(newEvent); + timelineService.save(timeline); + } + } + + public void updatePaperDeadlines(Paper paper) { + eventRepository.delete(eventRepository.findAllByPaper(paper)); + + createFromPaper(paper); + } + public List findByCurrentDate() { return eventRepository.findByCurrentDate(); } diff --git a/src/main/java/ru/ulstu/timeline/service/TimelineService.java b/src/main/java/ru/ulstu/timeline/service/TimelineService.java index 4101f92..dd5c384 100644 --- a/src/main/java/ru/ulstu/timeline/service/TimelineService.java +++ b/src/main/java/ru/ulstu/timeline/service/TimelineService.java @@ -23,15 +23,24 @@ public class TimelineService { this.eventService = eventService; } - public List findAll() { + public List findAllDto() { return convert(timelineRepository.findAll(), TimelineDto::new); } + public List findAll() { + return timelineRepository.findAll(); + } + @Transactional public int create(TimelineDto timelineDto) { return timelineRepository.save(copyFromDto(new Timeline(), timelineDto)).getId(); } + @Transactional + public Timeline save(Timeline timeline) { + return timelineRepository.save(timeline); + } + private Timeline copyFromDto(Timeline timeline, TimelineDto timelineDto) { timeline.setEvents(eventService.findByIds(convert(timelineDto.getEvents(), EventDto::getId))); return timeline; diff --git a/src/main/resources/commits.log b/src/main/resources/commits.log index cb97503..5d1bca7 100644 --- a/src/main/resources/commits.log +++ b/src/main/resources/commits.log @@ -1,489 +1,298 @@ -Anton Romanov;Thu Mar 15 11:10:34 2018 +0400;change to date time -romanov73;Thu Mar 15 11:03:19 2018 +0400;read commits in constructor -romanov73;Thu Mar 15 09:12:07 2018 +0400;add commits page -Romanov Anton;Wed Mar 14 20:26:54 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 20:16:53 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 20:08:09 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 20:00:58 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 19:50:22 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 19:34:17 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 19:20:42 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:59:18 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:47:17 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:35:37 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:33:54 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:29:27 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:21:18 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:19:27 2018 +0000;Update README.md -Romanov Anton;Wed Mar 14 18:16:06 2018 +0000;Update README.md -romanov73;Wed Mar 14 21:28:10 2018 +0400;fix using constant -Aleksey Filippov;Wed Mar 14 20:07:25 2018 +0400;some fixes after merge -Aleksey Filippov;Wed Mar 14 19:52:45 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into odin-ui -Aleksey Filippov;Wed Mar 14 19:48:45 2018 +0400;refactoring of odin paginator -romanov73;Wed Mar 14 18:43:16 2018 +0400;Merge branch 'develop' into 36-rest -romanov73;Wed Mar 14 18:17:02 2018 +0400;Merge branch 'develop' into 36-rest -Aleksey Filippov;Wed Mar 14 18:11:00 2018 +0400;fix null value check in formatter -Aleksey Filippov;Wed Mar 14 18:06:16 2018 +0400;fix odin paginator style, fix odin negative file -romanov73;Wed Mar 14 18:04:47 2018 +0400;rename entities -Aleksey Filippov;Wed Mar 14 17:58:59 2018 +0400;improve odin table look -romanov73;Wed Mar 14 17:47:45 2018 +0400;fix db changelogs -romanov73;Wed Mar 14 17:47:20 2018 +0400;fix db changelogs -Gleb;Wed Mar 14 08:50:23 2018 +0000;Merge branch '48-' into 'develop' -funny73;Wed Mar 14 12:28:55 2018 +0400;Поправил отображение подразделения при редактировании смены -Aleksey Filippov;Wed Mar 14 00:02:24 2018 +0400;move navbar to the left, move odin css to separate file -Aleksey Filippov;Tue Mar 13 23:26:33 2018 +0400;some style fixes -Aleksey Filippov;Tue Mar 13 23:22:37 2018 +0400;move version panel to navbar -funny73;Tue Mar 13 20:41:41 2018 +0400;Поправил валидацию сменности -romanov73;Tue Mar 13 17:26:54 2018 +0400;fix offsetable page request -romanov73;Tue Mar 13 17:26:02 2018 +0400;fix table constructor -romanov73;Tue Mar 13 17:24:56 2018 +0400;fix checking empty value -Romanov Anton;Tue Mar 13 13:09:41 2018 +0000;Merge branch 'odin-ui' into '36-rest' -Aleksey Filippov;Tue Mar 13 16:59:27 2018 +0400;notes updated -Aleksey Filippov;Tue Mar 13 16:56:00 2018 +0400;odin refactoring -Aleksey Filippov;Tue Mar 13 16:53:38 2018 +0400;odin refactoring -romanov73;Tue Mar 13 15:27:17 2018 +0400;fix tool load calc -romanov73;Tue Mar 13 14:46:46 2018 +0400;fix area load calc -Aleksey Filippov;Tue Mar 13 13:38:23 2018 +0400;some fixes -romanov73;Tue Mar 13 13:33:25 2018 +0400;Merge remote-tracking branch 'origin/develop' into develop -romanov73;Tue Mar 13 13:33:07 2018 +0400;fix tools count calc -Aleksey Filippov;Tue Mar 13 13:12:09 2018 +0400;some odin refactoring -Aleksey Filippov;Tue Mar 13 13:11:41 2018 +0400;some offsetablepagerequest fix -Aleksey Filippov;Tue Mar 13 13:06:48 2018 +0400;add offsetablepagerequest -Aleksey Filippov;Tue Mar 13 07:27:12 2018 +0000;Merge branch '51-rest-points' into '36-rest' -romanov73;Tue Mar 13 11:22:02 2018 +0400;fix by comment: remove default version id -romanov73;Tue Mar 13 00:04:50 2018 +0400;fix path -romanov73;Mon Mar 12 23:55:05 2018 +0400;add tool square dictionary -romanov73;Mon Mar 12 23:36:49 2018 +0400;add dictionary pages -romanov73;Mon Mar 12 23:18:01 2018 +0400;sort second level menu items by name -romanov73;Mon Mar 12 23:11:22 2018 +0400;fix menu -romanov73;Mon Mar 12 22:52:15 2018 +0400;add stream api utils and converter for "map ... collect" -funny73;Mon Mar 12 20:01:47 2018 +0400;Добавил свойство базового изделия для изделия -romanov73;Mon Mar 12 19:46:52 2018 +0400;refactor units -romanov73;Mon Mar 12 19:36:57 2018 +0400;refactor tool types and work types -romanov73;Mon Mar 12 19:20:23 2018 +0400;refactor tools -romanov73;Mon Mar 12 19:07:09 2018 +0400;refactor stages -romanov73;Mon Mar 12 18:53:26 2018 +0400;refactor positions -romanov73;Mon Mar 12 18:27:36 2018 +0400;refactor employees -romanov73;Mon Mar 12 18:26:49 2018 +0400;refactor employees -romanov73;Mon Mar 12 18:09:38 2018 +0400;refactor categories -Aleksey Filippov;Mon Mar 12 17:32:06 2018 +0400;todo added -Aleksey Filippov;Mon Mar 12 17:29:51 2018 +0400;paginator added to odin -Aleksey Filippov;Mon Mar 12 17:29:06 2018 +0400;notes updated -funny73;Mon Mar 12 16:29:13 2018 +0400;Добавил сущность изделие без привязки к производственной программе -funny73;Mon Mar 12 15:16:35 2018 +0400;Переименовал сущность Product на ProductOnProgram Ещё немного переименования -funny73;Mon Mar 12 14:39:52 2018 +0400;Переименовал сущность Product на ProductOnProgram -Aleksey Filippov;Mon Mar 12 13:44:42 2018 +0400;add formatters and initial form support to odin -Aleksey Filippov;Mon Mar 12 13:44:16 2018 +0400;userlistdto refactoring -Aleksey Filippov;Mon Mar 12 13:43:59 2018 +0400;dateutils improvements -Aleksey Filippov;Mon Mar 12 13:43:43 2018 +0400;add support of localdatetime type to odin -Aleksey Filippov;Mon Mar 12 13:42:54 2018 +0400;odin backend example added -Aleksey Filippov;Mon Mar 12 13:42:12 2018 +0400;notes updated -funny73;Mon Mar 12 12:16:02 2018 +0400;Поправил всплывающие сообщения при работе с "Категориями" -Aleksey Filippov;Mon Mar 12 11:25:51 2018 +0400;some refactoring -Aleksey Filippov;Mon Mar 12 11:25:30 2018 +0400;odinid annotation added -Aleksey Filippov;Sun Mar 11 15:23:49 2018 +0400;notes updated -Aleksey Filippov;Sun Mar 11 15:18:45 2018 +0400;some fixes -Aleksey Filippov;Sun Mar 11 15:09:57 2018 +0400;simple table draw support added, some refactoring -Aleksey Filippov;Sun Mar 11 15:08:22 2018 +0400;add user id field to userlistdto -Aleksey Filippov;Sun Mar 11 14:32:50 2018 +0400;add jsonproperty annotation support -Aleksey Filippov;Sun Mar 11 13:38:45 2018 +0400;some template fixes -Aleksey Filippov;Sun Mar 11 13:33:09 2018 +0400;some balance page fixes -Aleksey Filippov;Sun Mar 11 13:25:58 2018 +0400;add jsonignore annotation support -Aleksey Filippov;Thu Mar 8 14:16:20 2018 +0400;some odin improvements -Aleksey Filippov;Wed Mar 7 16:03:04 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Wed Mar 7 16:01:21 2018 +0400;odin submodule for basic types added, some refactoring -romanov73;Tue Mar 6 22:52:02 2018 +0400;remove old packages -romanov73;Tue Mar 6 19:12:27 2018 +0400;add tool type crud -romanov73;Tue Mar 6 13:09:51 2018 +0400;add version crud -romanov73;Tue Mar 6 10:48:36 2018 +0400;add unit crud -romanov73;Mon Mar 5 16:58:37 2018 +0400;fix tree -romanov73;Mon Mar 5 16:38:37 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -romanov73;Mon Mar 5 16:38:21 2018 +0400;employee crud -Aleksey Filippov;Mon Mar 5 15:43:49 2018 +0400;some fixes -Aleksey Filippov;Mon Mar 5 15:39:53 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Mon Mar 5 15:39:33 2018 +0400;user reset password function added, some refactoring -romanov73;Mon Mar 5 15:29:16 2018 +0400;fix delete category -Aleksey Filippov;Mon Mar 5 15:08:27 2018 +0400;user change password function added, some refactoring -romanov73;Mon Mar 5 15:08:17 2018 +0400;add category crud -romanov73;Mon Mar 5 14:07:10 2018 +0400;add tree component -Aleksey Filippov;Mon Mar 5 11:30:22 2018 +0400;user delete function added, some refactoring -Aleksey Filippov;Mon Mar 5 11:18:23 2018 +0400;user update function added -Aleksey Filippov;Mon Mar 5 11:18:06 2018 +0400;some refactoring -Aleksey Filippov;Mon Mar 5 10:06:04 2018 +0400;add user activation function -Aleksey Filippov;Mon Mar 5 09:48:22 2018 +0400;add scheduler for users -Aleksey Filippov;Mon Mar 5 09:48:07 2018 +0400;add activateddate field to userentity -Aleksey Filippov;Mon Mar 5 09:47:25 2018 +0400;notes file updated -Aleksey Filippov;Mon Mar 5 09:47:11 2018 +0400;some refactoring -Aleksey Filippov;Mon Mar 5 09:21:49 2018 +0400;thymeleaf cache settings added -Aleksey Filippov;Mon Mar 5 09:21:11 2018 +0400;notes file added -Aleksey Filippov;Mon Mar 5 09:20:57 2018 +0400;some refactoring -Aleksey Filippov;Mon Mar 5 08:37:01 2018 +0400;some refactoring -romanov73;Mon Mar 5 00:08:02 2018 +0400;add callbacks on version getters -romanov73;Mon Mar 5 00:07:34 2018 +0400;fix npe -romanov73;Sun Mar 4 01:13:57 2018 +0400;fix column style -romanov73;Sun Mar 4 01:06:38 2018 +0400;fix table style -romanov73;Sun Mar 4 00:27:14 2018 +0400;add balance dto + draw employee balance -romanov73;Sat Mar 3 22:43:06 2018 +0400;add balance services -romanov73;Sat Mar 3 16:31:19 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -romanov73;Sat Mar 3 16:31:04 2018 +0400;add employee balance table -Aleksey Filippov;Sat Mar 3 15:54:23 2018 +0400;some user support improvements -Aleksey Filippov;Sat Mar 3 15:53:20 2018 +0400;edit migration files, need manual fix of databasechangelog table -Aleksey Filippov;Sat Mar 3 15:51:58 2018 +0400;add application properties handler -Aleksey Filippov;Sat Mar 3 15:51:19 2018 +0400;disable tests -Aleksey Filippov;Sat Mar 3 13:49:32 2018 +0400;some refactoring -romanov73;Fri Mar 2 18:10:23 2018 +0400;add balance page -Aleksey Filippov;Fri Mar 2 18:04:39 2018 +0400;some refactoring -Aleksey Filippov;Fri Mar 2 17:51:41 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Fri Mar 2 17:50:59 2018 +0400;advicecontroller improvements -Aleksey Filippov;Fri Mar 2 17:50:39 2018 +0400;some mvc improvements -romanov73;Fri Mar 2 15:15:46 2018 +0400;add dtos -romanov73;Fri Mar 2 15:02:38 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Fri Mar 2 14:54:33 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Fri Mar 2 14:53:39 2018 +0400;add migrations -Aleksey Filippov;Fri Mar 2 14:53:30 2018 +0400;some core improvements -Aleksey Filippov;Fri Mar 2 14:53:13 2018 +0400;some users improvements -romanov73;Fri Mar 2 12:42:54 2018 +0400;add category service -romanov73;Fri Mar 2 12:37:51 2018 +0400;fix unit service -romanov73;Fri Mar 2 11:24:11 2018 +0400;add unit controller -romanov73;Thu Mar 1 23:19:42 2018 +0400;fix versions panel -romanov73;Thu Mar 1 22:50:57 2018 +0400;Merge branch 'develop' into 36-rest -romanov73;Thu Mar 1 22:50:37 2018 +0400;Merge branch 'develop' into 36-rest -Romanov Anton;Thu Mar 1 18:31:03 2018 +0000;Merge branch '29-' into 'develop' -romanov73;Thu Mar 1 22:25:49 2018 +0400;change versions -romanov73;Thu Mar 1 20:14:22 2018 +0400;show version select -romanov73;Thu Mar 1 19:56:24 2018 +0400;add old models, add versions controller -romanov73;Thu Mar 1 19:55:59 2018 +0400;add old models, add versions controller -romanov73;Thu Mar 1 19:04:47 2018 +0400;save menu to session -romanov73;Thu Mar 1 18:50:00 2018 +0400;add favicon -funny73;Thu Mar 1 18:01:43 2018 +0400;1) Поправил имена колонок и таблицы для смен под постгрес 2) Исправил ошибку в имени переменной thidShift ->thirdShift -romanov73;Thu Mar 1 16:03:03 2018 +0400;add menu and restore changelogs -funny73;Thu Mar 1 15:33:36 2018 +0400;Добавил распорядок смен для каждого подразделения. Смена назначается на месяц. Есть возможность сохранить любой вариант комбинирования 1,2 и 3 смены. Например (1,3); (2); ()... Добавлен интерфейс для просмотра и редактирования распорядка смен по каждому подразделению. Добавлена валидация - для каждого месяца может быть только один распорядок смен. -Aleksey Filippov;Thu Mar 1 15:23:06 2018 +0400;migrate to webjars -Aleksey Filippov;Thu Mar 1 13:31:16 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Thu Mar 1 13:30:55 2018 +0400;create migrations for user models -Aleksey Filippov;Thu Mar 1 13:30:09 2018 +0400;old code refactoring -romanov73;Thu Mar 1 12:51:14 2018 +0400;add basic menu from rest -romanov73;Thu Mar 1 11:51:17 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -romanov73;Thu Mar 1 11:50:59 2018 +0400;try to fix ci: 3 remove tests -Aleksey Filippov;Thu Mar 1 11:50:25 2018 +0400;Merge remote-tracking branch 'origin/36-rest' into 36-rest -Aleksey Filippov;Thu Mar 1 11:49:59 2018 +0400;moved to new database -romanov73;Thu Mar 1 11:45:40 2018 +0400;try to fix ci: 2 change image -romanov73;Thu Mar 1 11:44:42 2018 +0400;try to fix ci: 1 -romanov73;Thu Mar 1 11:15:52 2018 +0400;fix csrf tokens -Aleksey Filippov;Thu Mar 1 00:25:43 2018 +0400;initial user management support added -romanov73;Wed Feb 28 22:26:00 2018 +0400;save current version in local storage -romanov73;Wed Feb 28 18:40:57 2018 +0400;add ajax datatable -romanov73;Wed Feb 28 18:01:23 2018 +0400;add static index page with menu -Romanov Anton;Tue Feb 27 16:53:04 2018 +0000;Merge branch '33-' into 'develop' -romanov73;Tue Feb 27 20:50:44 2018 +0400;calc area balance -romanov73;Tue Feb 27 17:36:31 2018 +0400;remove unused panel -Romanov Anton;Tue Feb 27 13:06:02 2018 +0000;Merge branch '32-' into 'develop' -romanov73;Tue Feb 27 17:02:35 2018 +0400;calc tool balance -romanov73;Tue Feb 27 15:45:39 2018 +0400;calc tool balance -romanov73;Tue Feb 27 12:16:41 2018 +0400;calc tool power -romanov73;Tue Feb 27 11:40:59 2018 +0400;use tool types in dto -romanov73;Tue Feb 27 11:29:05 2018 +0400;fix dtos -romanov73;Mon Feb 26 23:50:53 2018 +0400;inherit dtos -romanov73;Mon Feb 26 15:38:00 2018 +0400;fix services for balance calculation -Aleksey Filippov;Mon Feb 26 15:00:48 2018 +0400;move from maven to gradle, move from javaee to spring boot -romanov73;Thu Feb 22 18:03:35 2018 +0400;Add menu resource -Romanov Anton;Tue Feb 20 18:12:55 2018 +0000;Merge branch 'balance-different-dto' into 'develop' -romanov73;Tue Feb 20 22:09:33 2018 +0400;restore tests -romanov73;Tue Feb 20 21:46:45 2018 +0400;filter employees by stage -romanov73;Tue Feb 20 21:21:27 2018 +0400;filter employees by workload -romanov73;Tue Feb 20 20:58:23 2018 +0400;Merge branch 'develop' into balance-different-dto -funny73;Tue Feb 20 19:52:24 2018 +0400;Add shift unit model Add link to unit view -romanov73;Tue Feb 20 16:14:09 2018 +0400;Important fix using coefficient -romanov73;Mon Feb 19 19:00:07 2018 +0400;partially fix ajustment -romanov73;Mon Feb 19 18:24:10 2018 +0400;Modify dto for using with different periods and work types -Romanov Anton;Mon Feb 19 08:11:39 2018 +0000;Merge branch '30-' into 'develop' -romanov73;Mon Feb 19 12:09:05 2018 +0400;Add work type to position -Romanov Anton;Wed Feb 14 20:57:35 2018 +0000;Merge branch '34-' into 'develop' -romanov73;Thu Feb 15 00:51:24 2018 +0400;fixes by comments -romanov73;Thu Feb 15 00:47:21 2018 +0400;merge fields -romanov73;Wed Feb 14 23:42:35 2018 +0400;Merge branch 'develop' into 34-gleb -romanov73;Wed Feb 14 21:05:51 2018 +0400;add clock -Romanov Anton;Wed Feb 14 16:49:29 2018 +0000;Merge branch '45-balance-employee-recomendations' into 'develop' -romanov73;Wed Feb 14 20:46:59 2018 +0400;cleanup code -romanov73;Wed Feb 14 18:25:42 2018 +0400;reduce code -romanov73;Wed Feb 14 18:24:59 2018 +0400;adjust additional employees -romanov73;Wed Feb 14 17:22:10 2018 +0400;move employees from other units -romanov73;Tue Feb 13 23:59:09 2018 +0400;fix save product name -romanov73;Tue Feb 13 23:28:30 2018 +0400;add converter, fix UI and backing for add complex object -romanov73;Tue Feb 13 22:10:59 2018 +0400;Merge branch 'develop' into 34-gleb -funny73;Tue Feb 13 18:07:25 2018 +0400;Add stage to workload -funny73;Tue Feb 13 16:05:45 2018 +0400;Add stage to category -romanov73;Tue Feb 13 13:20:16 2018 +0400;add map of all units balances -romanov73;Tue Feb 13 11:24:50 2018 +0400;move method -romanov73;Tue Feb 13 00:35:30 2018 +0400;add dialog -romanov73;Mon Feb 12 22:59:49 2018 +0400;filter only workshops and manufactures -romanov73;Mon Feb 12 22:04:55 2018 +0400;rename employees -romanov73;Mon Feb 12 17:34:37 2018 +0400;fix font size -romanov73;Mon Feb 12 16:59:16 2018 +0400;fix versions panel width -Romanov Anton;Mon Feb 12 12:47:04 2018 +0000;Merge branch '41-' into 'develop' -romanov73;Mon Feb 12 16:43:06 2018 +0400;change to working hours -romanov73;Mon Feb 12 14:05:36 2018 +0400;remove constructor -romanov73;Mon Feb 12 14:05:13 2018 +0400;Merge remote-tracking branch 'origin/develop' into develop -romanov73;Mon Feb 12 14:04:57 2018 +0400;fix selects -Romanov Anton;Mon Feb 12 09:20:05 2018 +0000;Merge branch '39-work-type-code' into 'develop' -Aleksey Filippov;Mon Feb 12 13:16:36 2018 +0400;add migration for work type code -Aleksey Filippov;Mon Feb 12 13:16:28 2018 +0400;add work type code support to xhtml -Aleksey Filippov;Mon Feb 12 13:16:12 2018 +0400;add work type code -Romanov Anton;Mon Feb 12 08:25:47 2018 +0000;Update README.md -Romanov Anton;Mon Feb 12 08:25:35 2018 +0000;Update README.md -Romanov Anton;Mon Feb 12 08:07:30 2018 +0000;Update README.md -Romanov Anton;Mon Feb 12 07:10:38 2018 +0000;Merge branch '40-' into 'develop' -Aleksey Filippov;Mon Feb 12 11:08:13 2018 +0400;add migration for position type -Aleksey Filippov;Mon Feb 12 11:07:45 2018 +0400;add position type support to xhtml -Aleksey Filippov;Mon Feb 12 11:07:23 2018 +0400;move position converter from boundary to view -Aleksey Filippov;Mon Feb 12 11:06:55 2018 +0400;add position type converter -Aleksey Filippov;Mon Feb 12 11:06:35 2018 +0400;add position type to backing -Aleksey Filippov;Mon Feb 12 11:06:00 2018 +0400;add position type support to service -Aleksey Filippov;Mon Feb 12 11:05:44 2018 +0400;add position type to model -Romanov Anton;Mon Feb 12 07:02:32 2018 +0000;Merge branch '33-' into 'develop' -romanov73;Mon Feb 12 14:58:51 2018 +0400;refactor -romanov73;Mon Feb 12 14:58:33 2018 +0400;add human hours coefficient -romanov73;Mon Feb 12 14:56:43 2018 +0400;fix api name -romanov73;Mon Feb 12 00:58:15 2018 +0400;add balance button -romanov73;Sun Feb 11 01:36:15 2018 +0400;add tools balance prototype -romanov73;Sat Feb 10 23:09:33 2018 +0400;move enum -romanov73;Sat Feb 10 23:02:36 2018 +0400;refactor -romanov73;Sat Feb 10 22:54:28 2018 +0400;add quarter -romanov73;Sat Feb 10 22:42:14 2018 +0400;refactor -romanov73;Sat Feb 10 20:52:46 2018 +0400;Merge branch 'develop' into 33-balance-area -romanov73;Sat Feb 10 20:52:32 2018 +0400;Merge branch 'develop' into 33-balance-area -Romanov Anton;Sat Feb 10 16:14:26 2018 +0000;Merge branch '31-map-2-dto' into 'develop' -romanov73;Sat Feb 10 19:35:17 2018 +0400;fixes after Almaz consultation -romanov73;Sat Feb 10 14:25:00 2018 +0400;fix npe -romanov73;Sat Feb 10 13:50:21 2018 +0400;add filter by work type -romanov73;Sat Feb 10 13:08:56 2018 +0400;rename field -romanov73;Sat Feb 10 13:08:38 2018 +0400;filter by all children -Aleksey Filippov;Sat Feb 10 11:26:17 2018 +0400;some fixes -Aleksey Filippov;Sat Feb 10 11:26:06 2018 +0400;add dto for total balance -Aleksey Filippov;Sat Feb 10 11:11:58 2018 +0400;add dto for employee load by unit -Aleksey Filippov;Sat Feb 10 10:30:11 2018 +0400;getEmployeesByUnit method refactoring -romanov73;Sat Feb 10 00:22:37 2018 +0400;add other type of balance area -romanov73;Fri Feb 9 22:03:39 2018 +0400;add tools balance -romanov73;Fri Feb 9 19:50:21 2018 +0400;divide balance page -Aleksey Filippov;Fri Feb 9 16:37:18 2018 +0400;adapt backing and view to areas and employee experience dtos -Aleksey Filippov;Fri Feb 9 16:36:18 2018 +0400;add dto for employee experience -Aleksey Filippov;Fri Feb 9 16:35:51 2018 +0400;add dto for areas -Aleksey Filippov;Fri Feb 9 14:57:01 2018 +0400;some ui fixes -Aleksey Filippov;Fri Feb 9 14:55:36 2018 +0400;move db methods from getters to init -romanov73;Thu Feb 8 01:20:12 2018 +0400;add areas panel -romanov73;Thu Feb 8 01:19:13 2018 +0400;add areas panel -romanov73;Thu Feb 8 01:02:39 2018 +0400;add global preloader -romanov73;Thu Feb 8 00:57:46 2018 +0400;select default unit -romanov73;Thu Feb 8 00:57:23 2018 +0400;add preloader -romanov73;Wed Feb 7 22:46:44 2018 +0400;change id -Romanov Anton;Wed Feb 7 13:53:35 2018 +0000;Merge branch '23-' into 'develop' -Romanov Anton;Wed Feb 7 13:49:27 2018 +0000;Merge branch 'deploy-fixes' into 'develop' -funny73;Wed Feb 7 17:34:41 2018 +0400;UDP modify AirplaneKitCounter to double -Aleksey Filippov;Wed Feb 7 17:33:23 2018 +0400;some wildfly deploy fixes -funny73;Wed Feb 7 17:19:22 2018 +0400;Modify AirplaneKitCounter to double -> Workload.java -funny73;Wed Feb 7 17:00:10 2018 +0400;Add AirplaneKitCounter to balance view -> BalanceEmployeeService.java Modify Worckload total Value (Value * AirplaneKitCounter) -> BalanceService.java -funny73;Wed Feb 7 14:13:35 2018 +0400;Add AirplaneKitCounter to view -funny73;Wed Feb 7 14:13:15 2018 +0400;Add AirplaneKitCounter to model Workload -funny73;Wed Feb 7 14:12:15 2018 +0400;Changelog for airplainetKitCounter -Romanov Anton;Wed Feb 7 06:54:55 2018 +0000;Merge branch '22-' into 'develop' -romanov73;Wed Feb 7 14:47:34 2018 +0400;add unit types -Romanov Anton;Tue Feb 6 22:43:40 2018 +0000;Merge branch '25-' into 'develop' -romanov73;Wed Feb 7 02:41:34 2018 +0400;filter balance by unit -romanov73;Wed Feb 7 02:06:46 2018 +0400;filter balance by unit -romanov73;Wed Feb 7 02:05:10 2018 +0400;filter balance by unit -romanov73;Wed Feb 7 00:41:01 2018 +0400;add method get all unit children -romanov73;Tue Feb 6 23:26:18 2018 +0400;add filter by unit in balance results -romanov73;Tue Feb 6 21:26:45 2018 +0400;refactor work with tree of menu items -romanov73;Tue Feb 6 21:08:01 2018 +0400;refactor work with tree -romanov73;Tue Feb 6 21:07:22 2018 +0400;fix update after remove enum key -romanov73;Tue Feb 6 20:03:31 2018 +0400;rename method -Gleb;Tue Feb 6 15:07:04 2018 +0000;Merge branch '17-' into 'develop' -romanov73;Tue Feb 6 21:15:12 2018 +0400;fix inf. -funny73;Tue Feb 6 19:02:36 2018 +0400;Add changelog for units with unit_type == 'Корпус', unit_type='Цех' -funny73;Tue Feb 6 18:19:50 2018 +0400;Remove "Korpus" from "Tip podrazdeleniya" -Romanov Anton;Tue Feb 6 11:31:43 2018 +0000;Merge branch '24-' into 'develop' -romanov73;Tue Feb 6 19:01:21 2018 +0400;add user -Romanov Anton;Thu Feb 1 19:45:21 2018 +0000;Merge branch 'wildfly-deploy' into 'develop' -Aleksey Filippov;Thu Feb 1 23:24:34 2018 +0400;add wildfly-maven-plugin, remove maven-glassfish-plugin -romanov73;Thu Feb 1 19:51:24 2018 +0400;add todos -Romanov Anton;Wed Jan 31 15:03:39 2018 +0000;Merge branch 'master' into 'develop' -romanov73;Wed Jan 31 18:53:27 2018 +0400;fix round -romanov73;Wed Jan 31 18:43:33 2018 +0400;fix round -romanov73;Wed Jan 31 18:38:33 2018 +0400;add balance by employees -romanov73;Wed Jan 31 18:30:18 2018 +0400;add balance by employees -Romanov Anton;Wed Jan 31 13:02:52 2018 +0000;Merge branch 'develop' into 'master' -Romanov Anton;Wed Jan 31 12:58:00 2018 +0000;Merge branch '4-' into 'develop' -romanov73;Wed Jan 31 16:47:51 2018 +0400;add balance by employees -romanov73;Wed Jan 31 00:47:39 2018 +0400;add calculation employee loads -romanov73;Wed Jan 31 00:47:25 2018 +0400;add calculation employee loads -romanov73;Wed Jan 31 00:47:08 2018 +0400;add calculation employee loads -romanov73;Wed Jan 31 00:46:53 2018 +0400;add calculation employee loads -romanov73;Wed Jan 31 00:45:59 2018 +0400;add interface for edit additional fields -romanov73;Wed Jan 31 00:45:04 2018 +0400;add comparable for using in tree map -romanov73;Wed Jan 31 00:44:33 2018 +0400;add fields for production program -romanov73;Wed Jan 31 00:43:56 2018 +0400;move interface to base entity -romanov73;Wed Jan 31 00:43:21 2018 +0400;add database fields for production program -romanov73;Wed Jan 31 00:42:55 2018 +0400;add dynamic columns -romanov73;Tue Jan 30 15:11:12 2018 +0400;add work type for workload -romanov73;Tue Jan 30 14:55:56 2018 +0400;add comments -romanov73;Tue Jan 30 03:00:28 2018 +0400;show by production program -romanov73;Tue Jan 30 00:07:31 2018 +0400;add employee available capacity -romanov73;Mon Jan 29 23:42:06 2018 +0400;fix units hierarchy bypass -romanov73;Mon Jan 29 23:28:28 2018 +0400;divide logic -romanov73;Mon Jan 29 22:59:45 2018 +0400;add employee experience table -romanov73;Mon Jan 29 22:15:29 2018 +0400;fix calc areas -romanov73;Mon Jan 29 21:57:23 2018 +0400;fix calc employee experience -romanov73;Mon Jan 29 21:12:52 2018 +0400;calc employee experience by units -romanov73;Mon Jan 29 14:01:36 2018 +0400;add employee experience -Romanov Anton;Mon Jan 29 06:04:01 2018 +0000;Update README.md -Romanov Anton;Sun Jan 28 16:16:56 2018 +0000;Merge branch 'develop' into 'master' -Romanov Anton;Sun Jan 28 16:06:14 2018 +0000;Merge branch '3-' into 'develop' -romanov73;Sun Jan 28 19:53:21 2018 +0400;remove product work types edit -romanov73;Sun Jan 28 19:41:31 2018 +0400;fix months select -romanov73;Sun Jan 28 19:06:10 2018 +0400;fix year select -romanov73;Sun Jan 28 04:28:21 2018 +0400;fix program edit -romanov73;Sun Jan 28 04:27:55 2018 +0400;add product backend -romanov73;Sun Jan 28 04:26:53 2018 +0400;add table and fields -Romanov Anton;Sat Jan 27 08:11:15 2018 +0000;Merge branch '9-' into 'develop' -romanov73;Sat Jan 27 15:28:22 2018 +0400;sort menu items, change logo -Romanov Anton;Sat Jan 27 05:55:52 2018 +0000;Update README.md -romanov73;Sat Jan 20 00:12:44 2018 +0400;fix versions select -Romanov Anton;Fri Jan 19 04:27:48 2018 +0000;Merge branch 'tool-square-catalog' into 'master' -Aleksey Filippov;Fri Jan 19 01:11:50 2018 +0400;add tool square catalog migration -Aleksey Filippov;Thu Jan 18 02:20:48 2018 +0400;add tool square catalog -romanov73;Thu Jan 11 21:22:14 2018 +0400;fix rest path -romanov73;Tue Jan 9 03:44:10 2018 +0400;fixes -romanov73;Tue Jan 9 00:09:27 2018 +0400;fix unit name -romanov73;Tue Jan 9 00:07:47 2018 +0400;fix year -romanov73;Mon Jan 8 19:16:28 2018 +0400;add short view -romanov73;Mon Jan 8 11:55:30 2018 +0400;fix -romanov73;Mon Jan 8 01:24:37 2018 +0400;fill work type by tool name -romanov73;Mon Jan 8 00:23:00 2018 +0400;ui fixes -romanov73;Sun Jan 7 23:54:40 2018 +0400;fix units hierarchy, add unit type, calc areas balance -romanov73;Sat Jan 6 22:51:11 2018 +0400;remove versions -romanov73;Sat Jan 6 22:06:03 2018 +0400;fix edit program -romanov73;Sat Jan 6 21:40:11 2018 +0400;add title image -romanov73;Sat Jan 6 18:04:27 2018 +0400;add production program input -romanov73;Wed Jan 3 21:05:48 2018 +0400;change wizard to tabs -romanov73;Wed Jan 3 01:03:05 2018 +0400;add wizard -romanov73;Sat Dec 30 02:02:42 2017 +0400;fix tools loading -romanov73;Sat Dec 30 01:46:01 2017 +0400;fix tools loading -romanov73;Sat Dec 30 01:32:33 2017 +0400;fix tools loading -romanov73;Sat Dec 30 01:28:24 2017 +0400;fix tools loading -romanov73;Sat Dec 30 00:54:26 2017 +0400;fix employee loading -romanov73;Fri Dec 29 19:04:14 2017 +0400;fix unit select -romanov73;Fri Dec 29 17:19:10 2017 +0400;fix unit select -romanov73;Fri Dec 29 01:40:38 2017 +0400;add cache -romanov73;Fri Dec 29 01:27:18 2017 +0400;add cache -romanov73;Fri Dec 29 01:14:09 2017 +0400;add cache -romanov73;Fri Dec 29 01:12:17 2017 +0400;change color -romanov73;Fri Dec 29 00:50:57 2017 +0400;add ci -romanov73;Fri Dec 29 00:48:10 2017 +0400;add ci -romanov73;Fri Dec 29 00:34:36 2017 +0400;add ci -romanov73;Fri Dec 29 00:31:22 2017 +0400;add ci -romanov73;Fri Dec 29 00:18:51 2017 +0400;add ci -romanov73;Fri Dec 29 00:16:44 2017 +0400;add ci -romanov73;Fri Dec 29 00:13:33 2017 +0400;add ci -romanov73;Fri Dec 29 00:09:51 2017 +0400;fix menus -Romanov Anton;Thu Dec 28 19:47:02 2017 +0000;Merge branch 'balance-example' into 'master' -romanov73;Thu Dec 28 23:44:52 2017 +0400;add other dictionaries -romanov73;Sat Dec 23 10:40:41 2017 +0400;add tool and work types -romanov73;Sat Dec 23 09:12:38 2017 +0400;fix menu item -romanov73;Sat Dec 23 09:12:23 2017 +0400;fix employee load -romanov73;Sat Dec 23 08:51:18 2017 +0400;add employee category -romanov73;Sat Dec 23 08:22:10 2017 +0400;add categories dictionary -romanov73;Fri Dec 22 12:38:08 2017 +0400;add menu item -romanov73;Fri Dec 22 12:31:26 2017 +0400;add employee category -romanov73;Fri Dec 22 09:55:31 2017 +0400;fix calendar -romanov73;Fri Dec 22 09:33:56 2017 +0400;fix date -romanov73;Thu Dec 21 16:38:20 2017 +0400;fix for context path change -romanov73;Thu Dec 21 13:58:02 2017 +0400;fluid panel -romanov73;Wed Dec 20 20:50:17 2017 +0400;fix context path -romanov73;Wed Dec 20 17:12:19 2017 +0400;fix displaying position -romanov73;Wed Dec 20 17:10:14 2017 +0400;load employees from file -romanov73;Wed Dec 20 15:09:54 2017 +0400;fix tool loading -romanov73;Mon Dec 18 18:18:04 2017 +0400;add resource versions -romanov73;Mon Dec 18 17:36:50 2017 +0400;add resource -romanov73;Mon Dec 18 17:07:47 2017 +0400;add swagger -romanov73;Sat Dec 16 09:42:46 2017 +0400;add new version -romanov73;Fri Dec 15 19:50:46 2017 +0400;fix title -romanov73;Fri Dec 15 19:24:13 2017 +0400;fix title -romanov73;Fri Dec 15 11:57:18 2017 +0400;add menu items -romanov73;Fri Dec 15 11:52:01 2017 +0400;add positions dictionary -romanov73;Fri Dec 15 11:29:02 2017 +0400;fix select for employee -romanov73;Fri Dec 15 10:35:12 2017 +0400;add employee backing -romanov73;Fri Dec 15 09:36:33 2017 +0400;fix 500 error page -romanov73;Thu Dec 14 22:26:45 2017 +0400;fix mapping -romanov73;Thu Dec 14 22:49:44 2017 +0400;add employee -romanov73;Thu Dec 14 22:37:30 2017 +0400;add employee -romanov73;Thu Dec 14 14:12:03 2017 +0400;fix crud service -romanov73;Thu Dec 14 12:51:59 2017 +0400;fix table style -romanov73;Thu Dec 14 12:22:48 2017 +0400;remove border for grid -romanov73;Thu Dec 14 12:20:14 2017 +0400;add version_id for units -romanov73;Thu Dec 14 11:49:53 2017 +0400;fix font size -romanov73;Thu Dec 14 11:08:46 2017 +0400;add unit fields -romanov73;Thu Dec 14 10:23:01 2017 +0400;KISS units hierarchy -romanov73;Wed Dec 13 19:04:05 2017 +0400;refresh page -romanov73;Wed Dec 13 17:43:54 2017 +0400;add version -romanov73;Wed Dec 13 01:46:05 2017 +0400;body width -romanov73;Wed Dec 13 01:45:17 2017 +0400;add menu item -romanov73;Tue Dec 12 22:20:07 2017 +0400;fix tree -romanov73;Tue Dec 12 20:02:20 2017 +0400;fix login -romanov73;Tue Dec 12 19:29:03 2017 +0400;add unit tree -romanov73;Tue Dec 12 18:23:38 2017 +0400;add unit dictionary -romanov73;Tue Dec 12 16:18:03 2017 +0400;add filter -romanov73;Tue Dec 12 14:13:31 2017 +0400;fix menu session -romanov73;Tue Dec 12 00:10:47 2017 +0400;remove bootstrap -romanov73;Mon Dec 11 21:53:18 2017 +0400;add unit select -romanov73;Mon Dec 11 19:49:15 2017 +0400;add menu item and role -romanov73;Mon Dec 11 19:37:38 2017 +0400;fix permissions -romanov73;Mon Dec 11 17:08:39 2017 +0400;refactor and add tools dictionary backing -romanov73;Mon Dec 11 17:08:04 2017 +0400;refactor and add tools dictionary backing -romanov73;Mon Dec 11 17:07:27 2017 +0400;refactor and add tools dictionary backing -romanov73;Mon Dec 11 14:12:24 2017 +0400;add tools dictionary page -romanov73;Sat Dec 9 09:54:45 2017 +0400;add global exception hadler -romanov73;Sat Nov 25 13:52:33 2017 +0400;add monitoring -romanov73;Sat Nov 25 13:21:18 2017 +0400;fix xls and xlsx -romanov73;Sat Nov 25 12:39:45 2017 +0400;upload tools -romanov73;Fri Nov 24 22:16:27 2017 +0400;save tools -romanov73;Fri Nov 24 13:06:21 2017 +0400;fix message -romanov73;Fri Nov 24 12:11:43 2017 +0400;add loading from xlsx -romanov73;Fri Nov 17 19:43:35 2017 +0400;add message -romanov73;Fri Nov 17 15:11:22 2017 +0400;fix button -romanov73;Fri Nov 17 10:15:42 2017 +0400;add registration service -romanov73;Thu Nov 16 21:35:04 2017 +0400;add push script -romanov73;Thu Nov 16 20:54:49 2017 +0400;fix named query execution -romanov73;Sun Nov 12 22:19:03 2017 +0400;sort menu items -romanov73;Sat Nov 11 15:09:35 2017 +0400;fix title -romanov73;Sat Nov 11 14:54:25 2017 +0400;fix table -romanov73;Sat Nov 11 14:35:38 2017 +0400;fix style attribute -romanov73;Sat Nov 11 14:08:56 2017 +0400;show user sessions -romanov73;Sat Nov 11 13:51:34 2017 +0400;rename service -romanov73;Fri Nov 10 22:03:25 2017 +0400;fix update tree -romanov73;Fri Nov 10 14:29:25 2017 +0400;edit menu items -romanov73;Fri Nov 10 12:17:24 2017 +0400;set bootstrap theme for primefaces -romanov73;Thu Nov 9 23:40:40 2017 +0400;fix saving entitites -romanov73;Thu Nov 9 23:27:42 2017 +0400;fix saving entitites -romanov73;Thu Nov 9 20:51:19 2017 +0400;fix titles -romanov73;Thu Nov 9 18:00:45 2017 +0400;fix login page title -romanov73;Thu Nov 9 13:36:21 2017 +0400;commit log -romanov73;Thu Nov 9 07:31:37 2017 +0400;reverse sort commits -romanov73;Thu Nov 9 00:27:48 2017 +0400;sort commits -romanov73;Wed Nov 8 23:16:07 2017 +0400;extend commits log -romanov73;Wed Nov 8 21:42:16 2017 +0400;fix styles -romanov73;Wed Nov 8 19:17:08 2017 +0400;add logout -romanov73;Wed Nov 8 19:13:17 2017 +0400;add logout -romanov73;Wed Nov 8 20:18:35 2017 +0400;Merge branch 'master' of gitlab.com:romanov73/balance -romanov73;Wed Nov 8 20:17:55 2017 +0400;add database diagramm -Romanov Anton;Wed Nov 8 04:13:39 2017 +0000;Update README.md -Romanov Anton;Wed Nov 8 04:11:33 2017 +0000;Update README.md -romanov73;Wed Nov 8 07:48:13 2017 +0400;Merge remote-tracking branch 'origin/master' -Romanov Anton;Tue Nov 7 18:05:04 2017 +0000;Update README.md -romanov73;Tue Nov 7 22:01:50 2017 +0400;add example of permissions validation -romanov73;Tue Nov 7 20:56:31 2017 +0400;rename project -romanov73;Wed Oct 11 21:37:49 2017 +0400;reverse sort commits -romanov73;Wed Oct 11 21:32:19 2017 +0400;fix read resource as file -romanov73;Wed Oct 11 20:23:10 2017 +0400;Merge remote-tracking branch 'origin/master' -romanov73;Wed Oct 11 20:22:52 2017 +0400;add commits log -Romanov Anton;Tue Oct 10 20:47:29 2017 +0000;Update README.md -romanov73;Fri Oct 6 01:55:57 2017 +0400;add menu to platform \ No newline at end of file +Anton Romanov;Thu Mar 28 14:59:35 2019 +0400;partially restored commits page +Anton Romanov;Wed Mar 27 13:27:49 2019 +0400;#33 small external link +Anton Romanov;Wed Mar 27 09:07:02 2019 +0000;Update README.md +Anton Romanov;Wed Mar 27 07:58:58 2019 +0000;Merge branch '33-paper-url' into 'dev' +Семенова Мария;Sat Mar 23 12:23:30 2019 +0400;#33 link in new tab +Семенова Мария;Sat Mar 23 12:04:51 2019 +0400;Merge branch 'dev' into 33-paper-url +Anton Romanov;Fri Mar 22 10:36:09 2019 +0000;Merge branch '13-paper-files' into 'dev' +Anton Romanov;Fri Mar 22 13:58:03 2019 +0400;#13 reduce of code +Anton Romanov;Fri Mar 22 13:52:06 2019 +0400;#13 fix condition +Семенова Мария;Fri Mar 22 13:21:32 2019 +0400;#13 streams refactoring +Семенова Мария;Fri Mar 22 09:32:21 2019 +0400;#13 rename 'deleted', move creating fileDto to service +Семенова Мария;Thu Mar 21 18:26:28 2019 +0400;#13 fileDataDto instead of Object[] +Семенова Мария;Tue Mar 19 17:59:19 2019 +0400;#13 some refactoring +Семенова Мария;Tue Mar 19 17:41:02 2019 +0400;Merge branch 'dev' into 13-paper-files +Семенова Мария;Mon Mar 18 23:31:33 2019 +0400;#33 url in paper +Anton Romanov;Mon Mar 18 22:35:01 2019 +0400;merge deploy environments +Anton Romanov;Mon Mar 18 22:25:28 2019 +0400;add environment +Семенова Мария;Mon Mar 18 21:02:26 2019 +0400;#13 download files +Семенова Мария;Mon Mar 18 19:17:28 2019 +0400;#13 add files to db +Семенова Мария;Mon Mar 18 18:39:15 2019 +0400;#13 addNewFile js function +Семенова Мария;Mon Mar 18 16:13:22 2019 +0400;Merge branch 'dev' into 13-paper-files +Семенова Мария;Mon Mar 18 16:02:55 2019 +0400;#13 file list on paper page +Anton Romanov;Mon Mar 18 11:08:15 2019 +0000;Merge branch '50-refactorForGrants' into 'dev' +T-Midnight;Mon Mar 18 14:27:54 2019 +0400;Delete DeadlineDTO and update usages +Семенова Мария;Mon Mar 18 13:00:34 2019 +0400;#13 add fileDataDto +Семенова Мария;Mon Mar 18 11:07:30 2019 +0400;#13 change model, schema +T-Midnight;Fri Mar 15 12:24:02 2019 +0400;Add new status for grant +T-Midnight;Fri Mar 15 12:19:25 2019 +0400;Rename title +T-Midnight;Fri Mar 15 12:19:01 2019 +0400;Create Navigation class to avoid "magic strings" and code duplication +Anton Romanov;Wed Mar 13 07:16:32 2019 +0000;Merge branch '72-link-to-timetable' into 'dev' +Anton Romanov;Tue Mar 12 14:44:11 2019 +0400;add patronymic +Anton Romanov;Tue Mar 12 13:40:48 2019 +0400;display user in filter +Anton Romanov;Tue Mar 12 12:51:59 2019 +0300;add service methods +Anton Romanov;Tue Mar 12 12:35:09 2019 +0300;add timetable link +Anton Romanov;Mon Mar 11 10:49:07 2019 +0000;Merge branch '54-view-conference' into 'dev' +Nightblade73;Mon Mar 11 14:43:32 2019 +0400;#54 deleted edit btn +Nightblade73;Mon Mar 11 12:58:40 2019 +0400;#54 add back link, css fixes +Nightblade73;Mon Mar 11 11:36:00 2019 +0400;#54 add custom paper-list +Nightblade73;Sun Mar 10 22:15:09 2019 +0400;#54 add custom deadline-list, add edit-button, add edit and delete icons +Nightblade73;Thu Mar 7 22:50:37 2019 +0400;#54 add member list +Nightblade73;Wed Mar 6 20:51:46 2019 +0400;#54 part of make-up +Nightblade73;Wed Mar 6 16:48:51 2019 +0400;#54 add transitions +Anton Romanov;Wed Mar 6 16:40:33 2019 +0400;fix login +Nightblade73;Wed Mar 6 16:27:25 2019 +0400;#50 creating html page, changing href +Anton Romanov;Wed Mar 6 12:25:34 2019 +0000;Merge branch '29-page-header' into 'dev' +Anton Romanov;Wed Mar 6 16:19:43 2019 +0400;fix css +Anton Romanov;Wed Mar 6 14:36:46 2019 +0300;fix props +Anton Romanov;Wed Mar 6 14:35:09 2019 +0300;fix props +user;Wed Mar 6 14:25:02 2019 +0300;header fix +Anton Romanov;Mon Mar 4 10:28:46 2019 +0400;fix code +Anton Romanov;Mon Mar 4 10:24:30 2019 +0400;fix code +Anton Romanov;Fri Mar 1 11:27:57 2019 +0400;fix branch +Anton Romanov;Fri Mar 1 11:22:25 2019 +0400;add links to papers +Anton Romanov;Fri Mar 1 11:21:25 2019 +0400;add links to papers +Anton Romanov;Sun Feb 3 14:54:02 2019 +0000;Update README.md +Anton Romanov;Thu Jan 17 01:01:26 2019 +0400;filter dashboard papers +Anton Romanov;Thu Jan 17 00:57:34 2019 +0400;fix failed conditions +Anton Romanov;Tue Jan 8 19:55:27 2019 +0000;Update README.md +Anton Romanov;Tue Jan 8 19:36:36 2019 +0000;Update README.md +Anton Romanov;Sat Jan 5 08:01:07 2019 +0400;fix notifications +Anton Romanov;Fri Jan 4 17:41:48 2019 +0400;fix notifications +Anton Romanov;Sun Dec 30 19:23:11 2018 +0400;some layout fix +Anton Romanov;Sun Dec 30 19:22:51 2018 +0400;sort deadlines +Anton Romanov;Sat Dec 29 09:58:37 2018 +0400;fix enum field name +Anton Romanov;Fri Dec 28 10:04:42 2018 +0000;Merge branch '35-' into 'master' +Anton Romanov;Fri Dec 28 14:00:09 2018 +0400;some refactor +Anton Romanov;Fri Dec 28 13:57:20 2018 +0400;some refactor +T-Midnight;Tue Dec 25 12:50:14 2018 +0400;Create model folder for grant +T-Midnight;Tue Dec 25 02:44:50 2018 +0400;Hide button "Add Project" when project already exists (not perfect) +T-Midnight;Tue Dec 25 00:14:38 2018 +0400;Made button "delete grant" visible +T-Midnight;Mon Dec 24 23:39:19 2018 +0400;Rename table grant to grants +T-Midnight;Mon Dec 24 15:20:57 2018 +0400;Update classes +T-Midnight;Mon Dec 24 15:18:52 2018 +0400;Add thymeleaf template +T-Midnight;Mon Dec 24 13:05:37 2018 +0400;Create service&repository for Project +T-Midnight;Mon Dec 24 11:07:02 2018 +0400;Create js for grants +T-Midnight;Mon Dec 24 11:03:03 2018 +0400;Create html fragments +T-Midnight;Sun Dec 23 02:22:41 2018 +0400;Create Controller&Service +T-Midnight;Sun Dec 23 02:22:31 2018 +0400;Update ProjectDto +T-Midnight;Sun Dec 23 02:22:24 2018 +0400;Add constructor +T-Midnight;Sun Dec 23 02:22:06 2018 +0400;Add function getNextDeadline() +T-Midnight;Sat Dec 22 18:03:18 2018 +0400;Create GrantRepository +T-Midnight;Sat Dec 22 03:31:43 2018 +0400;Create setters for GrantDto +Anton Romanov;Fri Dec 21 00:07:26 2018 +0400;fix display paper title +Anton Romanov;Thu Dec 20 23:30:25 2018 +0400;fix paper status template +Anton Romanov;Wed Dec 19 01:29:54 2018 +0400;try to fix template resolvers, step 4 +Anton Romanov;Wed Dec 19 01:00:08 2018 +0400;try to fix template resolvers, step 3 +Anton Romanov;Wed Dec 19 00:44:12 2018 +0400;try to fix template resolvers, step 2 +Anton Romanov;Wed Dec 19 00:22:36 2018 +0400;try to fix template resolvers +Anton Romanov;Wed Dec 19 00:11:39 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Wed Dec 19 00:09:07 2018 +0400;try to fix gradlew +Anton Romanov;Tue Dec 18 23:02:48 2018 +0400;sort filtered papers +Anton Romanov;Tue Dec 18 18:45:43 2018 +0000;Merge branch '47-statuses' into 'master' +Anton Romanov;Tue Dec 18 22:42:34 2018 +0400;add statuses +Anton Romanov;Tue Dec 18 18:18:25 2018 +0000;Merge branch '46-mvc' into 'master' +Anton Romanov;Tue Dec 18 22:15:21 2018 +0400;fix filer +Anton Romanov;Tue Dec 18 19:40:23 2018 +0400;fix scripts +Anton Romanov;Tue Dec 18 19:23:15 2018 +0400;show authors +Anton Romanov;Tue Dec 18 18:47:15 2018 +0400;confirm delete paper +Anton Romanov;Tue Dec 18 18:05:30 2018 +0400;add papers navigation +Anton Romanov;Mon Dec 17 17:56:48 2018 +0400;fix submit form +Anton Romanov;Mon Dec 17 17:29:06 2018 +0400;fix email notification +Anton Romanov;Mon Dec 17 17:28:52 2018 +0400;fix route +Anton Romanov;Mon Dec 17 13:46:08 2018 +0400;edit deadlines +Anton Romanov;Fri Dec 14 16:00:46 2018 +0400;Merge branch 'master' into 46-mvc +Anton Romanov;Fri Dec 14 16:00:33 2018 +0400;Merge branch 'master' into 46-mvc +Anton Romanov;Tue Dec 11 11:14:21 2018 +0000;Merge branch '36-' into 'master' +Anton Romanov;Tue Dec 11 15:08:35 2018 +0400;move classes, add deadline to entities, fix db changelogs +T-Midnight;Sat Dec 8 23:53:38 2018 +0400;Create model for grant, deadline and project +Anton Romanov;Wed Dec 5 18:08:47 2018 +0400;save authors +Anton Romanov;Wed Dec 5 17:36:53 2018 +0400;fix npe +Anton Romanov;Wed Dec 5 17:06:56 2018 +0400;format dates +Anton Romanov;Wed Dec 5 16:51:26 2018 +0400;fix create paper +Anton Romanov;Wed Dec 5 06:00:33 2018 +0000;add rest controller +Anton Romanov;Tue Dec 4 14:49:23 2018 +0400;fix js +Anton Romanov;Tue Dec 4 14:48:39 2018 +0400;show status +Anton Romanov;Tue Dec 4 14:13:01 2018 +0400;add validation +Anton Romanov;Tue Dec 4 11:35:51 2018 +0400;pass values for paper +Anton Romanov;Mon Nov 26 23:07:14 2018 +0400;load paper +Anton Romanov;Fri Nov 23 16:40:15 2018 +0000;Merge branch '14-filter-frontend' into 'master' +Anton Romanov;Fri Nov 23 20:37:24 2018 +0400;fix failed commit +Anton Romanov;Fri Nov 23 16:24:26 2018 +0000;Merge branch '10-savePaper' into 'master' +Anton Romanov;Fri Nov 23 16:45:40 2018 +0400;show paper list in mvc +Alyona;Fri Nov 23 14:17:16 2018 +0400;filter +Alyona;Fri Nov 23 14:12:37 2018 +0400;Merge branch 'master' into 14-filter-frontend +Alyona;Fri Nov 23 14:10:49 2018 +0400;Merge remote-tracking branch 'origin/master' +Alyona;Fri Nov 23 14:10:36 2018 +0400;Merge branch 'master' of C:\Users\катя\IdeaProjects\ng-tracker with conflicts. +Elena;Fri Nov 23 14:05:23 2018 +0400;задача 10(new) +Elena;Fri Nov 23 13:53:20 2018 +0400;задача 10 +Elena;Fri Nov 23 12:39:36 2018 +0400;Merge branch 'master' into 10-savePaper +Anton Romanov;Thu Nov 22 21:48:36 2018 +0400;fix colors +Anton Romanov;Thu Nov 22 21:31:41 2018 +0400;fix colors +Anton Romanov;Thu Nov 22 21:06:58 2018 +0400;add paper status +Anton Romanov;Thu Nov 22 11:20:08 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Thu Nov 22 11:19:50 2018 +0400;add mertica +Anton Romanov;Wed Nov 21 15:47:26 2018 +0400;remove empty page +Anton Romanov;Wed Nov 21 15:47:14 2018 +0400;add toolbar +Anton Romanov;Wed Nov 21 15:42:20 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Wed Nov 21 11:42:47 2018 +0000;Merge branch '31-' into 'master' +Anton Romanov;Wed Nov 21 15:40:20 2018 +0400;close failed papers +T-Midnight;Wed Nov 21 15:28:41 2018 +0400;Create grant page +Anton Romanov;Wed Nov 21 08:51:11 2018 +0000;Merge branch '30-main-grants-page' into 'master' +Anton Romanov;Wed Nov 21 12:46:42 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Wed Nov 21 12:46:27 2018 +0400;notify if paper deadline in future +T-Midnight;Mon Nov 19 12:16:39 2018 +0400;Update dashboard for grants +Anton Romanov;Mon Nov 19 08:21:22 2018 +0400;fix for remove event +Anton Romanov;Mon Nov 19 07:46:02 2018 +0400;fix event create conditions +Anton Romanov;Sun Nov 18 14:29:41 2018 +0400;fix delete button +Anton Romanov;Sat Nov 17 12:31:22 2018 +0400;fix delete button +Anton Romanov;Sat Nov 17 11:56:52 2018 +0400;show events +Anton Romanov;Wed Nov 14 17:14:56 2018 +0400;fix build script for netbeans +Anton Romanov;Wed Nov 14 17:04:40 2018 +0400;show toolbar buttons +Anton Romanov;Wed Nov 14 17:04:29 2018 +0400;show toolbar buttons +Anton Romanov;Wed Nov 14 17:04:13 2018 +0400;show paper status +Anton Romanov;Wed Nov 14 17:03:22 2018 +0400;fix code +Anton Romanov;Wed Nov 14 15:18:22 2018 +0400;fix code +Anton Romanov;Wed Nov 14 15:15:23 2018 +0400;read dashboard +Alyona;Wed Nov 14 08:55:46 2018 +0400;filter +Anton Romanov;Tue Nov 13 11:46:25 2018 +0000;Merge branch '14-DB-filter' into 'master' +Anton Romanov;Tue Nov 13 15:41:18 2018 +0400;filter papers +Anton Romanov;Sun Nov 11 14:28:51 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Sun Nov 11 12:43:27 2018 +0400;move class +Anton Romanov;Sat Nov 10 21:44:36 2018 +0000;Merge branch '20-' into 'master' +Anton Romanov;Sun Nov 11 01:31:27 2018 +0400;fix scheduler +Anton Romanov;Sun Nov 11 01:29:06 2018 +0400;refactor and db changes +Anton Romanov;Sat Nov 10 23:15:35 2018 +0400;delete paper +T-Midnight;Sat Nov 10 21:55:09 2018 +0400;Create dashboard for grants +Anton Romanov;Sat Nov 10 21:43:52 2018 +0400;add route +Alyona;Sat Nov 10 20:28:17 2018 +0400;fix +Alyona;Fri Nov 9 15:43:42 2018 +0400;fix +Elena;Fri Nov 9 15:43:25 2018 +0400;Задача №10 +Anton Romanov;Fri Nov 9 15:37:58 2018 +0400;remove styles from email template +Alyona;Fri Nov 9 15:29:48 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Fri Nov 9 15:21:03 2018 +0400;move styles to body +Anton Romanov;Fri Nov 9 11:15:00 2018 +0000;Merge branch '21-Event-status' into 'master' +Anton Romanov;Fri Nov 9 15:08:10 2018 +0400;Merge branch 'master' into 21-Event-status +Anton Romanov;Fri Nov 9 15:05:39 2018 +0400;fix styles +Anton Romanov;Fri Nov 9 14:53:24 2018 +0400;add styles in email templates +Alyona;Fri Nov 9 14:51:19 2018 +0400;added period event +Alyona;Fri Nov 9 14:48:21 2018 +0400;added period event +Elena;Fri Nov 9 13:43:08 2018 +0400;Merge branch 'master' into 10-savePaper +Elena;Fri Nov 9 13:42:28 2018 +0400;Задача №10 +Alyona;Fri Nov 9 13:30:31 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Fri Nov 9 10:04:50 2018 +0400;add notification templates +Anton Romanov;Fri Nov 9 09:16:24 2018 +0400;move to notification service +Anton Romanov;Fri Nov 9 08:39:00 2018 +0400;fix scheduler code to use service +Anton Romanov;Thu Nov 8 21:58:10 2018 +0400;add toolbar +Anton Romanov;Thu Nov 8 20:34:09 2018 +0400;fix paths +Anton Romanov;Thu Nov 8 20:08:26 2018 +0400;add config parameter +Anton Romanov;Thu Nov 8 19:39:22 2018 +0400;Merge remote-tracking branch 'origin/master' +Anton Romanov;Thu Nov 8 19:36:50 2018 +0400;add paper create strategy +Anton Romanov;Tue Nov 6 10:39:25 2018 +0000;Update README.md +Anton Romanov;Tue Nov 6 14:10:00 2018 +0400;fix ci +Anton Romanov;Thu Nov 1 12:53:19 2018 +0400;fix imports +Alyona;Wed Oct 31 20:06:27 2018 +0400;changelog +Alyona;Wed Oct 31 19:35:23 2018 +0400;Merge branch 'master' into 21-Event-status +Alyona;Wed Oct 31 19:33:21 2018 +0400;Merge branch 'master' of C:\Users\катя\IdeaProjects\ng-tracker with conflicts. +Alyona;Tue Oct 30 23:59:42 2018 +0400;added event status +Anton Romanov;Tue Oct 30 19:32:00 2018 +0000;Merge branch '4-show-time-line' into 'master' +Anton Romanov;Tue Oct 30 23:29:18 2018 +0400;Merge branch 'master' into 4-show-time-line +Anton Romanov;Tue Oct 30 23:26:55 2018 +0400;fix db +Anton Romanov;Tue Oct 30 23:07:01 2018 +0400;Revert "remove liquibase" +Anton Romanov;Tue Oct 30 23:04:49 2018 +0400;Merge remote-tracking branch 'origin/4-show-time-line' into 4-show-time-line +Anton Romanov;Tue Oct 30 23:04:21 2018 +0400;Revert "remove liquibase" +Anton Romanov;Sat Oct 27 21:00:43 2018 +0000;Merge branch '11-Message-about-deadlines' into 'master' +Anton Romanov;Sat Oct 27 21:00:01 2018 +0000;Merge branch '12-' into 'master' +Alyona;Sun Oct 28 00:33:00 2018 +0400;fix +Alyona;Sun Oct 28 00:26:09 2018 +0400;fix +Alyona;Sun Oct 28 00:17:16 2018 +0400;fix +Alyona;Sun Oct 28 00:15:42 2018 +0400;fix +Alyona;Sat Oct 27 23:50:12 2018 +0400;fix +Alyona;Sat Oct 27 23:46:49 2018 +0400;fix +Anton Romanov;Sat Oct 27 23:25:27 2018 +0400;- make scheduler as a service - reformat code - fix cyrillic letter +Anton Romanov;Sat Oct 27 23:16:14 2018 +0400;add database column +Alyona;Sat Oct 27 23:11:07 2018 +0400;class for send messages about update paper +Alyona;Sat Oct 27 22:32:51 2018 +0400;add deadlineSсheduler +Alyona;Sat Oct 27 22:24:10 2018 +0400;add deadlineDate to models +Anton Romanov;Thu Oct 25 10:27:57 2018 +0400;some fix +Anton Romanov;Thu Oct 25 04:59:51 2018 +0000;Merge branch '8-' into 'master' +Alyona;Thu Oct 25 08:53:48 2018 +0400;finish deadline +Alyona;Thu Oct 25 08:53:29 2018 +0400;finish deadline +Alyona;Thu Oct 25 08:44:25 2018 +0400;Merge branch 'master' into 8-Deadline +Alyona;Thu Oct 25 08:41:37 2018 +0400;partially add deadline +Anton Romanov;Thu Oct 18 07:25:58 2018 +0000;Merge branch '7-dates-Matveeva' into 'master' +Anton Romanov;Thu Oct 18 11:21:26 2018 +0400;use html5 datetime pickers +Elena;Thu Oct 18 10:38:04 2018 +0400;Задача №7 +Anton Romanov;Thu Oct 18 04:49:10 2018 +0000;Merge branch '6-authors-list-Matveeva' into 'master' +Anton Romanov;Thu Oct 11 19:49:16 2018 +0400;fix buttons size +Anton Romanov;Thu Oct 11 15:39:57 2018 +0400;fix styles +Anton Romanov;Thu Oct 11 10:03:44 2018 +0400;load paper statuses +Anton Romanov;Thu Oct 11 09:05:41 2018 +0400;fix progress background +Elena;Wed Oct 10 23:09:45 2018 +0400;Задача №6 +Anton Romanov;Wed Oct 10 13:18:24 2018 +0000;Merge branch '5-' into 'master' +Anton Romanov;Wed Oct 10 17:05:54 2018 +0400;fix paper view +Elena;Wed Oct 10 15:30:47 2018 +0400;Задача №5 new +Elena;Wed Oct 10 10:09:07 2018 +0400;Merge branch 'master' into 5-Matveeva-Page +Elena;Thu Oct 4 10:39:27 2018 +0400;Задача №5 +Anton Romanov;Tue Oct 2 07:46:40 2018 +0000;Merge branch '27-file-upload' into 'master' +Anton Romanov;Tue Oct 2 11:11:13 2018 +0400;Merge branch 'master' into 27-file-upload +Anton Romanov;Tue Oct 2 10:58:41 2018 +0400;add messages +Anton Romanov;Mon Oct 1 13:54:11 2018 +0400;add example for file uploading +Anton Romanov;Sat Sep 29 09:22:48 2018 +0400;minimize scripts +Anton Romanov;Thu Sep 27 21:32:16 2018 +0400;fix error pages +Anton Romanov;Thu Sep 27 16:01:02 2018 +0000;Merge branch 'refactor-ui' into 'master' +Anton Romanov;Thu Sep 27 12:11:25 2018 +0400;move pages +Anton Romanov;Thu Sep 27 10:35:22 2018 +0400;some refactor +Anton Romanov;Thu Sep 27 06:08:53 2018 +0000;Merge branch '3-ui' into 'master' +Anton Romanov;Thu Sep 27 10:03:00 2018 +0400;Merge branch 'master' into 3-ui +Anton Romanov;Thu Sep 27 10:02:49 2018 +0400;Merge branch 'master' into 3-ui +Alyona;Wed Sep 26 16:44:36 2018 +0400;Merge branch 'master' into 5-Page-of-paper +Alyona;Wed Sep 26 16:41:33 2018 +0400;Merge branch 'master' into 23-dashboard +Anton Romanov;Wed Sep 26 12:22:38 2018 +0000;Merge branch '23-dashboard' into 'master' +Alyona;Wed Sep 26 16:11:43 2018 +0400;Merge branch 'master' into 23-dashboard +Alyona;Wed Sep 26 16:11:19 2018 +0400;Merge branch 'master' into 23-dashboard +Alyona;Wed Sep 26 16:04:31 2018 +0400;add paper page +Anton Romanov;Wed Sep 26 11:55:20 2018 +0000;Merge branch '24-paper-page' into 'master' +Alyona;Tue Sep 25 17:13:01 2018 +0400;Alyona-Test +Elena;Tue Sep 25 16:45:01 2018 +0400;Тестовое задание +Anton Romanov;Sat Sep 22 06:56:33 2018 +0000;Update README.md +Anton Romanov;Sat Sep 8 10:19:21 2018 +0400;change ports +Anton Romanov;Sat Sep 8 10:07:21 2018 +0400;Merge remote-tracking branch 'origin/4-show-time-line' into 4-show-time-line +Anton Romanov;Sat Sep 8 09:54:14 2018 +0400;Merge branch 'master' into 4-show-time-line +Anton Romanov;Sat Sep 8 09:53:34 2018 +0400;path to timeline +Anton Romanov;Sat Sep 8 09:50:13 2018 +0400;fix papers font +Anton Romanov;Thu Sep 6 19:14:04 2018 +0000;Update README.md +Anton Romanov;Thu Sep 6 23:01:39 2018 +0400;add variable +Anton Romanov;Thu Sep 6 22:50:34 2018 +0400;deploy on vps +Anton Romanov;Wed Sep 5 21:58:04 2018 +0400;add timeline page +Anton Romanov;Wed Sep 5 14:50:49 2018 +0400;sort papers +Anton Romanov;Wed Sep 5 13:45:20 2018 +0400;fix paper colors +Anton Romanov;Wed Sep 5 13:31:51 2018 +0400;add method for create paper +Anton Romanov;Wed Sep 5 11:27:22 2018 +0400;get paper list +Anton Romanov;Sun Jun 10 13:43:40 2018 +0400;add timeline page +Anton Romanov;Sun Jun 10 01:53:32 2018 +0400;fix time +Anton Romanov;Sun Jun 10 01:49:38 2018 +0400;send notification +Anton Romanov;Sun Jun 10 01:12:28 2018 +0400;add event controller +Anton Romanov;Sat Jun 9 22:58:32 2018 +0400;remove liquibase +Anton Romanov;Sat Jun 9 22:41:00 2018 +0400;fix ports +Aleksey Filippov;Sun May 20 08:05:21 2018 +0200;delete orphaned files, migrate to webjars, some fixes and refactoring +Anton Romanov;Sat May 5 14:49:34 2018 +0400;add paper authors +Anton Romanov;Sat May 5 11:17:13 2018 +0400;add paper status +Anton Romanov;Sat May 5 11:14:37 2018 +0400;fix papers delete +Anton Romanov;Sat May 5 10:57:02 2018 +0400;fix papers crud +Anton Romanov;Sat May 5 00:39:18 2018 +0400;fix paper controller +Anton Romanov;Sat May 5 00:24:48 2018 +0400;add file uploading +Anton Romanov;Fri May 4 18:09:29 2018 +0400;add big logo +Anton Romanov;Fri May 4 18:04:09 2018 +0400;add paper controller +Anton Romanov;Fri May 4 17:54:46 2018 +0400;add ci +Anton Romanov;Fri May 4 17:23:22 2018 +0400;gitignore +Anton Romanov;Fri May 4 17:08:20 2018 +0400;add java code +Anton Romanov;Mon Apr 30 00:47:50 2018 +0400;add works +Anton Romanov;Sun Apr 29 20:48:05 2018 +0400;add paper page +Anton Romanov;Sun Apr 29 20:46:54 2018 +0400;add paper page +Anton Romanov;Sun Apr 29 20:44:47 2018 +0400;add paper page +Anton Romanov;Sun Apr 29 18:24:42 2018 +0400;add papers page +Anton Romanov;Sun Apr 29 17:09:58 2018 +0400;fix menu and sources +Anton Romanov;Sun Apr 29 00:49:37 2018 +0400;fix title page +Anton Romanov;Sat Apr 28 23:30:38 2018 +0400;fix title page +Anton Romanov;Sat Apr 28 22:50:26 2018 +0400;copy from landing diff --git a/src/main/resources/db/changelog-20190318_000000-schema.xml b/src/main/resources/db/changelog-20190318_000000-schema.xml new file mode 100644 index 0000000..a4f7ec1 --- /dev/null +++ b/src/main/resources/db/changelog-20190318_000000-schema.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/src/main/resources/db/changelog-20190318_000001-schema.xml b/src/main/resources/db/changelog-20190318_000001-schema.xml new file mode 100644 index 0000000..98ec657 --- /dev/null +++ b/src/main/resources/db/changelog-20190318_000001-schema.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/src/main/resources/db/changelog-20190327_000000-schema.xml b/src/main/resources/db/changelog-20190327_000000-schema.xml new file mode 100644 index 0000000..4913072 --- /dev/null +++ b/src/main/resources/db/changelog-20190327_000000-schema.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/src/main/resources/db/changelog-20190331_000000-schema.xml b/src/main/resources/db/changelog-20190331_000000-schema.xml new file mode 100644 index 0000000..76a7daa --- /dev/null +++ b/src/main/resources/db/changelog-20190331_000000-schema.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-20190331_000010-schema.xml b/src/main/resources/db/changelog-20190331_000010-schema.xml new file mode 100644 index 0000000..04bda75 --- /dev/null +++ b/src/main/resources/db/changelog-20190331_000010-schema.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index b8654ae..800b2f1 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -18,5 +18,10 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/public/css/conference.css b/src/main/resources/public/css/conference.css index 06d8041..ec88796 100644 --- a/src/main/resources/public/css/conference.css +++ b/src/main/resources/public/css/conference.css @@ -1,94 +1,122 @@ -.col-lg-12 a{ - position: absolute; - font-size: smaller; +body { + min-width: 400px; } -.col-lg-12 a img{ - width: 36px; - height: 33px; -} -.form-group textarea{ + + +.form-group textarea { min-height: 206px; max-height: 463px; } - -.deadline-list{ +.deadline-list { height: 200px; padding: 0px; overflow-y: scroll; } -.deadline{ +.deadline { margin: 0; + height: 40px; } -.deadline-text{ +.deadline-text { flex: 1; } -.member-list{ +.member-list { height: 200px; padding: 0px; overflow-y: scroll; } -.member{ +.member { margin: 0; } -.paper-list{ +.paper-list { height: 200px; padding: 0px; overflow-y: scroll; } -.paper{ +.paper { margin: 0; } -.paper-name{ +.paper-name { flex: 1; } -.paper-name span{ +.paper-name span { margin: 6px 15px; display: inline-block; } -.icon{ +.icon { width: 38px; height: 38px; padding: 2px; cursor: pointer; } -.icon-delete{ +.icon-delete { background-color: #f44; } -.icon-paper{ - height: 26px; - width: 26px; - float: right; - margin: 5px; +.icon-delete:hover { + background-color: #ff2929; + transition: background-color .15s ease-in-out; } -.grey-border{ +.icon-paper { + height: 26px; + width: 26px; + float: right; + margin: 5px; +} + +.grey-border { color: #495057; background-clip: padding-box; border: 1px solid #ced4da; border-radius: .25rem; - transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; -} - -#add-paper{ - margin-left: 10px; + transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out; } -#cancel-button{ +#cancel-button { position: relative; font-size: 1rem; } +.paper-control button { + margin: 0 0 10px 10px; + float: right; +} + +@media (max-width: 1199px) { + .paper-control { + display: block!important; + } +} + +@media (max-width: 991px) { + .dates-panel { + display: block!important; + } + + .date { + margin-bottom: 10px; + } +} + +@media (max-width: 768px) { + .dashboard-elements { + display: block!important; + } + + .dashboard-right { + margin-bottom: 10px; + } +} diff --git a/src/main/resources/public/css/odin.css b/src/main/resources/public/css/odin.css new file mode 100644 index 0000000..2bfeb75 --- /dev/null +++ b/src/main/resources/public/css/odin.css @@ -0,0 +1,226 @@ +.odin-unselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.odin-kill-padding { + padding: 0; +} + +.odin-input-group { + padding-left: 15px !important; + padding-right: 15px !important; +} + +.odin-closable .fa { + font-size: 1.5em; + margin-top: -1px; +} + +.odin-closable .fa:hover:before { + content: "\f057"; +} + +/* + Odin Toolbar +*/ +.odin-toolbar { + padding-left: 1px; + padding-bottom: 4px; +} + +.odin-toolbar .odin-btn { + float: none !important; +} + +.odin-btn { + min-width: 112px; + margin-right: 3px; +} + +@media (min-width: 768px) { + .odin-btn { + min-width: 150px; + } +} + +/* + Odin Paginator +*/ +.odin-paginator { + margin: 0; + margin-top: 5px; + text-align: center; +} + +.odin-paginator-content { + display: inline-block; +} + +.odin-paginator-content a { + cursor: pointer; + color: black; + float: left; + padding: 6px 16px; + text-decoration: none; + transition: background-color .3s; + border-radius: 4px; +} + +.odin-paginator-content i { + color: black; + float: left; + padding: 6px 16px; +} + +.odin-paginator-content a.active { + background-color: #4CAF50; + color: white; +} + +.odin-paginator-content a:hover:not(.active) { + background-color: #ddd; +} + +/* + Odin Formatters +*/ +.odin-negative { + color: red; + font-weight: bold; +} + +/* + Odin Table +*/ +.odin-table { + min-height: 324px; + border: 1px solid #ddd; + padding: 0; + margin: 0 0 0 1px; + background-color: #f8f8f8; +} + +.odin-table > table { + margin-bottom: 0; +} + +.odin-table > table > tbody > tr { + background-color: #fff; +} + +.odin-table-pointed-line { + cursor: pointer; +} + +.odin-table-selected-line { + background-color: #5bc0de !important; +} + +.odin-table-selected-line:hover { + background-color: #6bd0ee !important; +} + +/* + Odin Form + */ +.odin-form { + display: none; + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: 1500; + background: rgba(0, 0, 0, 0.5); +} + +.odin-form .panel { + position: relative; + max-height: 95%; + max-width: 95%; + overflow: auto; +} + +@media (min-width: 768px) { + .odin-form .panel { + max-width: 55%; + } +} + +.odin-form .panel-footer { + padding: 5px 7px; +} + +.odin-form .odin-btn { + float: right; +} + +.odin-checkbox { + width: 20px; + height: 20px; +} + +.odin-form .tab-pane { + padding-top: 5px; +} + +/* + Odin Confirm Box + */ +.odin-confirm-box { + display: none; + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: 2000; + background: rgba(0, 0, 0, 0.5); +} + +.odin-confirm-box .panel { + position: relative; + max-width: 95%; +} + +.odin-confirm-box .panel-footer { + text-align: center; +} + +@media (min-width: 768px) { + .odin-confirm-box .panel { + max-width: 25%; + } +} + +.odin-confirm-box .panel-body { + text-align: center; +} + +/* + Odin Table Box + */ +.odin-table-box { + z-index: 2500; +} + +/* + Odin Simple Box + */ + +@media (min-width: 768px) { + .odin-simple-form .panel { + max-width: 35%; + } +} \ No newline at end of file diff --git a/src/main/resources/public/css/paper.css b/src/main/resources/public/css/paper.css new file mode 100644 index 0000000..6e61d0c --- /dev/null +++ b/src/main/resources/public/css/paper.css @@ -0,0 +1,5 @@ +#files-list .row > div:nth-child(6) { + display: flex; + justify-content: center; + flex-direction: column; +} \ No newline at end of file diff --git a/src/main/resources/public/css/tasks.css b/src/main/resources/public/css/tasks.css new file mode 100644 index 0000000..2f42db5 --- /dev/null +++ b/src/main/resources/public/css/tasks.css @@ -0,0 +1,24 @@ +.bootstrap-tagsinput{ + + width: 100%; + padding: .375rem .75rem; +} + +.bootstrap-tagsinput .label{ + + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: 700; + line-height: 2.5; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} + +.bootstrap-tagsinput .label-info{ + + background-color: orange; +} diff --git a/src/main/resources/public/js/conference.js b/src/main/resources/public/js/conference.js new file mode 100644 index 0000000..304daae --- /dev/null +++ b/src/main/resources/public/js/conference.js @@ -0,0 +1,27 @@ +$(document).ready(function () { + + $('.data-href-js').click( function() { + window.location = $(this).attr('data-href'); + }); + + $('.circle').parent().click( function() { + $(this).children('.circle').toggleClass('circle-active'); + }); + + $('.checkbox-js').parent().click( function() { + $(this).children('.checkbox').toggleClass('selected'); + }); + + $('#select-all-js').click( function() { + $(this).toggleClass('selected'); + + var childNodes = $('.conference-item .form-check .checkbox') + .each(function(i, elem) { + if ($(this).hasClass('selected') && !$('#select-all-js').hasClass('selected')) { + $(this).toggleClass('selected'); + } else if (!$(this).hasClass('selected') && $('#select-all-js').hasClass('selected')){ + $(this).toggleClass('selected'); + } + }); + }); +}); diff --git a/src/main/resources/public/js/config.js b/src/main/resources/public/js/config.js new file mode 100644 index 0000000..50d1b40 --- /dev/null +++ b/src/main/resources/public/js/config.js @@ -0,0 +1,13 @@ +/* exported contextPath */ +var contextPath = ""; +var apiVersion = "/api/1.0"; + +var basePath = contextPath + apiVersion; + +/* exported uiLocale */ +var uiLocale = "ru"; + +/* exported urlVersions */ +var urlVersions = basePath + "/versions"; +/* exported urlCommits */ +var urlCommits = basePath + "/commits"; \ No newline at end of file diff --git a/src/main/resources/public/js/core.js b/src/main/resources/public/js/core.js index 5c9241c..bf6fb77 100644 --- a/src/main/resources/public/js/core.js +++ b/src/main/resources/public/js/core.js @@ -1,7 +1,9 @@ // from config.js /* global urlVersions */ -var urlFileUpload = "/api/1.0/papers/uploadTmpFile"; +var urlFileUpload = "/api/1.0/files/uploadTmpFile"; +var urlFileDownload = "/api/1.0/files/download/"; +var urlFileDownloadTmp = "/api/1.0/files/download-tmp/"; /* exported MessageTypesEnum */ var MessageTypesEnum = { @@ -86,20 +88,18 @@ function getFromRest(url, callBack, errorCallBack) { } /* exported getFromRestWithVersion */ -function getFromRestWithVersion(url, callBack, errorCallBack) { - getFromRestWithVersionAndParams(url, "", callBack, errorCallBack); +function getFromRest(url, callBack, errorCallBack) { + getFromRestWithParams(url, "", callBack, errorCallBack); } /* exported getFromRestWithVersionAndParams */ -function getFromRestWithVersionAndParams(url, params, callBack, errorCallBack) { - getCurrentVersion(function (version) { - $.ajax({ - url: url + "?versionId=" + version + params, - cache: false, - success: function (response) { - errorHandler(response, callBack, errorCallBack); - } - }); +function getFromRestWithParams(url, params, callBack, errorCallBack) { + $.ajax({ + url: url + "?" + params, + cache: false, + success: function (response) { + errorHandler(response, callBack, errorCallBack); + } }); } @@ -189,32 +189,6 @@ function deleteFromRest(url, callBack, completeCallback, errorCallBack) { }); } -/* exported getCurrentVersion */ -function getCurrentVersion(callBack, errorCallBack) { - var version = localStorage.getItem("currentVersion"); - - if (($("#select-versions")[0].options.length > 0) - && ($("#select-versions option[value='" + version + "']").length === 0)) { - localStorage.removeItem("currentVersion"); - version = ""; - } - - if (isEmpty(version)) { - getFromRest(urlVersions, - function (versions) { - if (isEmpty(versions) || versions.count === 0) { - return; - } - var currentVersion = versions.items[0]; - localStorage.setItem("currentVersion", currentVersion.id); - callBack(currentVersion.id); - }, - errorCallBack); - } else { - callBack(version); - } -} - /* exported fillSelect */ function fillSelect(selectElement, values) { $(selectElement).html(""); diff --git a/src/main/resources/public/js/file-loader.js b/src/main/resources/public/js/file-loader.js index 9ee16a1..1ba467b 100644 --- a/src/main/resources/public/js/file-loader.js +++ b/src/main/resources/public/js/file-loader.js @@ -42,6 +42,7 @@ function FileLoader(args) { div.append(fileLabel); var fileInput = $("") .attr("type", "file") + .attr("multiple", '') .hide(); fileInput.change(function () { var files = $(this).prop("files"); @@ -75,20 +76,22 @@ function FileLoader(args) { showFeedbackMessage(ALERT_CHOOSE_FILE, MessageTypesEnum.DANGER); return; } - var currentFile = files[0]; - if (!isEmpty(fileExtensions) && fileExtensions.indexOf(getFileExt(currentFile)) === -1) { - showFeedbackMessage(ALERT_UNKNOWN_FILE_EXT, MessageTypesEnum.DANGER); - return; - } - if (currentFile.size === 0) { - showFeedbackMessage(ALERT_EMPTY_FILE, MessageTypesEnum.DANGER); - return; - } - if (currentFile.size / SIZE_TO_MB > MAX_FILE_SIZE_MB) { - showFeedbackMessage(ALERT_MAX_FILE + " " + MAX_FILE_SIZE_MB + "Mb", MessageTypesEnum.DANGER); - return; + for (var i = 0; i < files.length; i++) { + var currentFile = files[i]; + if (!isEmpty(fileExtensions) && fileExtensions.indexOf(getFileExt(currentFile)) === -1) { + showFeedbackMessage(ALERT_UNKNOWN_FILE_EXT, MessageTypesEnum.DANGER); + return; + } + if (currentFile.size === 0) { + showFeedbackMessage(ALERT_EMPTY_FILE, MessageTypesEnum.DANGER); + return; + } + if (MAX_FILE_SIZE_MB != -1 && currentFile.size / SIZE_TO_MB > MAX_FILE_SIZE_MB) { + showFeedbackMessage(ALERT_MAX_FILE + " " + MAX_FILE_SIZE_MB + "Mb", MessageTypesEnum.DANGER); + return; + } + upload(currentFile); } - upload(currentFile); }); buttonGroup.append(uploadButton); diff --git a/src/main/resources/public/js/odin.js b/src/main/resources/public/js/odin.js new file mode 100644 index 0000000..54d8832 --- /dev/null +++ b/src/main/resources/public/js/odin.js @@ -0,0 +1,1512 @@ +// form config.js +/* global uiLocale, urlVersions */ +// from core.js +/* global isEmpty, deleteFromRest, fillSelect, MessageTypesEnum, showFeedbackMessage, getCurrentVersionData */ +/* global getFromRestWithParams, getFromRest */ +/* global postToRestWithVersionAndParams, putToRestWithVersionAndParams */ + +// TODO: settings for table selection mode (single, multiple) + +var odinMetaList = "/meta/list"; +var odinMetaElement = "/meta/element"; +var odinCopy = "/copy-from-version"; + +/* exported OdinTableWithMeta */ +function OdinTableWithMeta(divId, dataUrl, disableCopy) { + return OdinTableWithMetaAndParams(divId, dataUrl, "", disableCopy, ""); +} + +/* exported OdinTableWithMetaAndGlobalCallback */ +function OdinTableWithMetaAndGlobalCallback(divId, dataUrl, disableCopy, globalSaveCallback, globalSelectCallback) { + return OdinTableWithMetaAndParams(divId, dataUrl, "", disableCopy, globalSaveCallback, globalSelectCallback); +} + +/* exported OdinTableWithMetaAndParams */ +function OdinTableWithMetaAndParams(divId, dataUrl, params, disableCopy, globalSaveCallback, globalSelectCallback) { + return new OdinTable(divId, dataUrl + odinMetaList, dataUrl + odinMetaElement, dataUrl, + params, disableCopy, globalSaveCallback, globalSelectCallback); +} + +function OdinTable(divId, listMetaDataUrl, elementMetaDataUrl, dataUrl, params, disableCopy, globalSaveCallback, globalSelectCallback) { + var CLICK_DELAY = 250; + var DATA_ATTR = "odin-data"; + var DATA_VIEW_ATTR = "odin-data-view"; + var TYPE_ATTR = "type"; + var ID_ATTR = "id"; + var DISABLED_ATTR = "disabled"; + var REQUIRED_ATTR = "required"; + var LABELS_SELECTOR = "label"; + var INPUTS_SELECTOR = ":input"; + var BUTTONS_SELECTOR = ":button"; + var CHECKED_ATTR = "checked"; + var NOT_CHECKED_ATTR = ""; + var PAGINATOR_ITEMS_PER_PAGE = 10; + var PAGINATOR_VISIBLE_BUTTONS_COUNT = 3; + var odinTable; + + var L10nEnum = { + VIEW: "Наименование", + COLLECTION: "Коллеция объектов", + GO_TO: "Перейти", + + BUTTON_ADD: "Добавить", + BUTTON_CREATE: "Создать", + BUTTON_EDIT: "Изменить", + BUTTON_DELETE: "Удалить", + + BUTTON_COPY: "Копировать", + + BUTTON_OK: "Продолжить", + BUTTON_CANCEL: "Отмена", + + BUTTON_SAVE: "Записать", + BUTTON_CLOSE: "Закрыть", + + CAPTION_CREATE_FORM: "Новый элемент", + CAPTION_EDIT_FORM: "(редактирование)", + CAPTION_CHOOSE_FORM: "Выбор объекта", + CAPTION_COPY_FORM: "Копирование данных", + CAPTION_DEFAULT_TAB: "Реквизиты", + CPATION_FORM_DEFAULT: "...", + + QUESTION_LOST_CHANGES: "Закрыть без сохранения?", + QUESTION_DELETE_ITEM: "Выполнить удаление?", + QUESTION_DEFAULT_CAPTION: "Продолжит?", + + ERROR_VERSIONS_MATCH: "Версии совпадают" + }; + Object.freeze(L10nEnum); + + var FieldTypesEnum = { + BOOLEAN: "boolean", + DATE: "date", + NUMERIC: "numeric", + STRING: "string", + COLLECTION: "collection", + OBJECT: "object" + }; + Object.freeze(FieldTypesEnum); + + var DateTypesEnum = { + DATETIME: "datetime", + DATE: "date", + TIME: "time" + }; + Object.freeze(DateTypesEnum); + + var StringTypesEnum = { + STRING: "string", + PASSWORD: "password", + TEXT: "text", + EMAIL: "email", + HREF: "href" + }; + Object.freeze(StringTypesEnum); + + var VisibleTypesEnum = { + ALL: "all", + ON_CREATE: "on_create", + ON_UPDATE: "on_update", + NONE: "none" + }; + Object.freeze(VisibleTypesEnum); + + var InputTypesEnum = { + CHECKBOX: "checkbox", + PASSWORD: "password", + TEXT: "text", + EMAIL: "email", + DATE: "date", + DATETIME: "datetime-local", + TIME: "time", + NUMBER: "number", + HIDDEN: "hidden", + SUBMIT: "submit" + }; + Object.freeze(InputTypesEnum); + + var FormTypesEnum = { + FORM: "form", + CONFIRM: "confirm", + SIMPLE: "simple" + }; + Object.freeze(FormTypesEnum); + + var NumberAttrEnum = { + MIN: "min", + MAX: "max", + STEP: "step" + }; + Object.freeze(NumberAttrEnum); + + var StringAttrEnum = { + MIN: "minlength", + MAX: "maxlength" + }; + Object.freeze(StringAttrEnum); + + $(document.body).append("
"); + $("#odinTemplates").load("/templates/odin.html", function () { + $("#" + divId).append("
" + + " " + + "
"); + odinTable = new OdinTableMain(divId, listMetaDataUrl, elementMetaDataUrl, dataUrl, params, disableCopy, globalSaveCallback, globalSelectCallback); + }); + + this.getSelectedItems = function () { + return odinTable.getSelectedItems(); + } + + function format(str, args) { + if (isEmpty(str) || isEmpty(args)) { + return str; + } + if (!Array.isArray(args)) { + throw "Odin: Format args is not array"; + } + return str.replace(/\{(\d+)\}/g, + function (match, number) { + return typeof args[number] !== "undefined" ? + args[number] : match; + }); + } + + function centerDiv(component) { + if (isEmpty(component)) { + return; + } + component.offset({ + top: ($(window).height() - component.height()) / 2, + left: ($(window).width() - component.width()) / 2 + }); + } + + function tmpl(id) { + var html = $("#odinTemplates").find("#" + id).html(); + if (isEmpty(html)) { + throw "Odin: Template load error"; + } + var template = format(html.trim(), Array.prototype.slice.call(arguments, 1)); + return $(template); + } + + function find(object, selector) { + var result = object.find(selector); + if (isEmpty(result)) { + throw "Can't find elements by selector " + selector; + } + return result; + } + + function findFiltered(object, selector, notSelector) { + var result = object.find(selector).not(notSelector); + if (isEmpty(result)) { + throw "Can't find elements by selector " + selector; + } + return result; + } + + function OdinFormCommon(type) { + var BUTTON_CLOSE_SELECTOR = "i.fa"; + var CAPTION_SELECTOR = "#caption"; + var PANEL_SELECTOR = ".panel"; + var FORM_INPUTS_SELECTOR = ":input"; + var DATA_CHANGED_ATTR = "changed"; + + var form; + var header; + var content; + var footer; + + var createForm = function () { + switch (type) { + case FormTypesEnum.FORM: + form = tmpl("form"); + break; + case FormTypesEnum.CONFIRM: + form = tmpl("formConfirm"); + break; + default: + form = tmpl("formSimple"); + } + if (isEmpty(form)) { + throw "Odin: Unknown form type"; + } + header = createFormHeader(); + content = createFormContent(); + footer = createFormFooter(); + var formPanel = tmpl("formPanel"); + formPanel.append(header); + formPanel.append(content); + formPanel.append(footer); + form.append(formPanel); + setCaption(L10nEnum.CPATION_FORM_DEFAULT); + $(document.body).append(form); + }; + + var createFormHeader = function () { + var fHeader = tmpl("formHeader"); + fHeader.find(BUTTON_CLOSE_SELECTOR).click(function () { + hideForm(); + }); + return fHeader; + }; + + var createFormContent = function () { + return tmpl("formContent"); + }; + + var createFormFooter = function () { + return tmpl("formFooter"); + }; + + var setCaption = function (caption) { + if (isEmpty(caption)) { + throw "Odin: Caption is not set"; + } + find(header, CAPTION_SELECTOR).text(caption); + }; + + var addFormClass = function (clazz) { + if (isEmpty(clazz)) { + throw "Odin: Additional class is not set"; + } + form.addClass(clazz); + }; + + var isModified = function () { + return form.data(DATA_CHANGED_ATTR); + }; + + var setFormSubmit = function (callBack) { + if (isEmpty(callBack)) { + throw "Odin: Callback is not set"; + } + form.submit(function () { + callBack(); + return false; + }); + }; + + var showForm = function () { + form.show(0, function () { + centerDiv(find(form, PANEL_SELECTOR)); + }); + if (type === FormTypesEnum.FORM) { + find(form, FORM_INPUTS_SELECTOR).change(function () { + form.data(DATA_CHANGED_ATTR, true); + }); + } + }; + + var hideForm = function () { + var callBack = function () { + form.hide(); + form.remove(); + }; + callBack(); + }; + + this._getHeader = function () { + return header; + }; + + this._getContent = function () { + return content; + }; + + this._getFooter = function () { + return footer; + }; + + this._setCaption = function (caption) { + setCaption(caption); + }; + + this._setFormSubmit = function (callBack) { + setFormSubmit(callBack); + }; + + this._addFormClass = function (clazz) { + addFormClass(clazz); + }; + + this._isModified = function () { + return isModified(); + }; + + this._show = function () { + showForm(); + }; + + this._hide = function () { + hideForm(); + }; + + createForm(); + } + + function OdinToolbar(tableDiv, createCallBack, editCallBack, deleteCallBack) { + var SELECTOR_ODIN_TABLE = ".odin-table"; + + var toolbar; + + var createButton; + var editButton; + var deleteButton; + + var initialize = function () { + if (isEmpty(tableDiv)) { + throw "Odin-Toolbar: Target div is not set"; + } + var table = find(tableDiv, SELECTOR_ODIN_TABLE); + toolbar = tmpl("toolbar"); + toolbar.insertBefore(table, null); + if (!isEmpty(createCallBack)) { + createButton = tmpl("createButton", L10nEnum.BUTTON_CREATE); + createButton.click(function () { + createCallBack(); + }); + toolbar.append(createButton); + } + if (!isEmpty(editCallBack)) { + editButton = tmpl("editButton", L10nEnum.BUTTON_EDIT); + editButton.click(function () { + editCallBack(); + }); + setEditButtonState(false); + toolbar.append(editButton); + } + if (!isEmpty(deleteCallBack)) { + deleteButton = tmpl("deleteButton", L10nEnum.BUTTON_DELETE); + deleteButton.click(function () { + deleteCallBack(); + }); + setDeleteButtonState(false); + toolbar.append(deleteButton); + } + }; + + var setEditButtonState = function (state) { + if (isEmpty(editButton)) { + return; + } + editButton.attr("disabled", !state); + }; + + var setDeleteButtonState = function (state) { + if (isEmpty(deleteButton)) { + return; + } + deleteButton.attr("disabled", !state); + }; + + this.addButton = function (caption, callBack) { + if (isEmpty(caption) || isEmpty(callBack)) { + throw "Odin-Toolbar: Caption or callback is not set"; + } + var button = tmpl("basicButton", caption); + button.click(function () { + callBack(); + }); + toolbar.append(button); + }; + + this.setEditButtonState = function (state) { + setEditButtonState(state); + }; + + this.setDeleteButtonState = function (state) { + setDeleteButtonState(state); + }; + + initialize(); + } + + function OdinPaginator(tableDiv, callBack) { + var SELECTOR_PAGINATOR_CONTENT = ".odin-paginator-content"; + var SELECTOR_PAGINATOR_BUTTON = "a"; + var PAGINATOR_BUTTON_PREFIX = "odin-paginator-"; + var PAGINATOR_SELECTED_BUTTON_CLASS = "active"; + + var initialize = function () { + if (isEmpty(tableDiv)) { + throw "Odin-Paginator: Target div is not set"; + } + if (isEmpty(callBack)) { + throw "Odin-Paginator: Callback is not set"; + } + tableDiv.append(tmpl("paginator")); + }; + + var drawPaginator = function (data, offset) { + var paginatorContentDiv = find(tableDiv, SELECTOR_PAGINATOR_CONTENT); + paginatorContentDiv.empty(); + if (isEmpty(data)) { + return; + } + $.each(data, function (index, value) { + if (value.name) { + paginatorContentDiv.append(tmpl("paginatorButton", value.offset, value.name)); + } else { + paginatorContentDiv.append(tmpl("paginatorSeparator")); + } + }); + var buttons = find(paginatorContentDiv, SELECTOR_PAGINATOR_BUTTON); + buttons.removeClass("active"); + buttons.click(function () { + $('#preloader').show(); + var offset = $(this).attr(ID_ATTR).replace(PAGINATOR_BUTTON_PREFIX, ""); + callBack(offset); + }); + find(paginatorContentDiv, "#" + PAGINATOR_BUTTON_PREFIX + offset) + .addClass(PAGINATOR_SELECTED_BUTTON_CLASS); + }; + + this.drawPaginator = function (offset, count) { + var currentOffset = parseInt(offset ? offset : "0"); + var buttonCount = Math.floor( + count <= PAGINATOR_ITEMS_PER_PAGE ? 0 : count / PAGINATOR_ITEMS_PER_PAGE) + + (count < PAGINATOR_ITEMS_PER_PAGE || + count % PAGINATOR_ITEMS_PER_PAGE === 0 ? 0 : 1); + var data = []; + Array.apply(0, Array(buttonCount)).forEach(function (element, index) { + if (index > 0 && index < buttonCount - 1 && + buttonCount > PAGINATOR_VISIBLE_BUTTONS_COUNT * 2) { + if (index === currentOffset - PAGINATOR_VISIBLE_BUTTONS_COUNT || + index === currentOffset + PAGINATOR_VISIBLE_BUTTONS_COUNT + 1) { + data.push({ + "offset": null, + "name": null + }); + } + if (index <= currentOffset - PAGINATOR_VISIBLE_BUTTONS_COUNT || + index > currentOffset + PAGINATOR_VISIBLE_BUTTONS_COUNT) { + return true; + } + } + data.push({ + "offset": index, + "name": index + 1 + }); + }); + drawPaginator(data, currentOffset); + }; + + initialize(); + } + + function OdinTableFormatter() { + var BOOLEAN_TRUE_CLASS = "fa-check"; + var BOOLEAN_FALSE_CLASS = "fa-times"; + + var formatBooleanValue = function (value) { + return tmpl("tableBoolean", (value ? BOOLEAN_TRUE_CLASS : BOOLEAN_FALSE_CLASS)); + }; + + var formatDateValue = function (value, dateType) { + var date = new Date(value); + var formatterSettings = {}; + switch (dateType) { + case DateTypesEnum.DATETIME: + formatterSettings = { + year: "numeric", + month: "numeric", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric" + }; + break; + case DateTypesEnum.TIME: + formatterSettings = { + hour: "numeric", + minute: "numeric", + second: "numeric" + }; + break; + } + var dateFormatter = new Intl.DateTimeFormat(uiLocale, formatterSettings); + return dateFormatter.format(date); + }; + + var formatNumericValue = function (value, positiveOnly, scale) { + var numberFormatter = new Intl.NumberFormat(uiLocale, { + useGrouping: false, + minimumFractionDigits: scale + }); + var formattedValue = numberFormatter.format(value); + if (positiveOnly && value < 0) { + return tmpl("tableNumericNegative", formattedValue); + } + return formattedValue; + }; + + var formatStringValue = function (value, maxLength, stringType) { + switch (stringType) { + case StringTypesEnum.HREF: + return tmpl("anchor", value, L10nEnum.GO_TO); + default: + if (isEmpty(maxLength) || maxLength === 0) { + return value; + } + return value.substring(0, Math.min(value.length, maxLength)); + } + }; + + this.formatValue = function (value, fieldParams) { + if (isEmpty(value) || isEmpty(fieldParams)) { + return ""; + } + if (fieldParams.hidden) { + return value; + } + switch (fieldParams.fieldType) { + case FieldTypesEnum.BOOLEAN: + return formatBooleanValue(value); + case FieldTypesEnum.DATE: + return formatDateValue(value, fieldParams.type); + case FieldTypesEnum.NUMERIC: + return formatNumericValue(value, fieldParams.positiveOnly, fieldParams.scale); + case FieldTypesEnum.STRING: + return formatStringValue(value, fieldParams.maxLength, fieldParams.type); + case FieldTypesEnum.COLLECTION: + return L10nEnum.COLLECTION; + case FieldTypesEnum.OBJECT: + return value.view; + default: + return value; + } + }; + } + + function OdinTableView(odinDiv, editCallback, globalSelectCallback) { + var TABLEVIEW_SELECTED_LINE_CLASS = "odin-table-selected-line"; + var TABLEVIEW_LINE_SELECTOR = "tr"; + var TABLEVIEW_SELECTED_LINE_SELECTOR = TABLEVIEW_LINE_SELECTOR + + "." + TABLEVIEW_SELECTED_LINE_CLASS; + var TABLEVIEW_LINE_DATA_SELECTOR = TABLEVIEW_LINE_SELECTOR + + "[" + DATA_ATTR + "=\"{0}\"]"; + var TABLEVIEW_CHOOSABLE_CLASS = "table-hover odin-unselectable"; + var TABLEVIEW_LINE_POINTED_CLASS = "odin-table-pointed-line"; + var TABLEVIEW_HEAD_COLUMN_SELECTOR = "th:nth-child({0})"; + var TABLEVIEW_BODY_COLUMN_SELECTOR = "td:nth-child({0})"; + + var tTable; + var tHead; + var tBody; + var choosable; + var formatter; + var toolbar; + + var createLine = function (idValue) { + var prevent = false; + var timer = 0; + var newLine = tmpl("tableLine"); + if (!isEmpty(idValue) && choosable) { + newLine.attr(DATA_ATTR, idValue); + newLine.click(function () { + var btn = $(this); + timer = setTimeout(function () { + if (!prevent) { + btn.toggleClass(TABLEVIEW_SELECTED_LINE_CLASS); + } + prevent = false; + if (!isEmpty(globalSelectCallback)) { + globalSelectCallback(getLines()); + } + if (!isEmpty(toolbar)) { + toolbar.setEditButtonState(!isEmpty(getLines())); + toolbar.setDeleteButtonState(!isEmpty(getLines())); + } + }, CLICK_DELAY); + }); + if (!isEmpty(editCallback)) { + newLine.dblclick(function () { + clearTimeout(timer); + prevent = true; + editCallback(idValue); + }); + } + newLine.addClass(TABLEVIEW_LINE_POINTED_CLASS); + } + return newLine; + }; + + var addLineToHead = function (line) { + tHead.append(line); + }; + + var addLineToBody = function (line) { + tBody.append(line); + }; + + var clearBody = function () { + tBody.empty(); + }; + + var initialize = function () { + if (isEmpty(odinDiv)) { + throw "Odin: Odin div is not set"; + } + odinDiv.append(tmpl("table")); + tTable = find(odinDiv, "table"); + tHead = find(odinDiv, "thead"); + tBody = find(odinDiv, "tbody"); + formatter = new OdinTableFormatter(); + }; + + var getLines = function (isAll) { + var selector = isAll ? TABLEVIEW_LINE_SELECTOR : TABLEVIEW_SELECTED_LINE_SELECTOR; + var selectedItems = []; + try { + find(tBody, selector).each(function () { + selectedItems.push({ + id: $(this).attr(DATA_ATTR), + view: $(this).attr(DATA_VIEW_ATTR) + }); + }); + } catch (e) { + // Ignore + } + return selectedItems; + }; + + var disableToolbar = function () { + if (isEmpty(toolbar)) { + return; + } + toolbar.setEditButtonState(false); + toolbar.setDeleteButtonState(false); + }; + + this.createHead = function (metaData, isOdinDto) { + if (isEmpty(metaData)) { + throw "Odin: Metadata is not set"; + } + choosable = isOdinDto; + if (choosable) { + tTable.addClass(TABLEVIEW_CHOOSABLE_CLASS); + } + var tHeadLine = createLine(); + $.each(metaData, function (index, value) { + tHeadLine.append(tmpl("tableHeadColumn", value.caption)); + }); + addLineToHead(tHeadLine); + $.each(metaData, function (columnIndex, columnParams) { + if (columnParams.visible === VisibleTypesEnum.NONE) { + var index = columnIndex + 1; + find(tHead, format(TABLEVIEW_HEAD_COLUMN_SELECTOR, [index])).hide(); + } + }); + }; + + this.fillBody = function (metaData, data) { + clearBody(); + $.each(data, function (index, value) { + var idValue = choosable ? value.id : null; + var line = createLine(idValue); + line.attr(DATA_VIEW_ATTR, value.view); + $.each(metaData, function (columnIndex, columnParams) { + var column = tmpl("tableBodyColumn"); + column.append( + formatter.formatValue(value[columnParams.fieldName], + columnParams)); + line.append(column); + }); + addLineToBody(line); + }); + if (!isEmpty(data)) { + $.each(metaData, function (columnIndex, columnParams) { + if (columnParams.visible === VisibleTypesEnum.NONE) { + var index = columnIndex + 1; + find(tBody, format(TABLEVIEW_BODY_COLUMN_SELECTOR, [index])).hide(); + } + }); + } + }; + + this.getSelectedItems = function () { + return getLines(false); + }; + + this.getItems = function () { + return getLines(true); + }; + + // Delete form view only! + this.deleteById = function (id) { + if (isEmpty(id)) { + return; + } + try { + find(tBody, format(TABLEVIEW_LINE_DATA_SELECTOR, [id])).remove(); + disableToolbar(); + } catch (e) { + // Ignore + } + }; + + this.setToolbar = function (toolbarVar) { + toolbar = toolbarVar; + }; + + this.disableToolbar = function () { + disableToolbar(); + }; + + initialize(); + } + + function OdinTableMain(divId, listMetaDataUrl, elementMetaDataUrl, dataUrl, args, disableCopy, globalSaveCallback, globalSelectCallback) { + if (isEmpty(divId) || isEmpty(listMetaDataUrl) || isEmpty(dataUrl)) { + throw "Odin: Not enough parameters"; + } + + var OFFSET_ARG = "&offset="; + var COUNT_ARG = "&count="; + + var odinDiv; + var tableView; + var paginator; + + var currentOffset; + + var listMetaData; + var elementMetaData; + + var params = isEmpty(args) ? "" : args; + + var drawBody = function (offset) { + if (isEmpty(listMetaData)) { + throw "Odin: Meta data is not defined"; + } + currentOffset = isEmpty(offset) ? 0 : parseInt(offset); + getFromRestWithParams(dataUrl, + OFFSET_ARG + (currentOffset * PAGINATOR_ITEMS_PER_PAGE) + + COUNT_ARG + PAGINATOR_ITEMS_PER_PAGE + params, function (data) { + if (isEmpty(data)) { + throw "Odin: Response data is null"; + } + tableView.fillBody(listMetaData, data.items); + if (data.count > 0) { + paginator.drawPaginator(offset, data.count); + } + tableView.disableToolbar(); + $('#preloader').hide(); + }); + }; + + var initialize = function () { + odinDiv = find($(document.body), "#" + divId); + tableView = new OdinTableView(odinDiv, editItem, globalSelectCallback); + paginator = new OdinPaginator(odinDiv, drawBody); + getFromRest(listMetaDataUrl, function (data) { + if (isEmpty(data) || isEmpty(data.fields)) { + throw "Odin: Can't load list meta data"; + } + var isOdinDto = data.odinDto; + listMetaData = data.fields; + if (isOdinDto && !isEmpty(elementMetaDataUrl)) { + getFromRest(elementMetaDataUrl, function (data) { + if (isEmpty(data) || isEmpty(data.fields)) { + throw "Odin: Can't load element meta data"; + } + elementMetaData = data.fields; + var toolbar = new OdinToolbar(odinDiv, createItem, editItem, deleteItem, globalSaveCallback); + tableView.setToolbar(toolbar); + if (!disableCopy) { + toolbar.addButton(L10nEnum.BUTTON_COPY, function () { + new OdinCopyBox(dataUrl, drawBody); + }); + } + }); + } + tableView.createHead(listMetaData, isOdinDto); + drawBody(); + }); + }; + + var updateTable = function () { + // TODO: recalculate offset before redraw table + drawBody(currentOffset); + }; + + var createItem = function () { + new OdinForm(elementMetaData, dataUrl, updateTable, null, params); + }; + + var editItem = function (value) { + if (isEmpty(elementMetaDataUrl)) { + return; + } + var curValue = value; + if (isEmpty(value)) { + var selectedItems = tableView.getSelectedItems(); + if (!isEmpty(selectedItems)) { + curValue = selectedItems[0].id; + } + } + if (isEmpty(curValue)) { + return; + } + new OdinForm(elementMetaData, dataUrl, updateTable, curValue, params); + }; + + var deleteItem = function () { + var selectedItems = tableView.getSelectedItems(); + if (isEmpty(selectedItems)) { + return; + } + var callBack = function () { + $.each(selectedItems, function (index, value) { + deleteFromRest(dataUrl + "/" + value.id, null, function () { + if (index === selectedItems.length - 1) { + updateTable(); + } + }); + }); + }; + new OdinConfirmBox(callBack, L10nEnum.QUESTION_DELETE_ITEM); + }; + + this.getSelectedItems = function () { + return tableView.getSelectedItems(); + }; + + initialize(); + } + + function OdinFormControlGenerator() { + this.createInputGroup = function () { + return tmpl("formInputGroup"); + }; + + this.createLabel = function (id, caption) { + return tmpl("formLabel", id, caption); + }; + + var createInput = function (id, value, type) { + if (isEmpty(id)) { + throw "Odin: Input id is not set"; + } + if (isEmpty(type)) { + throw "Odin: Input type is not set"; + } + var curValue = isEmpty(value) ? "" : value; + var wrapper = tmpl("formInputWrapper"); + if (type === InputTypesEnum.CHECKBOX) { + wrapper.append(tmpl("formInputCheckbox", + id, (curValue ? CHECKED_ATTR : NOT_CHECKED_ATTR))); + } else { + wrapper.append(tmpl("formInput", + id, curValue, type)); + } + return wrapper; + }; + + this.createBooleanInput = function (id, value) { + return createInput(id, value, InputTypesEnum.CHECKBOX); + }; + + var fixDateUnit = function (dateUnitValue) { + return dateUnitValue < 10 ? "0" + dateUnitValue : dateUnitValue; + }; + + var dateToStr = function (value, type) { + if (isEmpty(value)) { + return ""; + } + var date = new Date(value); + var year = fixDateUnit(date.getFullYear()); + var month = fixDateUnit(date.getMonth() + 1); + var day = fixDateUnit(date.getDate()); + var hour = fixDateUnit(date.getHours()); + var minute = fixDateUnit(date.getMinutes()); + var formattedDate; + switch (type) { + case DateTypesEnum.DATETIME: + formattedDate = year + "-" + month + "-" + day + "T" + hour + ":" + minute; + break; + case DateTypesEnum.TIME: + formattedDate = hour + ":" + minute; + break; + default: + formattedDate = year + "-" + month + "-" + day; + } + return formattedDate; + }; + + this.createDateInput = function (id, value, type) { + var dateType; + switch (type) { + case DateTypesEnum.DATETIME: + dateType = InputTypesEnum.DATETIME; + break; + case DateTypesEnum.TIME: + dateType = InputTypesEnum.TIME; + break; + default: + dateType = InputTypesEnum.DATE; + } + return createInput(id, dateToStr(value, type), dateType); + }; + + this.createNumericInput = function (id, value) { + return createInput(id, value, InputTypesEnum.NUMBER); + }; + + this.createStringInput = function (id, value, type) { + var stringType; + switch (type) { + case StringTypesEnum.PASSWORD: + stringType = InputTypesEnum.PASSWORD; + break; + case StringTypesEnum.EMAIL: + stringType = InputTypesEnum.EMAIL; + break; + default: + stringType = InputTypesEnum.TEXT; + } + return createInput(id, value, stringType); + }; + + this.dateToStr = function (value, type) { + return dateToStr(value, type); + }; + } + + function OdinFormContentGenerator(createNavTabCallBack, isCreateOperation) { + var PRECISION_CHAR = "9"; + var SCALE_PREFIX = "0."; + var SCALE_CHAR = "0"; + var SCALE_POSTFIX = "1"; + var OBJECT_INPUT_CLASS = "input-group odin-input-group"; + var CREATE_BUTTON_TEXT_SELECTOR = ".btn-success > span"; + var CHOOSE_BTN_SELECTOR = ".odin-choose-btn"; + var CLEAR_BTN_SELECTOR = ".odin-clear-btn"; + var CLEARABLE_INPUT_SELECTOR = ".form-control"; + + var controlGenerator = new OdinFormControlGenerator(); + + var createBooleanControl = function (id, caption, value) { + var group = controlGenerator.createInputGroup(); + group.append(controlGenerator.createLabel(id, caption)); + group.append(controlGenerator.createBooleanInput(id, value)); + return group; + }; + + var createDateControl = function (id, caption, value, type) { + var group = controlGenerator.createInputGroup(); + group.append(controlGenerator.createLabel(id, caption)); + group.append(controlGenerator.createDateInput(id, value, type)); + return group; + }; + + var createNumericControl = function (id, caption, value, positiveOnly, precision, scale) { + var group = controlGenerator.createInputGroup(); + group.append(controlGenerator.createLabel(id, caption)); + var control = controlGenerator.createNumericInput(id, value); + find(control, INPUTS_SELECTOR).each(function () { + var currentControl = $(this); + if (positiveOnly) { + currentControl.attr(NumberAttrEnum.MIN, 0); + } + if (precision) { + currentControl + .attr(NumberAttrEnum.MAX, Array(precision + 1).join(PRECISION_CHAR)); + } + if (scale) { + var step = SCALE_PREFIX + Array(scale).join(SCALE_CHAR) + SCALE_POSTFIX; + currentControl.attr(NumberAttrEnum.STEP, step); + } + }); + group.append(control); + return group; + }; + + var createStringControl = function (id, caption, value, minLength, maxLength, type) { + var group = controlGenerator.createInputGroup(); + group.append(controlGenerator.createLabel(id, caption)); + var control = controlGenerator.createStringInput(id, value, type); + find(control, INPUTS_SELECTOR).each(function () { + var currentControl = $(this); + currentControl.attr(StringAttrEnum.MIN, minLength); + currentControl.attr(StringAttrEnum.MAX, maxLength); + }); + group.append(control); + return group; + }; + + var createCollectionControl = function (id, caption, values, path) { + // TODO: add required check if needed + var content = $(tmpl("emptyDiv")); + var tabView = new OdinTableView(content, null, null); + var createAction = function () { + new OdinChooseBox(path, function (selectedItems) { + if (isEmpty(selectedItems)) { + return; + } + var currentValues = tabView.getItems(); + $.merge(currentValues, selectedItems); + var existingIDs = []; + currentValues = $.grep(currentValues, function (v) { + if ($.inArray(v.id, existingIDs) !== -1) { + return false; + } else { + existingIDs.push(v.id); + return true; + } + }); + tabView.fillBody(metaData, currentValues); + }); + }; + var deleteAction = function () { + var callBack = function () { + $.each(tabView.getSelectedItems(), function (index, value) { + tabView.deleteById(value.id); + }); + }; + new OdinConfirmBox(callBack, L10nEnum.QUESTION_DELETE_ITEM); + }; + content.append(tabView); + var metaData = [ + { + "fieldType": "string", + "fieldName": "id", + "caption": "id", + "visible": "none" + }, + { + "fieldType": "string", + "fieldName": "view", + "caption": L10nEnum.VIEW, + "visible": "all" + } + ]; + tabView.createHead(metaData, true); + tabView.fillBody(metaData, values); + createNavTabCallBack(id, caption, content); + var toolbar = new OdinToolbar(content, createAction, null, deleteAction); + tabView.setToolbar(toolbar); + find(content, CREATE_BUTTON_TEXT_SELECTOR).text(L10nEnum.BUTTON_ADD); + return null; + }; + + var createObjectControl = function (id, caption, value, path) { + // TODO: add required check if needed + var chooseInput = controlGenerator.createStringInput( + id, isEmpty(value) ? "" : value.view, StringTypesEnum.TEXT); + chooseInput.addClass(OBJECT_INPUT_CLASS); + var buttonGroup = tmpl("buttonGroup"); + chooseInput.append(buttonGroup); + var chooseButton = tmpl("chooseButton"); + buttonGroup.append(chooseButton); + find(buttonGroup, CHOOSE_BTN_SELECTOR).click(function () { + new OdinChooseBox(path, function (selectedItems) { + if (isEmpty(selectedItems)) { + return; + } + find(chooseInput, CLEARABLE_INPUT_SELECTOR).each(function () { + $(this) + .val(selectedItems[0].view) + .attr(DATA_ATTR, selectedItems[0].id); + }); + }); + }); + var clearButton = tmpl("clearButton"); + buttonGroup.append(clearButton); + find(buttonGroup, CLEAR_BTN_SELECTOR).click(function () { + find(chooseInput, CLEARABLE_INPUT_SELECTOR).val(""); + }); + find(chooseInput, CLEARABLE_INPUT_SELECTOR).each(function () { + $(this) + .attr(DISABLED_ATTR, true) + .attr(DATA_ATTR, isEmpty(value) ? "" : value.id); + }); + var group = controlGenerator.createInputGroup(); + group.append(controlGenerator.createLabel(id, caption)); + group.append(chooseInput); + return group; + }; + + var configureControl = function (control, hidden, readonly, notempty) { + if (isEmpty(control)) { + return; + } + find(control, LABELS_SELECTOR).each(function () { + var currentControl = $(this); + if (hidden) { + currentControl.hide(); + } + }); + find(control, INPUTS_SELECTOR).each(function () { + var currentControl = $(this); + if (hidden) { + currentControl.hide(); + currentControl.attr(TYPE_ATTR, InputTypesEnum.HIDDEN); + } + if (readonly) { + currentControl.attr(DISABLED_ATTR, true); + } + if (notempty) { + currentControl.attr(REQUIRED_ATTR, true); + } + }); + return control; + }; + + this.createFormControl = function (value, fieldParams) { + if (isEmpty(fieldParams)) { + return null; + } + var control; + switch (fieldParams.fieldType) { + case FieldTypesEnum.BOOLEAN: + control = createBooleanControl(fieldParams.fieldName, + fieldParams.caption, value); + break; + case FieldTypesEnum.DATE: + control = createDateControl(fieldParams.fieldName, + fieldParams.caption, value, fieldParams.type); + break; + case FieldTypesEnum.NUMERIC: + control = createNumericControl(fieldParams.fieldName, + fieldParams.caption, value, fieldParams.positiveOnly, + fieldParams.precision, fieldParams.scale); + break; + case FieldTypesEnum.STRING: + control = createStringControl(fieldParams.fieldName, + fieldParams.caption, value, fieldParams.minLength, + fieldParams.maxLength, fieldParams.type); + break; + case FieldTypesEnum.COLLECTION: + control = createCollectionControl(fieldParams.fieldName, + fieldParams.caption, value, fieldParams.path); + break; + case FieldTypesEnum.OBJECT: + control = createObjectControl(fieldParams.fieldName, + fieldParams.caption, value, fieldParams.path); + break; + default: + return null; + } + var hidden; + switch (fieldParams.visible) { + case VisibleTypesEnum.NONE: + hidden = true; + break; + case VisibleTypesEnum.ON_CREATE: + case VisibleTypesEnum.ON_UPDATE: + hidden = isCreateOperation; + break; + default: + hidden = false; + } + return configureControl(control, hidden, fieldParams.readOnly, fieldParams.notEmpty); + }; + + this.getCurrentDateStr = function () { + return controlGenerator.dateToStr(new Date(), DateTypesEnum.DATE); + }; + } + + function OdinForm(metaData, dataUrl, tableCallBack, id, args) { + if (isEmpty(metaData) || isEmpty(dataUrl) || isEmpty(tableCallBack)) { + throw "Odin: Not enough parameters"; + } + + var DEFAULT_TAB_SELECTOR = "odin-values"; + var TABS_HEADER_SELECTOR = ".nav-tabs"; + var TABS_CONTENT_SELECTOR = ".tab-content"; + var TAB_SELECTOR = ".tab-pane"; + var COLLECTION_ITEM_SELECTOR = "tbody > tr"; + + OdinFormCommon.call(this, FormTypesEnum.FORM); + + var self = this; + + var generator; + + var params = isEmpty(args) ? "" : args; + + var isCreateForm = function () { + return isEmpty(id); + }; + + var formToJson = function () { + var formData = {}; + try { + findFiltered(self._getContent(), TAB_SELECTOR, "#" + DEFAULT_TAB_SELECTOR) + .each(function () { + var tabData = []; + try { + find($(this), COLLECTION_ITEM_SELECTOR) + .each(function () { + if ($(this).attr(DATA_ATTR)) { + tabData.push({ + id: $(this).attr(DATA_ATTR), + view: $(this).attr(DATA_VIEW_ATTR) + }); + return true; + } + }); + } catch (e) { + // Ignore + } + formData[$(this).attr(ID_ATTR)] = tabData; + }); + } catch (e) { + // Ignore + } + findFiltered(self._getContent(), INPUTS_SELECTOR, BUTTONS_SELECTOR) + .each(function () { + if (isEmpty($(this).val())) { + return true; + } + if ($(this).attr(DATA_ATTR)) { + formData[$(this).attr(ID_ATTR)] = { + id: $(this).attr(DATA_ATTR), + view: $(this).val() + }; + return true; + } + switch ($(this).attr(TYPE_ATTR)) { + case InputTypesEnum.CHECKBOX: + formData[$(this).attr(ID_ATTR)] = $(this).is(":" + CHECKED_ATTR); + break; + case InputTypesEnum.DATE: + case InputTypesEnum.DATETIME: + formData[$(this).attr(ID_ATTR)] = isEmpty($(this).val) ? + "" : Date.parse($(this).val()); + break; + case InputTypesEnum.TIME: + formData[$(this).attr(ID_ATTR)] = isEmpty($(this).val) ? + "" : Date.parse(generator.getCurrentDateStr() + + "T" + $(this).val()); + break; + case InputTypesEnum.NUMBER: + formData[$(this).attr(ID_ATTR)] = parseFloat($(this).val()); + break; + default: + formData[$(this).attr(ID_ATTR)] = $(this).val(); + } + }); + return JSON.stringify(formData); + }; + + var initialize = function () { + generator = new OdinFormContentGenerator(createNavTab, isCreateForm()); + self._getContent() + .append(tmpl("formTabs", DEFAULT_TAB_SELECTOR, L10nEnum.CAPTION_DEFAULT_TAB)); + var okBtn = tmpl("okButton", L10nEnum.BUTTON_SAVE); + okBtn.attr(TYPE_ATTR, InputTypesEnum.SUBMIT); + var closeBtn = tmpl("cancelButton", L10nEnum.BUTTON_CLOSE); + self._getFooter().append(closeBtn); + self._getFooter().append(okBtn); + if (isCreateForm()) { + configureAndShowForm(); + } else { + getFromRest(dataUrl + "/" + id, function (data) { + if (isEmpty(data)) { + throw format("Odin: Can't load data by id {0} and url {1}", [id, dataUrl]); + } + configureAndShowForm(data); + }); + } + closeBtn.click(function () { + closeForm(); + }); + }; + + var configureAndShowForm = function (data) { + var saveCallBack = function () { + saveData(formToJson()); + }; + self._setCaption(isEmpty(data) ? + L10nEnum.CAPTION_CREATE_FORM : + data.view + " " + L10nEnum.CAPTION_EDIT_FORM); + self._setFormSubmit(saveCallBack); + $.each(metaData, function (fieldIndex, fieldParams) { + var value = isEmpty(data) ? + null : data[fieldParams.fieldName]; + find(self._getContent(), "#" + DEFAULT_TAB_SELECTOR) + .append(generator.createFormControl(value, fieldParams)); + }); + self._show(); + }; + + var createNavTab = function (id, caption, content) { + find(self._getContent(), TABS_HEADER_SELECTOR).append(tmpl("formTab", id, caption)); + var tab = tmpl("formTabContent", id); + tab.append(content); + find(self._getContent(), TABS_CONTENT_SELECTOR).append(tab); + }; + + var saveData = function (data) { + var saveCallback = function (responseData) { + if (isEmpty(responseData)) { + throw "Odin: Error on data save"; + } + self._hide(); + tableCallBack(); + if (!isEmpty(globalSaveCallback)) { + globalSaveCallback(); + } + }; + if (isCreateForm()) { + postToRestWithParams(dataUrl, data, params, saveCallback); + } else { + putToRestWithParams(dataUrl, data, params, saveCallback); + } + }; + + var closeForm = function () { + if (self._isModified()) { + new OdinConfirmBox(self._hide, L10nEnum.QUESTION_LOST_CHANGES); + return; + } + self._hide(); + }; + + initialize(); + } + + function OdinConfirmBox(callBack, questionText) { + if (isEmpty(callBack) || isEmpty(questionText)) { + throw "Odin: Not enough parameters"; + } + + OdinFormCommon.call(this, FormTypesEnum.CONFIRM); + + var self = this; + + var initialize = function () { + var yesBtn = tmpl("okButton", L10nEnum.BUTTON_OK); + var cancelBtn = tmpl("cancelButton", L10nEnum.BUTTON_CANCEL); + self._setCaption(L10nEnum.QUESTION_DEFAULT_CAPTION); + self._getContent().text(questionText); + self._getFooter().append(yesBtn); + self._getFooter().append(cancelBtn); + self._show(); + + yesBtn.click(function () { + self._hide(); + callBack(); + if (!isEmpty(globalSaveCallback)) { + globalSaveCallback(); + } + }); + cancelBtn.click(function () { + self._hide(); + }); + }; + + initialize(); + } + + function OdinChooseBox(path, callBack) { + if (isEmpty(path) || isEmpty(callBack)) { + throw "Odin: Not enough parameters"; + } + + var ADDITIONAL_FORM_CLASS = "odin-table-box"; + var ADDITIONAL_CONTENT_CLASS = "odin-kill-padding"; + var CONTENT_ID_VALUE = "table-block"; + + OdinFormCommon.call(this); + + var self = this; + + var initialize = function () { + self._addFormClass(ADDITIONAL_FORM_CLASS); + self._getContent().addClass(ADDITIONAL_CONTENT_CLASS); + self._getContent().attr(ID_ATTR, CONTENT_ID_VALUE); + var yesBtn = tmpl("okButton", L10nEnum.BUTTON_OK); + var cancelBtn = tmpl("cancelButton", L10nEnum.BUTTON_CANCEL); + self._getFooter().append(cancelBtn); + self._getFooter().append(yesBtn); + var table = new OdinTableMain("table-block", path + odinMetaList, null, path); + self._show(); + + yesBtn.click(function () { + self._hide(); + callBack(table.getSelectedItems()); + }); + cancelBtn.click(function () { + self._hide(); + }); + }; + + initialize(); + } + + function OdinCopyBox(dataUrl, tableRedrawCallback) { + if (isEmpty(dataUrl) || isEmpty(tableRedrawCallback)) { + throw "Odin: Not enough parameters"; + } + + var ADDITIONAL_FORM_CLASS = "odin-simple-form"; + var FROM_VERSION_SELECTOR = "#fromVersion"; + var VERSION_SELECTOR = "#version"; + + OdinFormCommon.call(this); + + var self = this; + + var initialize = function () { + self._setCaption(L10nEnum.CAPTION_COPY_FORM); + self._addFormClass(ADDITIONAL_FORM_CLASS); + self._getContent().append(tmpl("copyForm")); + var from = find(self._getContent(), FROM_VERSION_SELECTOR); + var to = find(self._getContent(), VERSION_SELECTOR); + var yesBtn = tmpl("okButton", L10nEnum.BUTTON_OK); + var cancelBtn = tmpl("cancelButton", L10nEnum.BUTTON_CANCEL); + self._getFooter().append(cancelBtn); + self._getFooter().append(yesBtn); + + /*getFromRest(urlVersions, function (versions) { + if (isEmpty(versions) || versions.count === 0) { + return; + } + var versionsData = []; + versions.items.forEach(function (version) { + versionsData.push({ + id: version.id, + name: version.name + " от " + + new Date(version.date).toLocaleDateString(uiLocale) + }); + }); + fillSelect(from, versionsData.sort(function (a, b) { + return a.id - b.id; + })); + var currentVersion = getCurrentVersionData(); + if (!isEmpty(currentVersion)) { + to.attr(DATA_ATTR, currentVersion.id); + to.val(currentVersion.name); + } + self._show(); + });*/ + + yesBtn.click(function () { + if (isEmpty(from.val()) || isEmpty(to.val())) { + return; + } + if (from.val() === to.attr(DATA_ATTR)) { + showFeedbackMessage(L10nEnum.ERROR_VERSIONS_MATCH, MessageTypesEnum.DANGER); + return; + } + postToRestWithVersionAndParams(dataUrl + odinCopy, null, + "&fromVersionId=" + from.val(), function () { + self._hide(); + tableRedrawCallback(); + }); + }); + cancelBtn.click(function () { + self._hide(); + }); + }; + + initialize(); + } +} diff --git a/src/main/resources/public/js/tasks.js b/src/main/resources/public/js/tasks.js new file mode 100644 index 0000000..6bf160c --- /dev/null +++ b/src/main/resources/public/js/tasks.js @@ -0,0 +1,43 @@ +/*\n' + + ' \n' + + ' '); + } + $('#dataConfirmModal').find('#myModalLabel').text($(this).attr('data-confirm')); + $('#dataConfirmOK').attr('href', href); + $('#dataConfirmModal').modal({show:true}); + return false; + }); + +}); +/*]]>*/ \ No newline at end of file diff --git a/src/main/resources/public/templates/odin.html b/src/main/resources/public/templates/odin.html new file mode 100644 index 0000000..1f9f9d9 --- /dev/null +++ b/src/main/resources/public/templates/odin.html @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/admin/commits.html b/src/main/resources/templates/admin/commits.html index 9b2f115..2f3f58f 100644 --- a/src/main/resources/templates/admin/commits.html +++ b/src/main/resources/templates/admin/commits.html @@ -7,9 +7,13 @@
-
+
+
+
-
+
+
+
+ - \ No newline at end of file + + diff --git a/src/main/resources/templates/conferences/fragments/confDashboardFragment.html b/src/main/resources/templates/conferences/fragments/confDashboardFragment.html new file mode 100644 index 0000000..080946c --- /dev/null +++ b/src/main/resources/templates/conferences/fragments/confDashboardFragment.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+ +
+
+ title +

+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/resources/templates/conferences/fragments/confLineFragment.html b/src/main/resources/templates/conferences/fragments/confLineFragment.html new file mode 100644 index 0000000..f54a777 --- /dev/null +++ b/src/main/resources/templates/conferences/fragments/confLineFragment.html @@ -0,0 +1,23 @@ + + + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/src/main/resources/templates/conferences/fragments/confNavigationFragment.html b/src/main/resources/templates/conferences/fragments/confNavigationFragment.html new file mode 100644 index 0000000..31cc00f --- /dev/null +++ b/src/main/resources/templates/conferences/fragments/confNavigationFragment.html @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 9aae873..00e2c0f 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -23,6 +23,7 @@ + @@ -94,6 +95,10 @@ + + + + diff --git a/src/main/resources/templates/papers/papers.html b/src/main/resources/templates/papers/papers.html index d07ca07..2f2ac42 100644 --- a/src/main/resources/templates/papers/papers.html +++ b/src/main/resources/templates/papers/papers.html @@ -43,6 +43,7 @@ +
diff --git a/src/main/resources/templates/students/dashboard.html b/src/main/resources/templates/students/dashboard.html new file mode 100644 index 0000000..94ea121 --- /dev/null +++ b/src/main/resources/templates/students/dashboard.html @@ -0,0 +1,26 @@ + + + + + +
+
+
+
+

Работа со студентами

+
+
+
+
+
+ + + +
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/students/fragments/taskDashboardFragment.html b/src/main/resources/templates/students/fragments/taskDashboardFragment.html new file mode 100644 index 0000000..0daea58 --- /dev/null +++ b/src/main/resources/templates/students/fragments/taskDashboardFragment.html @@ -0,0 +1,24 @@ + + + + + + +
+
+
+ + +
+
+ + + title +

type

+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/resources/templates/students/fragments/taskLineFragment.html b/src/main/resources/templates/students/fragments/taskLineFragment.html new file mode 100644 index 0000000..79ad5d7 --- /dev/null +++ b/src/main/resources/templates/students/fragments/taskLineFragment.html @@ -0,0 +1,22 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/students/fragments/taskNavigationFragment.html b/src/main/resources/templates/students/fragments/taskNavigationFragment.html new file mode 100644 index 0000000..717930d --- /dev/null +++ b/src/main/resources/templates/students/fragments/taskNavigationFragment.html @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/students/fragments/taskStatusFragment.html b/src/main/resources/templates/students/fragments/taskStatusFragment.html new file mode 100644 index 0000000..8f3d800 --- /dev/null +++ b/src/main/resources/templates/students/fragments/taskStatusFragment.html @@ -0,0 +1,38 @@ + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/students/task.html b/src/main/resources/templates/students/task.html new file mode 100644 index 0000000..533c8f6 --- /dev/null +++ b/src/main/resources/templates/students/task.html @@ -0,0 +1,118 @@ + + + + + + + + +
+ +
+
+
+
+

Редактирование задачи

+
+
+
+
+
+
+
+
+
+ +
+ + +

+
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+
+ + +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
Дата создания:
+
+
+ + + text + +
+
+
+
+
+
+
Дата изменения:
+
+
+ + + text + +
+
+
+
+
+ +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/students/tasks.html b/src/main/resources/templates/students/tasks.html new file mode 100644 index 0000000..076f7ba --- /dev/null +++ b/src/main/resources/templates/students/tasks.html @@ -0,0 +1,66 @@ + + + + + + + +
+
+ +
+
+
+
+

Работа со студентами

+
+
+
+
+
+
+ +
+ +
+
+
+
Фильтр:
+ + + +
+
+
+
+
+ +
+ + +
+ + \ No newline at end of file