<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/lis-app/src/main/java" charset="UTF-8" />
+ <file url="file://$PROJECT_DIR$/lis-app/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/lis-db/src/main/java" charset="UTF-8" />
+ <file url="file://$PROJECT_DIR$/lis-db/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/lis-services/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/lis-ui/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/lis-ui/src/main/resources" charset="UTF-8" />
##### ZK
+https://www.zkoss.org/documentation#References
https://www.zkoss.org/wiki/ZK_Configuration_Reference/zk.xml/The_Library_Properties
https://www.zkoss.org/wiki/ZK_Developer%27s_Reference/Performance_Tips
https://www.zkoss.org/wiki/ZK%20Developer%27s%20Reference/Performance%20Tips/Listbox,%20Grid%20and%20Tree%20for%20Huge%20Data/Implement%20ListModel%20and%20TreeModel
https://www.zkoss.org/wiki/ZK_Client-side_Reference/General_Control/Client-side_selection_of_elements_and_widgets
https://www.zkoss.org/wiki/ZK_Developer%27s_Reference/Testing/Testing_Tips
https://www.zkoss.org/wiki/Small_Talks/2013/October/ZK_Testing_with_Sahi
+https://zkfiddle.org/sample/3ltrsms/9-Grid-style-7-1
+https://zkfiddle.org/sample/3bmc52p/1-detect-dark-mode
##### Spring ZK
logging:
level:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper: ERROR
-# org.springframework.security: DEBUG
+hu:
+ user-ibm:
+ sly-crm:
+ ui:
+ user-name: user
+ password: password
# org.springframework.security.web: INFO
# pattern:
# console: "%d %-5level %logger : %msg%n"
DOCKER
-docker run -itd --name lis --privileged=true -p 50000:50000 -p 27017:27017 -e LICENSE=accept -e DB2INSTANCE=db2admin -e DB2INST1_PASSWORD=password -e DBNAME=lis -e PERSISTENT_HOME=true -v /Docker:/database ibmcom/db2
+docker run -itd --name lis --privileged=true -p 50000:50000 -e LICENSE=accept -e DB2INSTANCE=db2admin -e DB2INST1_PASSWORD=password -e DBNAME=lis -e PERSISTENT_HOME=true -v /Docker:/database ibmcom/db2
docker logs -f lis
docker exec -it lis bash
docker stop lis
docker remove lis
+
+MIGRATE
+migrate new create profile --idpattern=000
--- /dev/null
+-- // create profile
+-- Migration SQL that makes the change goes here.
+
+CREATE TABLE profile (
+ id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ login VARCHAR(255),
+ type VARCHAR(255),
+ setting CLOB,
+ CONSTRAINT pk_profile PRIMARY KEY (id)
+);
+CREATE UNIQUE INDEX UDX_PROFILE_LOGIN_TYPE ON PROFILE(LOGIN, TYPE);
+
+-- //@UNDO
+-- SQL to undo the change goes here.
+DROP TABLE profile;
+
--- /dev/null
+package hu.user.lis.db;
+
+import lombok.*;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+@Getter
+@Setter
+@Entity
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Profile implements Serializable {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ Long id;
+ String login;
+ String type;
+ String setting;
+}
--- /dev/null
+package hu.user.lis.db.repository;
+
+import hu.user.lis.db.Profile;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface ProfileRepository extends JpaRepository<Profile, Long> {
+
+ Optional<Profile> findByLoginAndType(String login, String type);
+
+ List<Profile> findAllByLogin(String login);
+
+ void deleteAllByLogin(String login);
+
+}
return result;
}
+ public T fromJSON(String data, Class<T> objectClass) {
+ T result = null;
+ try {
+ result = (T) objectMapper.readValue(data, objectClass);
+ } catch (JsonProcessingException e) {
+ log.catching(e);
+ }
+ return result;
+ }
+
public boolean areEquals(T entity1, T entity2) {
boolean result = true;
String json1 = toJSON(entity1);
--- /dev/null
+package hu.user.lis.ui;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Getter
+@Setter
+@Component
+@ConfigurationProperties(prefix = "hu.user-ibm.sly-crm.ui")
+public class SlyCrmUIProperties {
+ String userName;
+ String password;
+}
package hu.user.lis.ui.auth;
import hu.user.lis.db.Associate;
+import hu.user.lis.db.Profile;
+import hu.user.lis.db.repository.ProfileRepository;
import lombok.Getter;
-import lombok.Setter;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
@Service
-@Getter
-@Setter
public class CurrentProfile {
+ @Autowired
+ ProfileRepository profileRepository;
+ @Getter
+ Associate associate;
+
+ @Getter
+ Map<String, Profile> settings = new HashMap<>();
+
+ public void setAssociate(Associate associate) {
+ this.associate = associate;
+ loadSettings();
+ }
+
+ private void loadSettings() {
+ List<Profile> profileSettings = profileRepository.findAllByLogin(associate.getLogin());
+ settings = profileSettings.stream().collect(Collectors.toMap(Profile::getType, p -> p));
+ }
- private Associate associate;
+ public Profile getSetting(String type) {
+ return settings.get(type);
+ }
-
+ public void addSetting(Profile columnProfile) {
+ Profile existing = settings.get(columnProfile.getType());
+ if (Objects.nonNull(existing)) {
+ columnProfile.setId(existing.getId());
+ }
+ settings.put(columnProfile.getType(), columnProfile);
+ profileRepository.save(columnProfile);
+ }
}
package hu.user.lis.ui.data;
+import hu.user.lis.db.Profile;
+import hu.user.lis.services.data.EntityDataService;
+import hu.user.lis.ui.auth.CurrentProfile;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.zkoss.json.JSONObject;
import org.zkoss.zul.FieldComparator;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Objects;
@Component
@Getter
@Setter
- JSONObject cols = new JSONObject();
+ JSONObject columnSettings = new JSONObject();
- public void addColumn(String name, String direction) {
+ @Autowired
+ CurrentProfile currentProfile;
+
+ @Autowired
+ EntityDataService<JSONObject> entityDataService;
+
+ public void addColumns(Map<String, String> columns) {
+ Profile profile = currentProfile.getSetting(getClass().getSimpleName());
+ if (Objects.isNull(profile)) {
+ columns.keySet().forEach(colName -> addColumn(colName, columns.get(colName)));
+ saveProfileSetting();
+ } else {
+ columnSettings = entityDataService.fromJSON(profile.getSetting(), JSONObject.class);
+ }
+ }
+
+ private void saveProfileSetting() {
+ Profile columnProfile = Profile.builder()
+ .login(currentProfile.getAssociate().getLogin())
+ .type(getClass().getSimpleName())
+ .setting(entityDataService.toJSON(columnSettings))
+ .build();
+ currentProfile.addSetting(columnProfile);
+ }
+
+ private void addColumn(String name, String direction) {
JSONObject sort = new JSONObject();
sort.put("sortDirection", direction);
- cols.put(name, sort);
+ columnSettings.put(name, sort);
if (!direction.equals(NATURAL)) {
setSortComparator(new FieldComparator(name, direction.equals(ASCENDING)));
log.info("{} {}", getClass().getSimpleName(), pageable);
return pageable;
}
+
+ @Override
+ public void sort(Comparator<T> cmpr, boolean ascending) {
+ super.sort(cmpr, ascending);
+
+ FieldComparator sortComparator = (FieldComparator) cmpr;
+ columnSettings.keySet().forEach(colName -> {
+ LinkedHashMap<String, String> col = (LinkedHashMap<String, String>) columnSettings.get(colName);
+ if (colName.equals(sortComparator.getRawOrderBy())) {
+ col.put("sortDirection", ascending ? ASCENDING : DESCENDING);
+ } else {
+ col.put("sortDirection", NATURAL);
+ }
+ });
+ saveProfileSetting();
+ log.info("Sort settings for {} : {}", getClass().getSimpleName(), columnSettings.toJSONString());
+ }
+
}
package hu.user.lis.ui.view;
+import com.google.common.collect.ImmutableMap;
import hu.user.lis.db.Associate;
import hu.user.lis.ui.Constants;
import hu.user.lis.ui.data.AssociatesDataModel;
@Init
public void init() {
super.init();
- addColumn("name", ASCENDING);
- addColumn("login", NATURAL);
- addColumn("active", NATURAL);
+ addColumns(ImmutableMap.of(
+ "name", ASCENDING,
+ "login", NATURAL,
+ "active", NATURAL
+ ));
}
package hu.user.lis.ui.view;
+import hu.user.lis.ui.SlyCrmUIProperties;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.info.BuildProperties;
@WireVariable
BuildProperties buildProperties;
+ @WireVariable
+ SlyCrmUIProperties slyCrmUIProperties;
+
public LoginViewModel() {
}
package hu.user.lis.ui.view;
+import com.google.common.collect.ImmutableMap;
import hu.user.lis.db.Partner;
import hu.user.lis.ui.Constants;
import hu.user.lis.ui.data.CachedSpringDataModel;
@Init
public void init() {
super.init();
- addColumn("name", ASCENDING);
- addColumn("vatNr", NATURAL);
- addColumn("address", NATURAL);
- addColumn("active", NATURAL);
+ addColumns(ImmutableMap.of(
+ "name", ASCENDING,
+ "vatNr", NATURAL,
+ "address", NATURAL,
+ "active", NATURAL
+ ));
}
protected void refresh() {
package hu.user.lis.ui.view;
+import com.google.common.collect.ImmutableMap;
import hu.user.lis.db.Project;
import hu.user.lis.ui.Constants;
import hu.user.lis.ui.data.CachedSpringDataModel;
public void init() {
super.init();
eventBus.register(this);
- addColumn("humanId", ASCENDING);
- addColumn("partner.name", NATURAL);
- addColumn("projectStatus.name", NATURAL);
- addColumn("name", NATURAL);
- addColumn("contactName", NATURAL);
- addColumn("active", NATURAL);
+ addColumns(ImmutableMap.of(
+ "humanId", ASCENDING,
+ "partner.name", NATURAL,
+ "projectStatus.name", NATURAL,
+ "name", NATURAL,
+ "contactName", NATURAL,
+ "active", NATURAL
+ ));
}
protected void refresh() {
package hu.user.lis.ui.view;
+import com.google.common.collect.ImmutableMap;
import hu.user.lis.db.Associate;
import hu.user.lis.db.Project;
import hu.user.lis.db.ServiceRecord;
super.init();
eventBus.register(this);
eventBus.registerForBinding(this);
- addColumn("project.humanId", ASCENDING);
- addColumn("project.name", NATURAL);
- addColumn("project.partner.name", NATURAL);
- addColumn("associate.name", NATURAL);
- addColumn("workDay", NATURAL);
- addColumn("description", NATURAL);
- addColumn("workHours", NATURAL);
+ addColumns(ImmutableMap.of(
+ "project.humanId", ASCENDING,
+ "project.name", NATURAL,
+ "project.partner.name", NATURAL,
+ "associate.name", NATURAL,
+ "workDay", NATURAL,
+ "description", NATURAL,
+ "workHours", NATURAL
+ ));
}
@AfterCompose
import org.zkoss.zkplus.spring.DelegatingVariableResolver;
import java.io.Serializable;
+import java.util.Map;
import java.util.Set;
@WireVariable
EntityDataService<T> entityDataService;
- protected void addColumn(String name, String direction) {
- getDataModel().addColumn(name, direction);
+ protected void addColumns(Map<String, String> columns) {
+ getDataModel().addColumns(columns);
}
public JSONObject getCols() {
- return getDataModel().getCols();
+ return getDataModel().getColumnSettings();
}
-
+
abstract protected CachedSpringDataModel<T> getDataModel();
@AfterCompose
<tabpanels>
<tabpanel>
<vlayout hflex="true">
+
<label value="Név"/>
<textbox hflex="true" instant="true" value="@bind(vm.formDocument.name) @validator(vm)"
forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+ <label value="@load(self.previousSibling)"/>
+ <!-- <label value="@bind(vmsgs[self.previousSibling])"/>-->
+
<label value="Login"/>
<textbox hflex="true" instant="true" value="@bind(vm.formDocument.login) @validator(vm)"
forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
<zk>
<window id="partnerPopup" width="60%" height="400px" closable="true"
- viewModel="@id('vm') @init('hu.user.lis.ui.editor.PartnerEditorModel')">
+ viewModel="@id('vm') @init('hu.user.lis.ui.editor.PartnerEditorModel')" validationMessages="@id('vmsgs')">
<caption label="Partner szerkesztés"/>
<!-- <w:script type="text/javascript" src="~./static/js/cleave.min.js"/>-->
<borderlayout>
<?component name="entity-selector" inline="true" class="hu.user.lis.ui.editor.widget.EntitySelector"?>
<zk>
<window id="projectEditor" hflex="true" vflex="true"
- viewModel="@id('vm') @init('hu.user.lis.ui.editor.ProjectEditorModel')"
- validationMessages="@id('vmsgs')">
+ viewModel="@id('vm') @init('hu.user.lis.ui.editor.ProjectEditorModel')">
<caption label="Projekt szerkesztés"/>
<borderlayout>
<center id="centerPanel" border="none" vflex="true" hflex="true" autoscroll="true">
<textbox instant="true" width="100%"
value="@bind(vm.formDocument.contactName) @validator(vm)"
forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
- <label value="@bind(vmsgs[self.previousSibling])"/>
</vlayout>
</row>
<row>
<rows>
<row>
<label value="User"/>
- <textbox name="username" hflex="true"/>
+ <textbox name="username" hflex="true" value="@load(vm.slyCrmUIProperties.userName)"/>
</row>
<row>
<label value="Password"/>
- <textbox type="password" name="password" hflex="true"/>
+ <textbox type="password" name="password" hflex="true"
+ value="@load(vm.slyCrmUIProperties.password)"/>
</row>
<row spans="2" align="right">
<hlayout>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-collections4</artifactId>
+ <version>4.4</version>
+ </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>