From b3a3cf5ec895fc8268a78002aa5f49759fcebdeb Mon Sep 17 00:00:00 2001 From: Donghuang Date: Sat, 18 Jun 2022 16:05:31 +0800 Subject: [PATCH] add websocket push --- server/crm/pom.xml | 4 + .../ambition/crm/auth/AuthRealmSupport.java | 6 +- .../controller/BaseController.java | 3 +- .../controller/BaseControllerAdvice.java | 2 +- .../controller/BaseCruController.java | 3 +- .../controller/BaseCrudController.java | 2 +- .../controller/BaseQueryController.java | 7 +- .../crm/common/request/BaseListCtrlrReq.java | 21 +++ .../controller/AbstractBaseController.java | 2 +- .../crm/controller/ApplicationController.java | 1 + .../crm/controller/AuthController.java | 37 ++-- .../crm/controller/CustomerController.java | 12 ++ .../controller/CustomerIssueController.java | 2 + .../CustomerPropertyController.java | 2 + .../CustomerYearToDateSaleController.java | 2 + .../crm/controller/ExportTaskController.java | 69 ++++++++ .../crm/controller/HomePageController.java | 2 + .../controller/ImportRecordController.java | 4 +- .../controller/LocalProductController.java | 17 +- .../crm/controller/UserController.java | 2 + .../crm/controller/WeekGoalController.java | 2 + .../crm/service/ExportTaskService.java | 16 +- .../support/ExportTaskServiceSupport.java | 76 ++++++++- .../ambition/crm/util/FileDownloadUtils.java | 26 +-- .../ambition/crm/ws/model/BaseWsResp.java | 23 +++ .../crm/ws/model/ExportTaskUpdatedWsResp.java | 29 ++++ .../crm/ws/service/WebSocketService.java | 15 +- .../ws/service/impl/WebSocketServiceImpl.java | 11 ++ server/lib/tigon | 2 +- .../java/com/pudonghot/ambition/crm/Test.java | 4 + .../ambition/crm/mapper/ExportTaskMapper.xml | 12 ++ .../ambition/crm/model/BaseDbModel.java | 43 ++++- .../ambition/crm/model/ExportTask.java | 7 +- .../ambition/crm/model/FileInfo.java | 2 + .../pudonghot/ambition/crm/model/User.java | 4 +- web/app/services/websocket.js | 70 +++++--- web/ember-cli-build.js | 3 +- web/package.json | 158 +++++++++--------- 38 files changed, 532 insertions(+), 171 deletions(-) rename server/crm/src/main/java/com/pudonghot/ambition/crm/{ => common}/controller/BaseController.java (86%) rename server/crm/src/main/java/com/pudonghot/ambition/crm/{ => common}/controller/BaseControllerAdvice.java (96%) rename server/crm/src/main/java/com/pudonghot/ambition/crm/{ => common}/controller/BaseCruController.java (95%) rename server/crm/src/main/java/com/pudonghot/ambition/crm/{ => common}/controller/BaseCrudController.java (94%) rename server/crm/src/main/java/com/pudonghot/ambition/crm/{ => common}/controller/BaseQueryController.java (93%) create mode 100644 server/crm/src/main/java/com/pudonghot/ambition/crm/common/request/BaseListCtrlrReq.java create mode 100644 server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ExportTaskController.java create mode 100644 server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/BaseWsResp.java create mode 100644 server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskUpdatedWsResp.java create mode 100644 server/mapper/src/main/java/com/pudonghot/ambition/crm/Test.java create mode 100644 server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ExportTaskMapper.xml diff --git a/server/crm/pom.xml b/server/crm/pom.xml index 09f9ae2..8eb5f04 100644 --- a/server/crm/pom.xml +++ b/server/crm/pom.xml @@ -29,6 +29,10 @@ + + me.chyxion.tigon + tigon-web-controller + org.springframework.boot diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/auth/AuthRealmSupport.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/auth/AuthRealmSupport.java index 1f95516..092a828 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/auth/AuthRealmSupport.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/auth/AuthRealmSupport.java @@ -2,7 +2,7 @@ package com.pudonghot.ambition.crm.auth; import lombok.val; import java.util.*; -import me.chyxion.tigon.mybatis.Search; + import me.chyxion.tigon.model.ViewModel; import me.chyxion.tigon.shiro.AuthRealm; import org.apache.commons.lang3.ArrayUtils; @@ -62,13 +62,13 @@ public class AuthRealmSupport implements AuthRealm { */ @Override public Collection roles(final Principal principal) { - val user = userService.find(new Search(User.EMPLOYEE_ID, principal)); + val user = userService.find(principal.getUserId()); val roles = new ArrayList(4); if (user.isAdmin()) { roles.add(User.ROLE_ADMIN); } val account = user.getAccount(); - if (ArrayUtils.contains(new String[] {User.ROLE_LELI, User.ROLE_CHYXION}, account)) { + if (ArrayUtils.contains(new String[] {User.ROLE_LELI, User.ROLE_DONGHUANG}, account)) { roles.add(account); } return roles; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseController.java similarity index 86% rename from server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseController.java rename to server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseController.java index 08a5cbb..1a92b01 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseController.java @@ -1,5 +1,6 @@ -package com.pudonghot.ambition.crm.controller; +package com.pudonghot.ambition.crm.common.controller; +import com.pudonghot.ambition.crm.controller.AbstractBaseController; import me.chyxion.tigon.model.ViewModel; import com.pudonghot.ambition.crm.model.User; import me.chyxion.tigon.shiro.service.AuthService; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseControllerAdvice.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseControllerAdvice.java similarity index 96% rename from server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseControllerAdvice.java rename to server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseControllerAdvice.java index 0f58170..14459ff 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseControllerAdvice.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseControllerAdvice.java @@ -1,4 +1,4 @@ -package com.pudonghot.ambition.crm.controller; +package com.pudonghot.ambition.crm.common.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.core.annotation.Order; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseCruController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseCruController.java similarity index 95% rename from server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseCruController.java rename to server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseCruController.java index 2b547d5..9ab74a4 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseCruController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseCruController.java @@ -1,6 +1,7 @@ -package com.pudonghot.ambition.crm.controller; +package com.pudonghot.ambition.crm.common.controller; import javax.validation.Valid; + import me.chyxion.tigon.form.FC2; import me.chyxion.tigon.model.M0; import me.chyxion.tigon.model.ViewModel; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseCrudController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseCrudController.java similarity index 94% rename from server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseCrudController.java rename to server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseCrudController.java index 32480f1..a4b5f40 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseCrudController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseCrudController.java @@ -1,4 +1,4 @@ -package com.pudonghot.ambition.crm.controller; +package com.pudonghot.ambition.crm.common.controller; import me.chyxion.tigon.form.FC2; import me.chyxion.tigon.model.M0; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseQueryController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseQueryController.java similarity index 93% rename from server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseQueryController.java rename to server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseQueryController.java index db48590..d43840b 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/BaseQueryController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/controller/BaseQueryController.java @@ -1,7 +1,7 @@ -package com.pudonghot.ambition.crm.controller; +package com.pudonghot.ambition.crm.common.controller; +import com.pudonghot.ambition.crm.common.controller.BaseController; import lombok.extern.slf4j.Slf4j; -import me.chyxion.tigon.model.M0; import me.chyxion.tigon.mybatis.Search; import me.chyxion.tigon.model.ViewModel; import me.chyxion.tigon.model.ListResult; @@ -19,8 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping; * May 10, 2016 4:50:58 PM */ @Slf4j -public class BaseQueryController> - extends BaseController { +public class BaseQueryController extends BaseController { @Autowired protected BaseQueryService queryService; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/common/request/BaseListCtrlrReq.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/request/BaseListCtrlrReq.java new file mode 100644 index 0000000..7726072 --- /dev/null +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/common/request/BaseListCtrlrReq.java @@ -0,0 +1,21 @@ +package com.pudonghot.ambition.crm.common.request; + +import lombok.Getter; +import lombok.Setter; +import me.chyxion.tigon.web.controller2.request.BaseListCtrlrReqApi; + +/** + * @author Donghuang + * @date Jun 18, 2022 13:27:22 + */ +@Getter +@Setter +public class BaseListCtrlrReq implements BaseListCtrlrReqApi { + private static final long serialVersionUID = 1L; + + private Integer start; + private Integer limit; + private String search; + private String filters; + private String orders; +} diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AbstractBaseController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AbstractBaseController.java index e4242cc..2b68705 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AbstractBaseController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AbstractBaseController.java @@ -177,7 +177,7 @@ public abstract class AbstractBaseController { } if (StringUtils.isNotBlank(strSearch)) { val orSearch = new Search(); - for (final String col : searchCols()) { + for (val col : searchCols()) { orSearch.or(new Search().like(col, decodeLike(strSearch))); } search.and(orSearch); diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java index e0f99ec..0ed4dbc 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java @@ -1,5 +1,6 @@ package com.pudonghot.ambition.crm.controller; +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import lombok.val; import java.util.List; import java.util.Arrays; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AuthController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AuthController.java index d1a1902..2fbcaf8 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AuthController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/AuthController.java @@ -1,20 +1,19 @@ package com.pudonghot.ambition.crm.controller; +import lombok.val; +import org.apache.shiro.SecurityUtils; +import me.chyxion.tigon.mybatis.Search; +import org.springframework.util.Assert; +import me.chyxion.tigon.model.ViewModel; +import com.pudonghot.ambition.crm.model.User; +import javax.validation.constraints.NotBlank; +import me.chyxion.tigon.kit.bean.BeanService; +import org.springframework.stereotype.Controller; +import me.chyxion.tigon.shiro.service.AuthService; +import com.pudonghot.ambition.crm.service.UserService; import com.pudonghot.ambition.crm.auth.SessionAbility; import com.pudonghot.ambition.crm.auth.model.AuthToken; import com.pudonghot.ambition.crm.auth.model.Principal; -import lombok.val; -import me.chyxion.tigon.kit.bean.BeanService; -import me.chyxion.tigon.mybatis.Search; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.util.Assert; -import me.chyxion.tigon.model.ViewModel; -import com.pudonghot.ambition.crm.model.User; -import org.springframework.stereotype.Controller; -import me.chyxion.tigon.shiro.service.AuthService; -import javax.validation.constraints.NotBlank; -import com.pudonghot.ambition.crm.service.UserService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestMethod; @@ -45,8 +44,10 @@ public class AuthController implements SessionAbility { @RequestParam("password") String password) { - val user = userService.find(new Search(User.ACCOUNT, loginId)); - Assert.state(user != null, "Unknown account"); + val user = findUser(loginId); + Assert.state(user != null, () -> "Incorrect account or password"); + Assert.state(user.getEnabled(), "Account is disabled, please contact admin"); + val principal = new Principal(); principal.setAccount(loginId); principal.setUserId(user.getId()); @@ -69,4 +70,12 @@ public class AuthController implements SessionAbility { public ViewModel info() { return userService.findViewModel(getUserId()); } + + User findUser(final String loginId) { + val user = userService.find(new Search(User.ACCOUNT, loginId)); + if (user != null) { + return user; + } + return userService.find(new Search(User.EMPLOYEE_ID, loginId)); + } } diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerController.java index dd026f3..3028ec4 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerController.java @@ -1,5 +1,7 @@ package com.pudonghot.ambition.crm.controller; +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; +import com.pudonghot.ambition.crm.service.ExportTaskService; import lombok.val; import java.util.*; import javax.validation.Valid; @@ -14,6 +16,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import org.apache.commons.lang3.StringUtils; import com.pudonghot.ambition.crm.model.User; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import com.pudonghot.ambition.crm.model.Customer; @@ -107,6 +110,9 @@ public class CustomerController Pair.of(CRITERION_COLS.get("issue"), Boolean.class)); } + @Autowired + private ExportTaskService exportTaskService; + @RequestMapping("/list") public ListResult> list( @Min(0) @@ -164,6 +170,12 @@ public class CustomerController return FileDownloadUtils.toResponseEntity(((CustomerService) queryService).exportCSV(getUserId()), null); } + @RequiresRoles(User.ROLE_ADMIN) + @RequestMapping("/async-export") + public void asyncExportCSV() { + exportTaskService.doExport(getUserId()); + } + @RequiresRoles(User.ROLE_ADMIN) @PostMapping("/delete") public void delete(@NotBlank @RequestParam("id") String id) { diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerIssueController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerIssueController.java index fef8db9..b8d80af 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerIssueController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerIssueController.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Arrays; import javax.validation.Valid; import javax.validation.constraints.Max; + +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import me.chyxion.tigon.model.ViewModel; import javax.validation.constraints.Min; import me.chyxion.tigon.model.ListResult; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerPropertyController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerPropertyController.java index c52dc1a..dd32780 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerPropertyController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerPropertyController.java @@ -3,6 +3,8 @@ package com.pudonghot.ambition.crm.controller; import java.util.List; import java.util.Arrays; import javax.validation.Valid; + +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import me.chyxion.tigon.mybatis.Search; import javax.validation.constraints.Max; import javax.validation.constraints.Min; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerYearToDateSaleController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerYearToDateSaleController.java index f6a8426..a5993e3 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerYearToDateSaleController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/CustomerYearToDateSaleController.java @@ -1,6 +1,8 @@ package com.pudonghot.ambition.crm.controller; import javax.validation.constraints.NotNull; + +import com.pudonghot.ambition.crm.common.controller.BaseController; import com.pudonghot.ambition.crm.model.User; import org.springframework.stereotype.Controller; import org.springframework.web.multipart.MultipartFile; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ExportTaskController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ExportTaskController.java new file mode 100644 index 0000000..e3191aa --- /dev/null +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ExportTaskController.java @@ -0,0 +1,69 @@ +package com.pudonghot.ambition.crm.controller; + +import lombok.val; +import javax.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import me.chyxion.tigon.mybatis.Search; +import com.pudonghot.ambition.crm.model.User; +import me.chyxion.tigon.web.controller2.ArgQuery; +import org.springframework.stereotype.Controller; +import com.pudonghot.ambition.crm.model.ExportTask; +import com.pudonghot.ambition.crm.auth.SessionAbility; +import org.apache.shiro.authz.annotation.RequiresRoles; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import me.chyxion.tigon.web.controller2.BaseQueryController; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.beans.factory.annotation.Autowired; +import com.pudonghot.ambition.crm.ws.service.WebSocketService; +import me.chyxion.tigon.web.controller2.response.ListCtrlrResp; +import com.pudonghot.ambition.crm.common.request.BaseListCtrlrReq; +import com.pudonghot.ambition.crm.ws.model.ExportTaskUpdatedWsResp; + +/** + * @author Donghuang + * @date Jun 18, 2022 09:47:30 + */ +@Slf4j +@Controller +@RequestMapping("/export-task") +public class ExportTaskController + extends BaseQueryController + implements SessionAbility { + + /** + * {@inheritDoc} + */ + @Override + @RequiresRoles(User.ROLE_ADMIN) + public ListCtrlrResp list(@Valid final BaseListCtrlrReq req) { + return list(req, new Search()); + } + + + /** + * {@inheritDoc} + */ + @Override + protected void before(final ArgQuery arg) { + super.before(arg); + val search = arg.getSearch(); + search.eq(ExportTask.CREATED_BY, getUserId()); + if (arg.getType() == ArgQuery.Type.LIST) { + search.desc(ExportTask.DATE_CREATED); + } + } + + @Autowired + private WebSocketService webSocketService; + + @PostMapping("/test-push") + @RequiresRoles(User.ROLE_ADMIN) + public void testPush(@RequestBody ExportTaskUpdatedWsResp resp) { + resp.setEmployeeKey(getUserId()); + webSocketService.publish(resp); + } +} diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/HomePageController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/HomePageController.java index af2f5f1..662b164 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/HomePageController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/HomePageController.java @@ -1,6 +1,8 @@ package com.pudonghot.ambition.crm.controller; import javax.validation.Valid; + +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import lombok.extern.slf4j.Slf4j; import javax.validation.constraints.Max; import javax.validation.constraints.Min; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ImportRecordController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ImportRecordController.java index 124ec4b..af9abae 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ImportRecordController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ImportRecordController.java @@ -2,6 +2,8 @@ package com.pudonghot.ambition.crm.controller; import java.util.List; import java.util.Arrays; + +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import lombok.extern.slf4j.Slf4j; import me.chyxion.tigon.model.ViewModel; import javax.validation.constraints.Max; @@ -30,7 +32,7 @@ public class ImportRecordController "u.name", "u.en_name", "u.account", - "u.employee_id" ); + "u.employee_id"); @RequestMapping("/list") @RequiresRoles(User.ROLE_ADMIN) diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/LocalProductController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/LocalProductController.java index 737e59b..5201db7 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/LocalProductController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/LocalProductController.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Arrays; import javax.validation.Valid; +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import lombok.val; import org.springframework.util.Assert; import me.chyxion.tigon.mybatis.Search; @@ -71,14 +72,14 @@ public class LocalProductController return result; } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/create", method = RequestMethod.POST) public void create( @Valid LocalProductFormForCreate form) { ((LocalProductService) queryService).create(form); } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/update", method = RequestMethod.POST) public void update( @Valid LocalProductFormForUpdate form) { @@ -98,7 +99,7 @@ public class LocalProductController return viewModel; } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/add-image", method = RequestMethod.POST) public ViewModel addImage( @Valid LocalProductImageFormForCreate form) { @@ -106,19 +107,19 @@ public class LocalProductController return new ViewModel<>(((LocalProductService) queryService).addImage(form)); } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/remove-image", method = RequestMethod.POST) public void removeImage(@NotBlank @RequestParam("id") String id) { ((LocalProductService) queryService).removeImage(id); } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/update-image", method = RequestMethod.POST) public void updateImage(@Valid LocalProductImageFormForUpdate form) { ((LocalProductService) queryService).updateImage(form); } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/add-attachment", method = RequestMethod.POST) public ViewModel addAttachment( @Valid LocalProductAttachedFileFormForCreate form) { @@ -131,13 +132,13 @@ public class LocalProductController ((LocalProductService) queryService).removeAttachment(id); } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/update-attachment", method = RequestMethod.POST) public void updateImage(@Valid LocalProductAttachedFileFormForUpdate form) { ((LocalProductService) queryService).updateAttachment(form); } - @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR) + @RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR) @RequestMapping(value = "/delete", method = RequestMethod.POST) public void delete(@NotBlank @RequestParam("id") String id) { ((LocalProductService) queryService).delete(id); diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/UserController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/UserController.java index 486071e..df831ef 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/UserController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/UserController.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.Arrays; import java.util.HashMap; import javax.validation.Valid; + +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import me.chyxion.tigon.mybatis.Search; import javax.validation.constraints.Max; import javax.validation.constraints.Min; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/WeekGoalController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/WeekGoalController.java index 7fc7dae..900a702 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/WeekGoalController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/WeekGoalController.java @@ -1,6 +1,8 @@ package com.pudonghot.ambition.crm.controller; import java.util.*; + +import com.pudonghot.ambition.crm.common.controller.BaseQueryController; import lombok.val; import javax.validation.Valid; import lombok.extern.slf4j.Slf4j; diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ExportTaskService.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ExportTaskService.java index 73cd68e..777a9dc 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ExportTaskService.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ExportTaskService.java @@ -1,6 +1,9 @@ package com.pudonghot.ambition.crm.service; import javax.validation.constraints.NotBlank; + +import com.pudonghot.ambition.crm.model.ExportTask; +import me.chyxion.tigon.service2.BaseQueryService; import org.springframework.validation.annotation.Validated; /** @@ -8,13 +11,20 @@ import org.springframework.validation.annotation.Validated; * @date May 29, 2022 21:24:42 */ @Validated -public interface ExportTaskService { +public interface ExportTaskService extends BaseQueryService { /** * do export * - * @param operator + * @param employeeKey employee key */ - void doExport(@NotBlank String operator); + void doExport(@NotBlank String employeeKey); + + /** + * notify task updated + * + * @param employeeKey employee key + */ + void notifyTaskUpdated(@NotBlank String employeeKey); } diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ExportTaskServiceSupport.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ExportTaskServiceSupport.java index 9f0eaa8..ae62e84 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ExportTaskServiceSupport.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ExportTaskServiceSupport.java @@ -1,32 +1,102 @@ package com.pudonghot.ambition.crm.service.support; import lombok.val; +import java.io.File; +import java.util.Date; +import lombok.extern.slf4j.Slf4j; +import me.chyxion.tigon.mybatis.Search; +import org.apache.commons.io.FileUtils; +import org.springframework.util.Assert; +import java.util.concurrent.ConcurrentMap; import org.springframework.stereotype.Service; +import java.util.concurrent.ConcurrentHashMap; +import com.pudonghot.ambition.crm.model.ExportTask; import org.springframework.core.task.TaskExecutor; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.beans.factory.annotation.Value; +import com.pudonghot.ambition.crm.mapper.ExportTaskMapper; import com.pudonghot.ambition.crm.service.CustomerService; import com.pudonghot.ambition.crm.service.ExportTaskService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Autowired; +import com.pudonghot.ambition.crm.ws.service.WebSocketService; +import me.chyxion.tigon.service.support2.BaseQueryServiceSupport; +import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus; +import com.pudonghot.ambition.crm.ws.model.ExportTaskUpdatedWsResp; /** * @author Donghuang * @date May 29, 2022 21:29:06 */ +@Slf4j @Service -public class ExportTaskServiceSupport implements ExportTaskService { +public class ExportTaskServiceSupport + extends BaseQueryServiceSupport + implements ExportTaskService { + + private final ConcurrentMap LOCK_MAP = new ConcurrentHashMap<>(); + @Autowired @Qualifier("exportTaskExecutor") private TaskExecutor threadPoolTaskExecutor; @Autowired private CustomerService customerService; + @Value("${export.location:/data/export}") + private String exportLocation; + @Autowired + private WebSocketService webSocketService; /** * {@inheritDoc} */ @Override - public void doExport(final String operator) { + public void doExport(final String employeeKey) { + val now = Long.valueOf(System.currentTimeMillis()); + Assert.state(now.equals(LOCK_MAP.putIfAbsent(employeeKey, now)), + "There is a running export task, please try again later!"); + threadPoolTaskExecutor.execute(() ->{ - val exportFile = customerService.exportCSV(operator); + try { + val exportTask = new ExportTask(); + exportTask.setCreatedBy(employeeKey); + exportTask.setDateCreated(new Date()); + exportTask.setStatus(EnumExportTaskStatus.RUNNING); + mapper.insert(exportTask); + + try { + val exportFile = customerService.exportCSV(employeeKey); + val distDir = new File(new File(exportLocation), + DateFormatUtils.format(now, "yyyyMMdd")); + FileUtils.moveFileToDirectory(exportFile, distDir, true); + exportTask.setStatus(EnumExportTaskStatus.DONE); + exportTask.setLocation(new File(distDir, exportFile.getName()).getPath()); + exportTask.setDateUpdated(new Date()); + mapper.update(exportTask); + } catch (final Throwable e) { + log.error("Export file error caused.", e); + exportTask.setStatus(EnumExportTaskStatus.FAILED); + exportTask.setNote(ExceptionUtils.getStackTrace(e)); + exportTask.setDateUpdated(new Date()); + mapper.update(exportTask); + } + + notifyTaskUpdated(employeeKey); + } + finally { + LOCK_MAP.remove(employeeKey); + } }); } + + /** + * {@inheritDoc} + */ + @Override + public void notifyTaskUpdated(final String employeeKey) { + webSocketService.publish( + new ExportTaskUpdatedWsResp(employeeKey, + mapper.count(new Search(ExportTask.CREATED_BY, employeeKey) + .isFalse(ExportTask.DOWNLOADED)))); + } } diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/util/FileDownloadUtils.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/util/FileDownloadUtils.java index c3f31ff..48633a6 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/util/FileDownloadUtils.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/util/FileDownloadUtils.java @@ -1,25 +1,16 @@ package com.pudonghot.ambition.crm.util; -import com.pudonghot.ambition.crm.exception.CVSFileImportingException; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import lombok.val; -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVParser; -import org.apache.commons.csv.CSVRecord; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.core.io.InputStreamResource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; - import java.io.*; +import lombok.val; +import lombok.SneakyThrows; import java.net.URLEncoder; -import java.nio.charset.Charset; +import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; -import java.util.Iterator; -import java.util.concurrent.atomic.AtomicBoolean; +import org.springframework.http.MediaType; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.core.io.InputStreamResource; /** * @author Donghuang @@ -27,7 +18,6 @@ import java.util.concurrent.atomic.AtomicBoolean; */ @Slf4j public class FileDownloadUtils { - private static final AtomicBoolean lock = new AtomicBoolean(false); /** * file to response entity diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/BaseWsResp.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/BaseWsResp.java new file mode 100644 index 0000000..579741d --- /dev/null +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/BaseWsResp.java @@ -0,0 +1,23 @@ +package com.pudonghot.ambition.crm.ws.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; + +/** + * @author Donghuang + * @date Jun 17, 2022 15:01:49 + */ +@Getter +@Setter +@ToString +public class BaseWsResp implements Serializable { + private static final long serialVersionUID = 1L; + + @NotBlank + private String employeeKey; + @NotBlank + private String type; +} diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskUpdatedWsResp.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskUpdatedWsResp.java new file mode 100644 index 0000000..8c39034 --- /dev/null +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskUpdatedWsResp.java @@ -0,0 +1,29 @@ +package com.pudonghot.ambition.crm.ws.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * @author Donghuang + * @date Jun 17, 2022 15:01:49 + */ +@Getter +@Setter +@ToString +public class ExportTaskUpdatedWsResp extends BaseWsResp { + private static final long serialVersionUID = 1L; + + private Integer countUndownloaded; + private Integer countFailed; + + public ExportTaskUpdatedWsResp() { + setType("EXPORT_TASK_UPDATED"); + } + + public ExportTaskUpdatedWsResp(final String employeeKey, final Integer countUndownloaded) { + this(); + this.countUndownloaded = countUndownloaded; + setEmployeeKey(employeeKey); + } +} diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/WebSocketService.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/WebSocketService.java index 4a170b9..3881375 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/WebSocketService.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/WebSocketService.java @@ -1,7 +1,10 @@ package com.pudonghot.ambition.crm.ws.service; +import javax.validation.Valid; import javax.validation.constraints.NotNull; import javax.validation.constraints.NotBlank; + +import com.pudonghot.ambition.crm.ws.model.BaseWsResp; import org.springframework.validation.annotation.Validated; /** @@ -14,8 +17,16 @@ public interface WebSocketService { /** * publish websocket message * - * @param employeeKey - * @param payload + * @param resp resp + */ + void publish(@NotNull @Valid BaseWsResp resp); + + /** + * publish websocket message + * + * @param employeeKey employee key + * @param payload payload */ void publish(@NotBlank String employeeKey, @NotNull Object payload); + } diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/impl/WebSocketServiceImpl.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/impl/WebSocketServiceImpl.java index 9272f59..19d54d2 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/impl/WebSocketServiceImpl.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/service/impl/WebSocketServiceImpl.java @@ -2,6 +2,7 @@ package com.pudonghot.ambition.crm.ws.service.impl; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import com.pudonghot.ambition.crm.ws.model.BaseWsResp; import org.springframework.beans.factory.annotation.Autowired; import com.pudonghot.ambition.crm.ws.service.WebSocketService; import org.springframework.messaging.simp.SimpMessagingTemplate; @@ -17,6 +18,16 @@ public class WebSocketServiceImpl implements WebSocketService { @Autowired private SimpMessagingTemplate message; + /** + * {@inheritDoc} + */ + @Override + public void publish(final BaseWsResp resp) { + publish(resp.getEmployeeKey(), resp); + } + + + @Override public void publish(final String employeeKey, final Object payload) { log.debug("Publish websocket message [{}] -> [{}].", employeeKey, payload); diff --git a/server/lib/tigon b/server/lib/tigon index a69a651..56a42f7 160000 --- a/server/lib/tigon +++ b/server/lib/tigon @@ -1 +1 @@ -Subproject commit a69a6519311d6a5ec932f2f7e1e71bb381a04a20 +Subproject commit 56a42f79cac7f8369bacf51e323242c0ae202e55 diff --git a/server/mapper/src/main/java/com/pudonghot/ambition/crm/Test.java b/server/mapper/src/main/java/com/pudonghot/ambition/crm/Test.java new file mode 100644 index 0000000..88814d3 --- /dev/null +++ b/server/mapper/src/main/java/com/pudonghot/ambition/crm/Test.java @@ -0,0 +1,4 @@ +package com.pudonghot.ambition.crm; + +public class Test { +} diff --git a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ExportTaskMapper.xml b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ExportTaskMapper.xml new file mode 100644 index 0000000..438104f --- /dev/null +++ b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ExportTaskMapper.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/server/model/src/main/java/com/pudonghot/ambition/crm/model/BaseDbModel.java b/server/model/src/main/java/com/pudonghot/ambition/crm/model/BaseDbModel.java index 3393c8e..c6332fd 100644 --- a/server/model/src/main/java/com/pudonghot/ambition/crm/model/BaseDbModel.java +++ b/server/model/src/main/java/com/pudonghot/ambition/crm/model/BaseDbModel.java @@ -4,18 +4,20 @@ import lombok.Getter; import lombok.Setter; import java.util.Date; import java.io.Serializable; +import me.chyxion.tigon.mybatis.BasicEntity; import me.chyxion.tigon.mybatis.NotUpdate; import lombok.experimental.FieldNameConstants; /** - * @author Shaun Chyxion
- * chyxion@163.com
- * Aug 09, 2017 22:24:40 + * Base Database model + * + * @author Donghuang + * @date Jun 18, 2022 09:39:26 */ @Getter @Setter @FieldNameConstants(prefix = "") -public class BaseDbModel implements Serializable { +public class BaseDbModel implements Serializable, BasicEntity { private static final long serialVersionUID = 1L; private Long id; @@ -25,6 +27,37 @@ public class BaseDbModel implements Serializable { private Date dateCreated; private String updatedBy; private Date dateUpdated; - private boolean enabled; + private Boolean enabled; private String note; + + /** + * convenient method + * + * @return true if is enabled + */ + public boolean isEnabled() { + return enabled != null && enabled; + } + + /** + * init date created + */ + @Override + public void beforeInsert() { + if (dateCreated == null) { + dateCreated = new Date(); + } + + if (enabled == null) { + enabled = Boolean.TRUE; + } + } + + /** + * update date updated + */ + @Override + public void beforeUpdate() { + dateUpdated = new Date(); + } } diff --git a/server/model/src/main/java/com/pudonghot/ambition/crm/model/ExportTask.java b/server/model/src/main/java/com/pudonghot/ambition/crm/model/ExportTask.java index 77c8fcb..264c249 100644 --- a/server/model/src/main/java/com/pudonghot/ambition/crm/model/ExportTask.java +++ b/server/model/src/main/java/com/pudonghot/ambition/crm/model/ExportTask.java @@ -3,8 +3,9 @@ package com.pudonghot.ambition.crm.model; import lombok.Getter; import lombok.Setter; import me.chyxion.tigon.mybatis.Table; -import me.chyxion.tigon.mybatis.NotUpdate; import lombok.experimental.FieldNameConstants; +import me.chyxion.tigon.mybatis.UseGeneratedKeys; +import me.chyxion.tigon.mybatis.NotUpdateWhenNull; import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus; /** @@ -13,6 +14,7 @@ import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus; */ @Getter @Setter +@UseGeneratedKeys @Table("crm_export_task") @FieldNameConstants(prefix = "") public class ExportTask extends BaseDbModel { @@ -20,6 +22,7 @@ public class ExportTask extends BaseDbModel { // Properties private EnumExportTaskStatus status; - @NotUpdate + @NotUpdateWhenNull private String location; + private boolean downloaded; } diff --git a/server/model/src/main/java/com/pudonghot/ambition/crm/model/FileInfo.java b/server/model/src/main/java/com/pudonghot/ambition/crm/model/FileInfo.java index aeb286f..ed932af 100644 --- a/server/model/src/main/java/com/pudonghot/ambition/crm/model/FileInfo.java +++ b/server/model/src/main/java/com/pudonghot/ambition/crm/model/FileInfo.java @@ -6,6 +6,7 @@ import me.chyxion.tigon.model.M3; import me.chyxion.tigon.mybatis.Table; import me.chyxion.tigon.mybatis.Transient; import lombok.experimental.FieldNameConstants; +import me.chyxion.tigon.mybatis.UseGeneratedKeys; /** * @version 0.0.1 @@ -16,6 +17,7 @@ import lombok.experimental.FieldNameConstants; */ @Getter @Setter +@UseGeneratedKeys @Table("crm_file_info") @FieldNameConstants(prefix = "") public class FileInfo extends M3 { diff --git a/server/model/src/main/java/com/pudonghot/ambition/crm/model/User.java b/server/model/src/main/java/com/pudonghot/ambition/crm/model/User.java index 53cfd15..2b7445d 100644 --- a/server/model/src/main/java/com/pudonghot/ambition/crm/model/User.java +++ b/server/model/src/main/java/com/pudonghot/ambition/crm/model/User.java @@ -25,9 +25,9 @@ public class User extends M3 { // roles public static final String ROLE_ADMIN = "ADMIN"; public static final String ROLE_LELI = "leli"; - public static final String ROLE_CHYXION = "donghuang"; + public static final String ROLE_DONGHUANG = "donghuang"; - // Properties + // Properties private String account; @NotUpdate private String employeeId; diff --git a/web/app/services/websocket.js b/web/app/services/websocket.js index a316b19..441febf 100644 --- a/web/app/services/websocket.js +++ b/web/app/services/websocket.js @@ -6,16 +6,6 @@ export default Service.extend({ ajax: service('ajax'), connect() { const me = this; - if (me.get('connected')) { - console.info('Websocket is connected, reconnect.'); - me.disconnect(); - } - - // connect - if (!me.get('stompClient')) { - me.set('stompClient', Stomp.over(new SockJS('/stomp'))); - } - const user = me.get('ajax.user'); if (!user) { @@ -23,15 +13,57 @@ export default Service.extend({ return; } - me.get('stompClient').connect({}, function() { - console.info('Connect websocket.', user); - me.stompClient.subscribe('/topic/' + user.id, function(msg) { + if (me.get('connected')) { + console.info('Websocket is connected, reconnect.'); + me.disconnect(); + } + + const client = new StompJs.Client({ + // brokerURL: 'ws://localhost:15674/ws', + webSocketFactory: function () { + // Note that the URL is different from the WebSocket URL + return new SockJS('/stomp'); + }, + connectHeaders: { + user: user.id, + // passcode: 'password', + }, + debug: function (str) { + console.log(str); + }, + reconnectDelay: 5000, + heartbeatIncoming: 4000, + heartbeatOutgoing: 4000, + }); + + client.onConnect = function(frame) { + // Do something, all subscribes must be done is this callback + // This is needed because this will be executed after a (re)connect + console.info('Websocket connected: ', frame); + me.set('subscription', client.subscribe('/topic/' + user.id, function(msg) { console.info('On websocket message: ', msg); $.trigger('WEBSOCKET', JSON.parse(msg.body)); - }); + })); me.set('connected', true); - console.info('Websocket connected.'); - }); + }; + + client.onDisconnect = function(frame) { + console.log('On websocket disconnect: ', frame); + me.set('connected', false); + }; + + client.onStompError = function (frame) { + // Will be invoked in case of error encountered at Broker + // Bad login/passcode typically will cause an error + // Complaint brokers will set `message` header with a brief message. Body may contain details. + // Compliant brokers will terminate the connection after any error + console.log('Broker reported error: ', frame.headers['message']); + console.log('Additional details: ', frame.body); + me.set('connected', false); + }; + + client.activate(); + me.set('client', client); }, willDestroy() { const me = this; @@ -40,10 +72,8 @@ export default Service.extend({ }, disconnect() { const me = this; - if (me.get('connected') && me.get('stompClient')) { - me.get('stompClient').disconnect(); - me.set('connected', false); - console.info('Websocket disconnected.'); + if (me.get('connected') && me.get('client')) { + me.get('client').deactivate(); return; } diff --git a/web/ember-cli-build.js b/web/ember-cli-build.js index 002e709..ce9aa79 100644 --- a/web/ember-cli-build.js +++ b/web/ember-cli-build.js @@ -110,8 +110,9 @@ module.exports = function(defaults) { importVendor(app, 'node_modules/bootstrap-wysiwyg/src/bootstrap-wysiwyg.js'); // WebSocket + importVendor(app, 'node_modules/@stomp/stompjs/bundles/stomp.umd.js'); importVendor(app, 'node_modules/sockjs-client/dist/sockjs.js'); - importVendor(app, 'node_modules/stomp-websocket/lib/stomp.js'); + // importVendor(app, 'node_modules/stomp-websocket/lib/stomp.js'); // Bootstrap Toolkit importVendor(app, 'node_modules/responsive-toolkit/dist/bootstrap-toolkit.js'); diff --git a/web/package.json b/web/package.json index 5e3606a..049810c 100644 --- a/web/package.json +++ b/web/package.json @@ -1,79 +1,79 @@ -{ - "name": "ambition-crm", - "version": "0.0.2", - "description": "Ambition CRM", - "private": true, - "directories": { - "doc": "doc", - "test": "tests" - }, - "scripts": { - "build": "ember build", - "start": "ember server", - "test": "ember test" - }, - "repository": "", - "author": "Shaun Chyxion", - "license": "MIT", - "devDependencies": { - "@ember/jquery": "1.1.0", - "@ember/optional-features": "^1.3.0", - "@ember/test-helpers": "^2.8.1", - "bootbox": "5.1.3", - "bootstrap": "3.4.1", - "bootstrap-colorpicker": "^2.5.2", - "bootstrap-tagsinput": "^0.7.1", - "bootstrap-wysiwyg": "^2.0.1", - "broccoli-asset-rev": "^3.0.0", - "ember-ajax": "^5.0.0", - "ember-auto-import": "^2.4.2", - "ember-cli": "3.28.5", - "ember-cli-app-version": "^5.0.0", - "ember-cli-babel": "^7.19.0", - "ember-cli-clipboard": "^0.16.0", - "ember-cli-dependency-checker": "^3.1.0", - "ember-cli-eslint": "^5.1.0", - "ember-cli-htmlbars": "^6.0.1", - "ember-cli-inject-live-reload": "^2.0.2", - "ember-cli-less": "^3.0.1", - "ember-cli-moment-shim": "^3.7.1", - "ember-cli-shims": "^1.2.0", - "ember-cli-sri": "^2.1.1", - "ember-cli-template-lint": "^2.0.2", - "ember-cli-uglify": "^3.0.0", - "ember-composable-helpers": "^3.1.1", - "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.1", - "ember-maybe-import-regenerator": "^1.0.0", - "ember-moment": "^10.0.0", - "ember-qunit": "^5.1.5", - "ember-radio-button": "^2.0.1", - "ember-resolver": "^8.0.0", - "ember-route-action-helper": "^2.0.8", - "ember-source": "3.28.9", - "ember-truth-helpers": "^3.0.0", - "emberx-select": "3.1.1", - "eslint-plugin-ember": "^10.6.1", - "font-awesome": "^4.7.0", - "fuelux": "^3.17.0", - "glob": "^8.0.3", - "jquery-colorbox": "^1.6.4", - "json-format-highlight": "^1.0.4", - "loader.js": "^4.7.0", - "moment": "^2.24.0", - "qunit": "^2.19.1", - "qunit-dom": "^2.0.0", - "responsive-toolkit": "^2.6.3", - "select2": "^4.0.13", - "toastr": "^2.1.4", - "validate.js": "^0.13.1", - "webpack": "^5.73.0" - }, - "dependencies": { - "sockjs-client": "^1.6.1", - "stomp-websocket": "^2.3.4-next" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } -} +{ + "name": "ambition-crm", + "version": "0.0.2", + "description": "Ambition CRM", + "private": true, + "directories": { + "doc": "doc", + "test": "tests" + }, + "scripts": { + "build": "ember build", + "start": "ember server", + "test": "ember test" + }, + "repository": "", + "author": "Shaun Chyxion", + "license": "MIT", + "devDependencies": { + "@ember/jquery": "1.1.0", + "@ember/optional-features": "^1.3.0", + "@ember/test-helpers": "^2.8.1", + "bootbox": "5.1.3", + "bootstrap": "3.4.1", + "bootstrap-colorpicker": "^2.5.2", + "bootstrap-tagsinput": "^0.7.1", + "bootstrap-wysiwyg": "^2.0.1", + "broccoli-asset-rev": "^3.0.0", + "ember-ajax": "^5.0.0", + "ember-auto-import": "^2.4.2", + "ember-cli": "3.28.5", + "ember-cli-app-version": "^5.0.0", + "ember-cli-babel": "^7.19.0", + "ember-cli-clipboard": "^0.16.0", + "ember-cli-dependency-checker": "^3.1.0", + "ember-cli-eslint": "^5.1.0", + "ember-cli-htmlbars": "^6.0.1", + "ember-cli-inject-live-reload": "^2.0.2", + "ember-cli-less": "^3.0.1", + "ember-cli-moment-shim": "^3.7.1", + "ember-cli-shims": "^1.2.0", + "ember-cli-sri": "^2.1.1", + "ember-cli-template-lint": "^2.0.2", + "ember-cli-uglify": "^3.0.0", + "ember-composable-helpers": "^3.1.1", + "ember-export-application-global": "^2.0.0", + "ember-load-initializers": "^2.1.1", + "ember-maybe-import-regenerator": "^1.0.0", + "ember-moment": "^10.0.0", + "ember-qunit": "^5.1.5", + "ember-radio-button": "^2.0.1", + "ember-resolver": "^8.0.0", + "ember-route-action-helper": "^2.0.8", + "ember-source": "3.28.9", + "ember-truth-helpers": "^3.0.0", + "emberx-select": "3.1.1", + "eslint-plugin-ember": "^10.6.1", + "font-awesome": "^4.7.0", + "fuelux": "^3.17.0", + "glob": "^8.0.3", + "jquery-colorbox": "^1.6.4", + "json-format-highlight": "^1.0.4", + "loader.js": "^4.7.0", + "moment": "^2.24.0", + "qunit": "^2.19.1", + "qunit-dom": "^2.0.0", + "responsive-toolkit": "^2.6.3", + "select2": "^4.0.13", + "toastr": "^2.1.4", + "validate.js": "^0.13.1", + "webpack": "^5.73.0" + }, + "dependencies": { + "@stomp/stompjs": "^6.1.2", + "sockjs-client": "^1.6.1" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } +}