From 7640c1dab6a2c4bb0c5095d818d2bffae73d8082 Mon Sep 17 00:00:00 2001 From: Donghuang Date: Thu, 23 Jun 2022 22:32:12 +0800 Subject: [PATCH] export task complete --- .../crm/controller/ExportTaskController.java | 48 +++++++++++++++++-- .../crm/service/ExportTaskService.java | 8 ++++ .../support/ExportTaskServiceSupport.java | 25 ++++++++-- .../ambition/crm/util/FileDownloadUtils.java | 17 +++---- .../ws/model/ExportTaskCompletedWsResp.java | 30 ++++++++++++ .../crm/ws/model/ExportTaskUpdatedWsResp.java | 1 - server/crm/src/main/resources/application.yml | 2 +- web/app/routes/export-task/list.js | 9 +++- web/app/services/export-task/service.js | 16 ++++++- web/app/services/message.js | 5 ++ web/app/styles/app.less | 2 +- .../templates/components/main-container.hbs | 8 ++-- web/app/templates/export-task/list.hbs | 42 +++++++--------- 13 files changed, 163 insertions(+), 50 deletions(-) create mode 100644 server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskCompletedWsResp.java 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 index e3191aa..a5a3019 100644 --- 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 @@ -1,18 +1,27 @@ package com.pudonghot.ambition.crm.controller; import lombok.val; +import java.io.File; +import java.util.Map; import javax.validation.Valid; import lombok.extern.slf4j.Slf4j; import me.chyxion.tigon.mybatis.Search; +import org.springframework.http.HttpStatus; +import org.apache.commons.lang3.StringUtils; +import javax.validation.constraints.NotNull; import com.pudonghot.ambition.crm.model.User; +import org.springframework.http.ResponseEntity; 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 com.pudonghot.ambition.crm.util.FileDownloadUtils; 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.RequestParam; +import com.pudonghot.ambition.crm.service.ExportTaskService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.beans.factory.annotation.Autowired; import com.pudonghot.ambition.crm.ws.service.WebSocketService; @@ -43,6 +52,40 @@ public class ExportTaskController return list(req, new Search()); } + /** + * download file + * @param id id + * @return file + */ + @RequiresRoles(User.ROLE_ADMIN) + @RequestMapping("/download") + public ResponseEntity file(@NotNull @RequestParam("id") final Long id) { + val exportTask = service.find(id); + if (exportTask == null) { + return ResponseEntity.notFound().build(); + } + + val userId = getUserId(); + + if (!userId.equals(exportTask.getCreatedBy())) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + exportTask.setDownloaded(true); + exportTask.setUpdatedBy(userId); + ((ExportTaskService) service).update(exportTask); + + val location = exportTask.getLocation(); + if (StringUtils.isNotBlank(location)) { + val file = new File(location); + if (file.exists() && file.isFile()) { + ((ExportTaskService) service).notifyTaskUpdated(userId); + return FileDownloadUtils.toResponseEntity(file, file.getName()); + } + } + + return ResponseEntity.notFound().build(); + } /** * {@inheritDoc} @@ -62,8 +105,7 @@ public class ExportTaskController @PostMapping("/test-push") @RequiresRoles(User.ROLE_ADMIN) - public void testPush(@RequestBody ExportTaskUpdatedWsResp resp) { - resp.setEmployeeKey(getUserId()); - webSocketService.publish(resp); + public void testPush(@RequestBody Map resp) { + webSocketService.publish(getUserId(), resp); } } 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 777a9dc..b14db1f 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,7 @@ package com.pudonghot.ambition.crm.service; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import com.pudonghot.ambition.crm.model.ExportTask; import me.chyxion.tigon.service2.BaseQueryService; @@ -26,5 +27,12 @@ public interface ExportTaskService extends BaseQueryService { * @param employeeKey employee key */ void notifyTaskUpdated(@NotBlank String employeeKey); + + /** + * update task + * + * @param exportTask task + */ + void update(@NotNull ExportTask exportTask); } 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 37bde29..2d435e3 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 @@ -24,6 +24,7 @@ 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; +import com.pudonghot.ambition.crm.ws.model.ExportTaskCompletedWsResp; /** * @author Donghuang @@ -73,15 +74,16 @@ public class ExportTaskServiceSupport exportTask.setLocation(new File(distDir, exportFile.getName()).getPath()); exportTask.setDateUpdated(new Date()); mapper.update(exportTask); - } catch (final Throwable e) { + notifyTaskComplete(employeeKey, true, null); + } + 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); + notifyTaskComplete(employeeKey, false, e.getMessage()); } - - notifyTaskUpdated(employeeKey); } finally { LOCK_MAP.remove(employeeKey); @@ -89,6 +91,15 @@ public class ExportTaskServiceSupport }); } + void notifyTaskComplete(final String employeeKey, final boolean success, final String message) { + val resp = new ExportTaskCompletedWsResp(employeeKey, + mapper.count(new Search(ExportTask.CREATED_BY, employeeKey) + .isFalse(ExportTask.DOWNLOADED))); + resp.setSuccess(success); + resp.setMessage(message); + webSocketService.publish(resp); + } + /** * {@inheritDoc} */ @@ -99,4 +110,12 @@ public class ExportTaskServiceSupport mapper.count(new Search(ExportTask.CREATED_BY, employeeKey) .isFalse(ExportTask.DOWNLOADED)))); } + + /** + * {@inheritDoc} + */ + @Override + public void update(final ExportTask exportTask) { + mapper.update(exportTask); + } } 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 48633a6..2e2c3bf 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 @@ -10,7 +10,7 @@ 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; +import org.springframework.core.io.FileSystemResource; /** * @author Donghuang @@ -36,16 +36,11 @@ public class FileDownloadUtils { headers.add("Pragma", "no-cache"); headers.add("Expires", "0"); - try (val fin = new FileInputStream(file)) { - return ResponseEntity.ok() - .headers(headers) - .contentLength(file.length()) - .contentType(MediaType.APPLICATION_OCTET_STREAM) - .body(new InputStreamResource(fin)); - } - catch (final IOException e) { - log.error("Download file error caused.", e); - } + return ResponseEntity.ok() + .headers(headers) + .contentLength(file.length()) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .body(new FileSystemResource(file)); } return ResponseEntity.notFound().build(); diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskCompletedWsResp.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskCompletedWsResp.java new file mode 100644 index 0000000..4e95bc1 --- /dev/null +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskCompletedWsResp.java @@ -0,0 +1,30 @@ +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 ExportTaskCompletedWsResp extends BaseWsResp { + private static final long serialVersionUID = 1L; + + private Integer countUndownloaded; + private Boolean success; + private String message; + + public ExportTaskCompletedWsResp() { + setType("EXPORT_TASK_COMPLETED"); + } + + public ExportTaskCompletedWsResp(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/model/ExportTaskUpdatedWsResp.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/ws/model/ExportTaskUpdatedWsResp.java index 8c39034..e471759 100644 --- 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 @@ -15,7 +15,6 @@ public class ExportTaskUpdatedWsResp extends BaseWsResp { private static final long serialVersionUID = 1L; private Integer countUndownloaded; - private Integer countFailed; public ExportTaskUpdatedWsResp() { setType("EXPORT_TASK_UPDATED"); diff --git a/server/crm/src/main/resources/application.yml b/server/crm/src/main/resources/application.yml index a6d8ee4..5f428ab 100644 --- a/server/crm/src/main/resources/application.yml +++ b/server/crm/src/main/resources/application.yml @@ -21,7 +21,7 @@ datasource: username: root database: - backup-dir: /Users/chyxion/Workspaces/ambition-crm/database_backups + backup-dir: d:/data/database_backups restore-shell: /data/program/mysql-backup/bin/mysql_restore.sh file: diff --git a/web/app/routes/export-task/list.js b/web/app/routes/export-task/list.js index 6d603fc..ea18451 100644 --- a/web/app/routes/export-task/list.js +++ b/web/app/routes/export-task/list.js @@ -1,5 +1,12 @@ import BaseListRoute from './../base-list'; +import { set } from '@ember/object'; export default BaseListRoute.extend({ - breadcrumbs: [{text: 'Export Tasks'}] + breadcrumbs: [{text: 'Export Tasks'}], + actions: { + download(rec) { + const me = this; + set(rec, 'downloaded', true); + } + } }); diff --git a/web/app/services/export-task/service.js b/web/app/services/export-task/service.js index cbd9fb9..26c566e 100644 --- a/web/app/services/export-task/service.js +++ b/web/app/services/export-task/service.js @@ -7,8 +7,20 @@ export default BaseService.extend({ const me = this; $.on('WEBSOCKET', function(e, data) { console.log('Export task: On websocket message trigger.', e, data); - if (data.type == 'EXPORT_TASK_UPDATED') { - me.set('countUndownloaded', data ? data.countUndownloaded : null); + if (!data) { + console.log('Event data is null, ignore.', e); + return; + } + + me.set('countUndownloaded', data.countUndownloaded); + + if (data.type == 'EXPORT_TASK_COMPLETED') { + if (data.success) { + me.get('message').alert('Export task completed.'); + } + else { + me.get('message').error('Export task error caused: ' + data.message); + } } }); } diff --git a/web/app/services/message.js b/web/app/services/message.js index 22b4a06..66fed79 100644 --- a/web/app/services/message.js +++ b/web/app/services/message.js @@ -11,6 +11,11 @@ export default Service.extend({ warn(msg) { toastr.warning(msg); }, + error(msg) { + toastr.options.closeButton = true; + toastr.error(msg); + toastr.options.closeButton = false; + }, alert2(msg) { this._show_alert_(msg); }, diff --git a/web/app/styles/app.less b/web/app/styles/app.less index 298afc6..cf92e4e 100644 --- a/web/app/styles/app.less +++ b/web/app/styles/app.less @@ -118,7 +118,7 @@ input[type="number"] { font-size: 10px; border-radius: 50%; color: #fff; - background-color: rgba(255, 0, 0, 0.8); + background-color: rgba(209, 91, 71, 0.9); // rgba(0, 0, 0, 0.7); display: flex; diff --git a/web/app/templates/components/main-container.hbs b/web/app/templates/components/main-container.hbs index 8277bf7..e8536a1 100644 --- a/web/app/templates/components/main-container.hbs +++ b/web/app/templates/components/main-container.hbs @@ -100,9 +100,11 @@
  • - - 21 - Export Task {{#if this.exportTaskService.countUndownloaded}}{{this.exportTaskService.countUndownloaded}}{{/if}} + + {{#if this.exportTaskService.countUndownloaded}} + {{this.exportTaskService.countUndownloaded}} + {{/if}} + Export Task
  • {{/if}} diff --git a/web/app/templates/export-task/list.hbs b/web/app/templates/export-task/list.hbs index f86a78b..ad0fe99 100644 --- a/web/app/templates/export-task/list.hbs +++ b/web/app/templates/export-task/list.hbs @@ -7,7 +7,9 @@ - {{sortable-th name='dateCreated' text='Date Created' style='min-width: 105px;'}} +
    + Date Created + Status @@ -32,32 +34,24 @@ {{it.status}} - {{status-cell model=it field='downloaded' enabledText='DOWNLOADED' disabledText='NOT DOWNLOAD'}} + {{#if it.downloaded}} + + + DOWNLOADED + + {{else}} + + + NOT DOWNLOAD + + {{/if}} -