From 126575f0bf386bc4f20f082c2ea126fba8051233 Mon Sep 17 00:00:00 2001 From: Donghuang Date: Thu, 23 Jun 2022 17:29:32 +0800 Subject: [PATCH] add export bage --- .../support/ExportTaskServiceSupport.java | 2 +- server/crm/src/main/resources/application.yml | 61 +++++++------ .../src/main/resources/application_dev.yml | 61 +++++++------ server/lib/tigon | 2 +- .../ambition/crm/mapper/CustomerMapper.java | 4 +- .../ambition/crm/mapper/CustomerMapper.xml | 8 +- .../crm/mapper/ImportRecordMapper.java | 4 +- .../ambition/crm/mapper/WeekGoalMapper.java | 4 +- server/model/pom.xml | 5 ++ .../main/java/me/chyxion/tigon/model/M1.java | 16 ++++ server/{launch.sh => start.sh} | 0 web/app/app.js | 6 +- web/app/components/a-btn.js | 8 ++ web/app/components/base-component.js | 4 - web/app/components/base-form-input.js | 23 ++--- web/app/components/basic-component.js | 4 +- web/app/components/breadcrumbs-bar.js | 9 +- web/app/components/date-cell.js | 3 +- web/app/components/delete-btn.js | 11 ++- web/app/components/editable-cell.js | 13 +-- web/app/components/file-input.js | 5 +- web/app/components/form-footer-buttons.js | 34 +++---- web/app/components/form-input-modal-select.js | 7 +- web/app/components/image-input.js | 4 +- web/app/components/image-previews.js | 4 +- web/app/components/list-select-checkbox.js | 10 +-- web/app/components/main-container.js | 8 +- web/app/components/modal-dialog.js | 5 +- web/app/components/op-detail.js | 4 +- web/app/components/pagination-bar.js | 28 +++--- web/app/components/reload-btn.js | 3 +- web/app/components/search-box.js | 10 +-- web/app/components/sortable-th.js | 38 ++++---- web/app/components/status-cell.js | 14 +-- web/app/components/status-toggle-button.js | 13 +-- web/app/components/top-navbar.js | 2 +- web/app/mixins/components/base-component.js | 22 +++-- web/app/mixins/services/base-service.js | 86 ------------------ web/app/router.js | 4 + web/app/routes/application.js | 7 +- web/app/routes/customer/list.js | 20 +++-- web/app/routes/export-task/list.js | 5 ++ web/app/routes/home-page/list.js | 1 - web/app/routes/import-record/list.js | 1 - web/app/services/export-task/service.js | 15 ++++ web/app/services/import-record/service.js | 5 +- web/app/services/message.js | 15 +++- web/app/services/service.js | 90 ++++++++++++++++++- web/app/services/store.js | 16 ++-- web/app/services/tool-service.js | 7 +- web/app/services/user/service.js | 1 - web/app/services/websocket.js | 6 +- web/app/styles/app.less | 17 ++++ web/app/templates/components/a-btn.hbs | 1 + .../templates/components/main-container.hbs | 9 +- web/app/templates/customer/list.hbs | 4 +- web/app/templates/export-task/list.hbs | 71 +++++++++++++++ .../integration/components/a-btn-test.js | 26 ++++++ .../unit/routes/export-task/list-test.js | 11 +++ .../unit/services/export-task/service-test.js | 12 +++ 60 files changed, 566 insertions(+), 323 deletions(-) rename server/{launch.sh => start.sh} (100%) mode change 100755 => 100644 create mode 100644 web/app/components/a-btn.js delete mode 100644 web/app/components/base-component.js delete mode 100644 web/app/mixins/services/base-service.js create mode 100644 web/app/routes/export-task/list.js create mode 100644 web/app/services/export-task/service.js create mode 100644 web/app/templates/components/a-btn.hbs create mode 100644 web/app/templates/export-task/list.hbs create mode 100644 web/tests/integration/components/a-btn-test.js create mode 100644 web/tests/unit/routes/export-task/list-test.js create mode 100644 web/tests/unit/services/export-task/service-test.js 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 ae62e84..37bde29 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 @@ -53,7 +53,7 @@ public class ExportTaskServiceSupport @Override public void doExport(final String employeeKey) { val now = Long.valueOf(System.currentTimeMillis()); - Assert.state(now.equals(LOCK_MAP.putIfAbsent(employeeKey, now)), + Assert.state(LOCK_MAP.putIfAbsent(employeeKey, now) == null, "There is a running export task, please try again later!"); threadPoolTaskExecutor.execute(() ->{ diff --git a/server/crm/src/main/resources/application.yml b/server/crm/src/main/resources/application.yml index 362653f..a6d8ee4 100644 --- a/server/crm/src/main/resources/application.yml +++ b/server/crm/src/main/resources/application.yml @@ -1,37 +1,46 @@ server: - port: 8088 + port: 8088 spring: - servlet: - multipart: - max-file-size: 512MB - max-request-size: 512MB + jackson: + default-property-inclusion: NON_NULL + time-zone: GMT+8 + serialization: + write-dates-as-timestamps: true + fail-on-empty-beans: false + servlet: + multipart: + max-file-size: 512MB + max-request-size: 512MB datasource: - database-name: ambition-crm - host: 172.16.4.6 - password: MySQL2b||!2b - port: 3306 - username: root + database-name: ambition-crm + host: 172.16.4.6 + password: MySQL2b||!2b + port: 3306 + username: root database: - backup-dir: /Users/chyxion/Workspaces/ambition-crm/database_backups - restore-shell: /data/program/mysql-backup/bin/mysql_restore.sh + backup-dir: /Users/chyxion/Workspaces/ambition-crm/database_backups + restore-shell: /data/program/mysql-backup/bin/mysql_restore.sh file: - base-dir: /Users/donghuang/Documents/Workspaces/ambition-crm/files/ - base-path: http://127.0.0.1:1217/lm-f/ + base-dir: /Users/donghuang/Documents/Workspaces/ambition-crm/files/ + base-path: http://127.0.0.1:1217/lm-f/ + +export: + location: d:/data/export tigon: - shiro: - session: - validation: - scheduler: - enabled: true - filter-chain: > - /auth/login=anon - /=anon - /index.html=anon - /assets/**=anon - /f/**=anon - /**=user + shiro: + session: + validation: + scheduler: + enabled: true + filter-chain: > + /auth/login=anon + /=anon + /index.html=anon + /assets/**=anon + /f/**=anon + /**=user diff --git a/server/crm/src/main/resources/application_dev.yml b/server/crm/src/main/resources/application_dev.yml index 362653f..5f428ab 100644 --- a/server/crm/src/main/resources/application_dev.yml +++ b/server/crm/src/main/resources/application_dev.yml @@ -1,37 +1,46 @@ server: - port: 8088 + port: 8088 spring: - servlet: - multipart: - max-file-size: 512MB - max-request-size: 512MB + jackson: + default-property-inclusion: NON_NULL + time-zone: GMT+8 + serialization: + write-dates-as-timestamps: true + fail-on-empty-beans: false + servlet: + multipart: + max-file-size: 512MB + max-request-size: 512MB datasource: - database-name: ambition-crm - host: 172.16.4.6 - password: MySQL2b||!2b - port: 3306 - username: root + database-name: ambition-crm + host: 172.16.4.6 + password: MySQL2b||!2b + port: 3306 + username: root database: - backup-dir: /Users/chyxion/Workspaces/ambition-crm/database_backups - restore-shell: /data/program/mysql-backup/bin/mysql_restore.sh + backup-dir: d:/data/database_backups + restore-shell: /data/program/mysql-backup/bin/mysql_restore.sh file: - base-dir: /Users/donghuang/Documents/Workspaces/ambition-crm/files/ - base-path: http://127.0.0.1:1217/lm-f/ + base-dir: /Users/donghuang/Documents/Workspaces/ambition-crm/files/ + base-path: http://127.0.0.1:1217/lm-f/ + +export: + location: d:/data/export tigon: - shiro: - session: - validation: - scheduler: - enabled: true - filter-chain: > - /auth/login=anon - /=anon - /index.html=anon - /assets/**=anon - /f/**=anon - /**=user + shiro: + session: + validation: + scheduler: + enabled: true + filter-chain: > + /auth/login=anon + /=anon + /index.html=anon + /assets/**=anon + /f/**=anon + /**=user diff --git a/server/lib/tigon b/server/lib/tigon index 56a42f7..1c57bda 160000 --- a/server/lib/tigon +++ b/server/lib/tigon @@ -1 +1 @@ -Subproject commit 56a42f79cac7f8369bacf51e323242c0ae202e55 +Subproject commit 1c57bdaf5ab05684239ea1a1e50d33730095d464 diff --git a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.java b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.java index 716b6d7..14b8ede 100644 --- a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.java +++ b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.java @@ -33,7 +33,7 @@ public interface CustomerMapper extends BaseMapper { * @return customers */ List listForShow( - @NotNull @Param("s") Search search, + @NotNull @Param(PARAM_SEARCH_KEY) Search search, @Param("account") String account); /** @@ -67,7 +67,7 @@ public interface CustomerMapper extends BaseMapper { * @return count of customers */ int countForShow( - @NotNull @Param("s") Search search, + @NotNull @Param(PARAM_SEARCH_KEY) Search search, @Param("account") String account); List> listMs(); diff --git a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.xml b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.xml index 0b68508..0b026df 100644 --- a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.xml +++ b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/CustomerMapper.xml @@ -234,24 +234,24 @@ - + join (select distinct customer_id from crm_customer_application) app_not_null on customer.id = app_not_null.customer_id - + join (select distinct customer_id from crm_customer_application where application_id in - + #{appId} ) app on customer.id = app.customer_id - + left join (select customer_id, max(year) year from crm_customer_year_to_date_sale where enabled = 1 diff --git a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ImportRecordMapper.java b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ImportRecordMapper.java index 7e32437..185aaef 100644 --- a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ImportRecordMapper.java +++ b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/ImportRecordMapper.java @@ -18,12 +18,12 @@ public interface ImportRecordMapper extends BaseMapper { * @param search search * @return import records */ - List listForShow(@Param("s") Search search); + List listForShow(@Param(PARAM_SEARCH_KEY) Search search); /** * count for show * @param search search * @return count of import records */ - int countForShow(@Param("s") Search search); + int countForShow(@Param(PARAM_SEARCH_KEY) Search search); } diff --git a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/WeekGoalMapper.java b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/WeekGoalMapper.java index 7958bfc..ccbca73 100644 --- a/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/WeekGoalMapper.java +++ b/server/mapper/src/main/java/com/pudonghot/ambition/crm/mapper/WeekGoalMapper.java @@ -20,14 +20,14 @@ public interface WeekGoalMapper extends BaseMapper { * @param search search * @return week goals */ - List listJoinUser(@Param("s") Search search); + List listJoinUser(@Param(PARAM_SEARCH_KEY) Search search); /** * count join user * @param search search * @return count of week goals */ - int countJoinUser(@Param("s") Search search); + int countJoinUser(@Param(PARAM_SEARCH_KEY) Search search); /** * @return list user diff --git a/server/model/pom.xml b/server/model/pom.xml index 75cfedd..e2f5c33 100644 --- a/server/model/pom.xml +++ b/server/model/pom.xml @@ -37,6 +37,11 @@ tigon-web ${tigon.webmvc.scope} + + me.chyxion.tigon + tigon-mybatis + provided + org.projectlombok lombok diff --git a/server/model/src/main/java/me/chyxion/tigon/model/M1.java b/server/model/src/main/java/me/chyxion/tigon/model/M1.java index b4d452a..0c19756 100644 --- a/server/model/src/main/java/me/chyxion/tigon/model/M1.java +++ b/server/model/src/main/java/me/chyxion/tigon/model/M1.java @@ -3,8 +3,12 @@ package me.chyxion.tigon.model; import lombok.Getter; import lombok.Setter; import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; import me.chyxion.tigon.mybatis.NotUpdate; +import org.apache.commons.lang3.StringUtils; import lombok.experimental.FieldNameConstants; +import me.chyxion.tigon.mybatis.util.EntityUtils; /** * @version 0.0.1 @@ -43,4 +47,16 @@ public class M1 extends M0 { super.beforeUpdate(); dateUpdated = new Date(); } + + public List cols() { + return EntityUtils.cols(getClass()); + } + + public List cols(final String table) { + if (StringUtils.isBlank(table)) { + return cols(); + } + + return cols().stream().map(it -> table + "." + it).collect(Collectors.toList()); + } } diff --git a/server/launch.sh b/server/start.sh old mode 100755 new mode 100644 similarity index 100% rename from server/launch.sh rename to server/start.sh diff --git a/web/app/app.js b/web/app/app.js index ebed86a..709ed1f 100644 --- a/web/app/app.js +++ b/web/app/app.js @@ -1,14 +1,12 @@ -import Ember from 'ember'; +import Application from '@ember/application'; import Resolver from './resolver'; import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; import $ from 'jquery'; -let App; - // Ember.MODEL_FACTORY_INJECTIONS = true; -App = Ember.Application.extend({ +const App = Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, Resolver diff --git a/web/app/components/a-btn.js b/web/app/components/a-btn.js new file mode 100644 index 0000000..e083988 --- /dev/null +++ b/web/app/components/a-btn.js @@ -0,0 +1,8 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: 'a', + classNames: ['cursor-pointer'], + attributeBindings: ['title', 'href', 'target'], + 'data-rel': 'tooltip' +}); diff --git a/web/app/components/base-component.js b/web/app/components/base-component.js deleted file mode 100644 index 87a0d74..0000000 --- a/web/app/components/base-component.js +++ /dev/null @@ -1,4 +0,0 @@ -import Ember from 'ember'; -import BaseComponentMixin from '../mixins/components/base-component'; - -export default Ember.Component.extend(BaseComponentMixin, {}); diff --git a/web/app/components/base-form-input.js b/web/app/components/base-form-input.js index 93971ba..6fbeec3 100644 --- a/web/app/components/base-form-input.js +++ b/web/app/components/base-form-input.js @@ -1,23 +1,24 @@ -import Ember from 'ember'; -import BaseComponentMixin from '../mixins/components/base-component'; +import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; +import BasicComponent from './basic-component'; -export default Ember.Component.extend(BaseComponentMixin, { +export default BasicComponent.extend({ 'col-width': 6, - colWidth: Ember.computed.alias('col-width'), + colWidth: alias('col-width'), classNameBindings: ['hasError:has-error'], - model: Ember.computed.alias('route.controller.model'), - errors: Ember.computed.alias('route.controller.errors'), - hasError: Ember.computed('errors', function() { + model: alias('route.controller.model'), + errors: alias('route.controller.errors'), + hasError: computed('errors', function() { return this.get('errors.' + this.get('name')); }), 'error-msg': true, - errorMsg: Ember.computed.alias('error-msg'), + errorMsg: alias('error-msg'), 'label-class': 'col-xs-12 col-sm-3 col-md-3', - labelClass: Ember.computed.alias('label-class'), + labelClass: alias('label-class'), 'input-class': 'col-xs-12 col-sm-5 col-md-5', - inputClass: Ember.computed.alias('input-class'), + inputClass: alias('input-class'), 'data-scope': 'model', - dataScope: Ember.computed.alias('data-scope'), + dataScope: alias('data-scope'), didReceiveAttrs() { let me = this; me._super(...arguments); diff --git a/web/app/components/basic-component.js b/web/app/components/basic-component.js index 58bb158..484e2e3 100644 --- a/web/app/components/basic-component.js +++ b/web/app/components/basic-component.js @@ -9,8 +9,8 @@ export default Component.extend({ routeName: alias('router.currentRouteName'), 'trim-index': true, route: computed('routeName', function() { - let me = this; - let routeName = me.get('routeName'); + const me = this; + const routeName = me.get('routeName'); return me.getRoute(me.get('trim-index') ? routeName.replace(/\.index$/, '') : routeName); }), diff --git a/web/app/components/breadcrumbs-bar.js b/web/app/components/breadcrumbs-bar.js index cc9fcf0..da53d93 100644 --- a/web/app/components/breadcrumbs-bar.js +++ b/web/app/components/breadcrumbs-bar.js @@ -1,9 +1,8 @@ -import Ember from 'ember'; -import BaseComponentMixin from '../mixins/components/base-component'; +import { computed } from '@ember/object'; +import BasicComponent from './basic-component'; -export default Ember.Component.extend(BaseComponentMixin, { - // breadcrumbs: Ember.computed.alias('route.breadcrumbs'), - breadcrumbs: Ember.computed('route', function() { +export default BasicComponent.extend({ + breadcrumbs: computed('route', function() { let me = this; let breadcrumbs = this.get('route.breadcrumbs'); if (!breadcrumbs) { diff --git a/web/app/components/date-cell.js b/web/app/components/date-cell.js index e59adfc..2d42fb6 100644 --- a/web/app/components/date-cell.js +++ b/web/app/components/date-cell.js @@ -1,7 +1,8 @@ import Ember from 'ember'; +import { alias } from '@ember/object/computed'; export default Ember.Component.extend({ tagName: 'span', - value: Ember.computed.alias('model'), + value: alias('model'), format: 'YYYY-MM-DD H:mm:ss' }); diff --git a/web/app/components/delete-btn.js b/web/app/components/delete-btn.js index fdd9832..7674e74 100644 --- a/web/app/components/delete-btn.js +++ b/web/app/components/delete-btn.js @@ -1,16 +1,15 @@ -import Ember from 'ember'; - -import BaseComponent from './base-component'; +import { alias } from '@ember/object/computed'; +import BaseComponent from './basic-component'; export default BaseComponent.extend({ tagName: 'a', attributeBindings: ['title'], 'data-rel': 'tooltip', - enabled: Ember.computed.alias('model.enabled'), + enabled: alias('model.enabled'), title: 'Delete', 'icon-size-class': 'bigger-120', didReceiveAttrs() { - let me = this; + const me = this; me._super(...arguments); if (me.get('icon-only')) { me.set('icon-size-class', 'bigger-130'); @@ -24,7 +23,7 @@ export default BaseComponent.extend({ } }, click() { - let me = this; + const me = this; me.dialog.confirm('Are you sure to delete?', () => { me.get('service').del(me.get('model.id')).then(() => { me.get('route.controller.model.data').removeObject(me.get('model')); diff --git a/web/app/components/editable-cell.js b/web/app/components/editable-cell.js index bc232e6..8952b53 100644 --- a/web/app/components/editable-cell.js +++ b/web/app/components/editable-cell.js @@ -1,10 +1,11 @@ -import Ember from 'ember'; -import BaseComponent from './base-component'; +import { alias } from '@ember/object/computed'; +import { later } from '@ember/runloop'; +import BaseComponent from './basic-component'; import $ from 'jquery'; export default BaseComponent.extend({ 'allow-blank': true, - allowBlank: Ember.computed.alias('allow-blank'), + allowBlank: alias('allow-blank'), type: 'text', step: 1, // for number 'confirm-update': true, @@ -14,12 +15,12 @@ export default BaseComponent.extend({ const me = this; me.set('oldValue', me.getFieldValue()); me.set('isEditing', true) - Ember.run.later(() => { + later(() => { $('input[type="text"][name="' + me.get('model.id') + '"]', me.element).focus(); }, 320); }, doUpdate() { - let me = this; + const me = this; if (me.get('isUpdating')) { console.info('Cell Is Updating, Ignore.'); return; @@ -60,7 +61,7 @@ export default BaseComponent.extend({ return this.get('model.' + this.get('field')); }, resetValue() { - let me = this; + const me = this; me.set('model.' + me.get('field'), me.get('oldValue')); }, execUpdate() { diff --git a/web/app/components/file-input.js b/web/app/components/file-input.js index 1e63c6d..c79134c 100644 --- a/web/app/components/file-input.js +++ b/web/app/components/file-input.js @@ -1,11 +1,10 @@ -import Ember from 'ember'; import Component from '@ember/component'; -import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; import $ from 'jquery' export default Component.extend({ file: {}, - value: computed.alias('file.file'), + value: alias('file.file'), 'no-file': 'Choose file', 'btn-choose': 'Choose file', didReceiveAttrs() { diff --git a/web/app/components/form-footer-buttons.js b/web/app/components/form-footer-buttons.js index 7deaf36..76782c2 100644 --- a/web/app/components/form-footer-buttons.js +++ b/web/app/components/form-footer-buttons.js @@ -1,6 +1,8 @@ -import Ember from 'ember'; -import BaseComponent from './base-component'; -import { computed } from '@ember/object'; +import BaseComponent from './basic-component'; +import { alias } from '@ember/object/computed'; +import { isArray } from '@ember/array'; +import { setProperties } from '@ember/object'; +import { isNone } from '@ember/utils'; import { inject as service } from '@ember/service'; import $ from 'jquery' @@ -9,12 +11,12 @@ export default BaseComponent.extend({ type: 'create', form: true, state: service('state'), - successMsg: computed.alias('success-message'), - postUrl: computed.alias('post-url'), - backRouteName: computed.alias('back-route'), - backRouteParams: computed.alias('back-route-params'), - hideGoback: computed.alias('no-goback'), - hideSubmit: computed.alias('no-submit'), + successMsg: alias('success-message'), + postUrl: alias('post-url'), + backRouteName: alias('back-route'), + backRouteParams: alias('back-route-params'), + hideGoback: alias('no-goback'), + hideSubmit: alias('no-submit'), 'back-to-list': false, backToList() { const me = this; @@ -29,20 +31,20 @@ export default BaseComponent.extend({ transitionToRoute(name, params, queryParams) { const me = this; let args = [name]; - if (!Ember.isNone(params)) { - if (Ember.isArray(params)) { + if (!isNone(params)) { + if (isArray(params)) { args = args.concat(params); } else if (params !== false) { args.push(params); } } - Ember.isNone(queryParams) || args.push({queryParams: queryParams}); + isNone(queryParams) || args.push({queryParams: queryParams}); me.get('router').transitionTo(...args); }, actions: { goback() { - let me = this; + const me = this; let routeName = me.get('backRouteName'); if (routeName) { me.transitionToRoute(routeName, @@ -57,13 +59,13 @@ export default BaseComponent.extend({ } }, save() { - let me = this; + const me = this; if (!me.validate()) { me.dialog.confirm('Are you sure to submit?', () => { me.postData().then((m) => { console.info('Post Model Result: ', m); // write back - Ember.setProperties(me.getModel(), m); + setProperties(me.getModel(), m); me.alertMessage(); me.send('goback'); }); @@ -75,7 +77,7 @@ export default BaseComponent.extend({ return this.get('type') === 'create'; }, validate() { - let me = this; + const me = this; let vr = me.get('service').validate( me.getModel(), me.get('type') + 'Constraints'); me.set('route.controller.errors', vr || {}); diff --git a/web/app/components/form-input-modal-select.js b/web/app/components/form-input-modal-select.js index 0b8194a..1b810b5 100644 --- a/web/app/components/form-input-modal-select.js +++ b/web/app/components/form-input-modal-select.js @@ -1,12 +1,13 @@ -import Ember from 'ember'; +import { computed } from '@ember/object'; +import { match } from '@ember/object/computed'; import BaseFormInput from './base-form-input'; export default BaseFormInput.extend({ classNames: ['form-group'], classNameBindings: ['hasError:has-error'], - hasError: Ember.computed('route.controller.errors', function() { + hasError: computed('route.controller.errors', function() { return this.get('errors.' + this.get('idField')); }), btnIcon: 'fa-server', - isFaBtnIcon: Ember.computed.match('btnIcon', /^fa-/) + isFaBtnIcon: match('btnIcon', /^fa-/) }); diff --git a/web/app/components/image-input.js b/web/app/components/image-input.js index a0d08b3..c0da8f2 100644 --- a/web/app/components/image-input.js +++ b/web/app/components/image-input.js @@ -1,10 +1,10 @@ import Component from '@ember/component'; -import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; import $ from 'jquery' export default Component.extend({ image: {}, - value: computed.alias('image.file'), + value: alias('image.file'), didReceiveAttrs() { const me = this; me._super(...arguments); diff --git a/web/app/components/image-previews.js b/web/app/components/image-previews.js index 0d23ef8..f207154 100644 --- a/web/app/components/image-previews.js +++ b/web/app/components/image-previews.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import { once } from '@ember/runloop'; import Component from '@ember/component'; import { computed } from '@ember/object'; import $ from 'jquery' @@ -50,7 +50,7 @@ export default Component.extend({ } }); - Ember.run.once(() => { + once(() => { // add a custom loading icon $('#cboxLoadingGraphic').html(''); }); diff --git a/web/app/components/list-select-checkbox.js b/web/app/components/list-select-checkbox.js index 2c4e824..6c195ff 100644 --- a/web/app/components/list-select-checkbox.js +++ b/web/app/components/list-select-checkbox.js @@ -1,9 +1,9 @@ -import Ember from 'ember'; -import BaseComponentMixin from '../mixins/components/base-component'; +import { alias } from '@ember/object/computed'; +import BasicComponent from './basic-component'; -export default Ember.Component.extend(BaseComponentMixin, { +export default BasicComponent.extend({ tagName: 'label', - selectedId: Ember.computed.alias('route.controller.selectedId'), - selectedModel: Ember.computed.alias('route.controller.selectedModel'), + selectedId: alias('route.controller.selectedId'), + selectedModel: alias('route.controller.selectedModel'), classNames: ['pos-rel'] }); diff --git a/web/app/components/main-container.js b/web/app/components/main-container.js index 96a40b2..7f80af9 100644 --- a/web/app/components/main-container.js +++ b/web/app/components/main-container.js @@ -1,13 +1,17 @@ import Component from '@ember/component'; +import { inject as service } from '@ember/service'; import $ from 'jquery' export default Component.extend({ elementId: 'main-container', classNames: ['main-container'], + exportTaskService: service('export-task/service'), sidebarCollapsed: false, didInsertElement() { - let me = this; + const me = this; me._super(...arguments); + + me.get('exportTaskService').startup(); // $('body').removeClass().addClass('login-layout blur-login'); (function($) { basics(); @@ -298,8 +302,6 @@ export default Component.extend({ }) } - - //in small devices display navbar dropdowns like modal boxes function smallDeviceDropdowns() { if(ace.vars['old_ie']) return; diff --git a/web/app/components/modal-dialog.js b/web/app/components/modal-dialog.js index b50cf05..f067d34 100644 --- a/web/app/components/modal-dialog.js +++ b/web/app/components/modal-dialog.js @@ -1,8 +1,7 @@ -import Component from '@ember/component' -import BaseComponentMixin from '../mixins/components/base-component'; +import BasicComponent from './basic-component'; import $ from 'jquery' -export default Component.extend(BaseComponentMixin, { +export default BasicComponent.extend({ classNames: ['modal', 'fade'], 'init-modal': true, 'close-to-parent': true, diff --git a/web/app/components/op-detail.js b/web/app/components/op-detail.js index 964a77c..5275974 100644 --- a/web/app/components/op-detail.js +++ b/web/app/components/op-detail.js @@ -8,8 +8,8 @@ export default Ember.LinkComponent.extend(BaseComponentMixin, { title: '操作详情', activeClass: '', willRender() { - let me = this; - let params = me.get('params'); + const me = this; + const params = me.get('params'); params.unshift(me.get('service.modelName')); params.unshift('op-detail'); params.unshift('操作详情'); diff --git a/web/app/components/pagination-bar.js b/web/app/components/pagination-bar.js index 3af7aa3..7188a32 100644 --- a/web/app/components/pagination-bar.js +++ b/web/app/components/pagination-bar.js @@ -1,21 +1,21 @@ -import Ember from 'ember'; -import BaseComponent from './base-component'; +import BaseComponent from './basic-component'; import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; export default BaseComponent.extend({ classNames: ['widget-toolbox', 'clearfix'], - total: Ember.computed.alias('route.controller.model.total'), + total: alias('route.controller.model.total'), prevPage: computed('currPage', function() { return this.get('currPage') - 1 || 1; }), nextPage: computed('currPage', function() { - let me = this; - let page = me.get('currPage'); + const me = this; + const page = me.get('currPage'); return page + 1 <= me.get('totalPage') ? page + 1 : page; }), currPage: computed('params.page', function() { - let me = this; - let currPage = parseInt(me.get('params.page')); + const me = this; + const currPage = parseInt(me.get('params.page')); console.info('Get current page [' + currPage + ']'); return currPage; }), @@ -23,7 +23,7 @@ export default BaseComponent.extend({ const me = this; const totalPage = me.get('totalPage'); const currPage = me.get('currPage'); - let pages = []; + const pages = []; if (currPage > 4) { pages.push({page: 1, text: 1}); @@ -59,7 +59,7 @@ export default BaseComponent.extend({ allPages: computed('total', function() { const me = this; const totalPage = me.get('totalPage'); - let pages = []; + const pages = []; let i = 0; while (++i <= totalPage) { @@ -68,15 +68,15 @@ export default BaseComponent.extend({ return pages; }), totalPage: computed('total', function() { - let me = this; - let pageSize = me.get('service.pageSize') || 32; + const me = this; + const pageSize = me.get('service.pageSize') || 32; return parseInt((me.get('total') + pageSize - 1) / pageSize); }), actions: { gotoPage(page) { - let me = this; - let router = me.get('router'); - let params = me.get('params'); + const me = this; + const router = me.get('router'); + const params = me.get('params'); console.info('Go to page [' + page + '], params: ', params); router.transitionTo(me.get('routeName'), page, {queryParams: params}); } diff --git a/web/app/components/reload-btn.js b/web/app/components/reload-btn.js index 4d0e935..813c5e1 100644 --- a/web/app/components/reload-btn.js +++ b/web/app/components/reload-btn.js @@ -1,5 +1,4 @@ -import Ember from 'ember'; -import BaseComponent from './base-component'; +import BaseComponent from './basic-component'; export default BaseComponent.extend({ tagName: 'a', diff --git a/web/app/components/search-box.js b/web/app/components/search-box.js index 33f889d..070db68 100644 --- a/web/app/components/search-box.js +++ b/web/app/components/search-box.js @@ -1,12 +1,12 @@ -import Ember from 'ember'; -import BaseComponentMixin from '../mixins/components/base-component'; +import { oneWay } from '@ember/object/computed'; +import BasicComponent from './basic-component'; -export default Ember.Component.extend(BaseComponentMixin, { +export default BasicComponent.extend({ classNames: ['widget-toolbar', 'no-border', 'no-padding'], - searchText: Ember.computed.oneWay('route.controller.search'), + searchText: oneWay('route.controller.search'), actions: { search() { - let me = this; + const me = this; me.set('route.controller.search', me.get('searchText')); } } diff --git a/web/app/components/sortable-th.js b/web/app/components/sortable-th.js index b496ade..4f74d26 100644 --- a/web/app/components/sortable-th.js +++ b/web/app/components/sortable-th.js @@ -1,43 +1,43 @@ -import Ember from 'ember'; -import BaseComponentMixin from '../mixins/components/base-component'; +import { computed } from '@ember/object'; +import BasicComponent from './basic-component'; -export default Ember.Component.extend(BaseComponentMixin, { +export default BasicComponent.extend({ tagName: 'th', - order: Ember.computed('route.controller.orders', function() { + order: computed('route.controller.orders', function() { return this.getDir(); }), - sorting: Ember.computed.none('order'), - asc: Ember.computed.equal('order', 'asc'), - desc: Ember.computed.equal('order', 'desc'), + sorting: computed.none('order'), + asc: computed.equal('order', 'asc'), + desc: computed.equal('order', 'desc'), // classNameBindings: ['asc:sorting_asc', 'desc:sorting_desc', 'sorting:sorting'], attributeBindings: ['style'], getDir() { - let me = this; - let name = me.get('name'); - let orders = me.getOrders(); + const me = this; + const name = me.get('name'); + const orders = me.getOrders(); if (orders && orders.length) { - let order = orders.find(order => order.hasOwnProperty(name)); + const order = orders.find(order => order.hasOwnProperty(name)); if (order) { return order[name]; } } }, getOrders() { - let me = this; - let strOrders = me.get('route.controller.orders'); + const me = this; + const strOrders = me.get('route.controller.orders'); if (strOrders) { return JSON.parse(strOrders); } }, actions: { sort() { - let me = this; + const me = this; let orders = me.getOrders() || []; - let name = me.get('name'); + const name = me.get('name'); if (orders.length) { orders = orders.filter(order => !order.hasOwnProperty(name)); } - let order = {}; + const order = {}; order[name] = me.get('order') === 'asc' ? 'desc' : 'asc'; @@ -46,10 +46,10 @@ export default Ember.Component.extend(BaseComponentMixin, { me.set('route.controller.orders', JSON.stringify(orders)); }, removeSort() { - let me = this; - let orders = me.getOrders(); + const me = this; + const orders = me.getOrders(); if (orders) { - let name = me.get('name'); + const name = me.get('name'); me.set('route.controller.orders', JSON.stringify(orders.filter(order => !order.hasOwnProperty(name)))); } diff --git a/web/app/components/status-cell.js b/web/app/components/status-cell.js index 87f53e7..bb701b0 100644 --- a/web/app/components/status-cell.js +++ b/web/app/components/status-cell.js @@ -1,23 +1,25 @@ -import Ember from 'ember'; +import Component from '@ember/component'; +import { addObserver } from '@ember/object/observers'; +import { computed } from '@ember/object'; -export default Ember.Component.extend({ +export default Component.extend({ tagName: 'span', classNames: ['label', 'label-sm'], classNameBindings: ['enabled:label-success:label-warning'], field: 'enabled', - name: Ember.computed.alias('field'), + name: computed.alias('field'), didReceiveAttrs() { - let me = this; + const me = this; me._super(...arguments); me.set('enabled', me.get(me.getFieldPath())); - Ember.addObserver(me, me.getFieldPath(), function() { + addObserver(me, me.getFieldPath(), function() { me.set('enabled', me.get(me.getFieldPath())); }); }, enabledText: '启用', disabledText: '禁用', getFieldPath() { - let me = this; + const me = this; return 'model.' + (me.get('field') || 'enabled'); }, }); diff --git a/web/app/components/status-toggle-button.js b/web/app/components/status-toggle-button.js index 3546eec..36b9e6d 100644 --- a/web/app/components/status-toggle-button.js +++ b/web/app/components/status-toggle-button.js @@ -1,5 +1,6 @@ -import Ember from 'ember'; -import BaseComponent from './base-component'; +import { computed } from '@ember/object'; +import { alias } from '@ember/object/computed'; +import BaseComponent from './basic-component'; export default BaseComponent.extend({ tagName: 'a', @@ -10,13 +11,13 @@ export default BaseComponent.extend({ disabledText: 'Disable', enabledOp: 'enable', disabledOp: 'disable', - enabled: Ember.computed.alias('model.enabled'), - title: Ember.computed('enabled', function() { + enabled: alias('model.enabled'), + title: computed('enabled', function() { let me = this; return this.get('enabled') ? me.get('disabledText') : me.get('enabledText'); }), - 'data-original-title': Ember.computed.alias('title'), - op: Ember.computed('enabled', function() { + 'data-original-title': alias('title'), + op: computed('enabled', function() { let me = this; return this.get('enabled') ? me.get('disabledOp') || me.get('disabledText') diff --git a/web/app/components/top-navbar.js b/web/app/components/top-navbar.js index c1ac150..6cb370c 100644 --- a/web/app/components/top-navbar.js +++ b/web/app/components/top-navbar.js @@ -1,4 +1,4 @@ -import BaseComponent from './base-component'; +import BaseComponent from './basic-component'; import { alias } from '@ember/object/computed'; import { inject as service } from '@ember/service'; diff --git a/web/app/mixins/components/base-component.js b/web/app/mixins/components/base-component.js index de26c84..323bdd2 100644 --- a/web/app/mixins/components/base-component.js +++ b/web/app/mixins/components/base-component.js @@ -1,19 +1,23 @@ -import Ember from 'ember'; +import Mixin from '@ember/object/mixin'; +import { inject as service } from '@ember/service'; +import { alias } from '@ember/object/computed'; +import { computed } from '@ember/object'; +import { getOwner } from '@ember/application'; -export default Ember.Mixin.create({ - toolService: Ember.inject.service('tool-service'), - routeName: Ember.computed.alias('router.currentRouteName'), +export default Mixin.create({ + toolService: service('tool-service'), + routeName: alias('router.currentRouteName'), 'trim-index': true, - route: Ember.computed('routeName', function() { + route: computed('routeName', function() { let me = this; let routeName = me.get('routeName'); return me.getRoute(me.get('trim-index') ? routeName.replace(/\.index$/, '') : routeName); }), - service: Ember.computed('routeName', function() { + service: computed('routeName', function() { return this.getService(); }), - params: Ember.computed('router.location.lastSetURL', function() { + params: computed('router.location.lastSetURL', function() { let me = this; let routeName = me.get('routeName'); return me.getRouteParams(me.get('trim-index') ? @@ -23,14 +27,14 @@ export default Ember.Mixin.create({ return this.get('route').paramsFor(routeName); }, getRoute(routeName) { - return Ember.getOwner(this).lookup( + return getOwner(this).lookup( 'route:' + (routeName || this.get('routeName'))); }, getParentRouteName(routeName) { return routeName.replace(/\.[^\.]+$/, ''); }, getService(name) { - let me = this; + const me = this; return name ? me.get('toolService').getServiceByRouteName(name) : me.getRoute().get('service') || me.get('toolService').getServiceByRouteName(me.get('routeName')); diff --git a/web/app/mixins/services/base-service.js b/web/app/mixins/services/base-service.js deleted file mode 100644 index f32afca..0000000 --- a/web/app/mixins/services/base-service.js +++ /dev/null @@ -1,86 +0,0 @@ -import Ember from 'ember'; -import $ from 'jquery' - -export default Ember.Mixin.create({ - store: Ember.inject.service(), - message: Ember.inject.service(), - pageSize: 32, - constraints: {}, - createConstraints: null, - updateConstraints: null, - find(params) { - console.debug('Find Model: ', params); - return this._getStore().find(this.get('modelName'), params); - }, - list(start, limit, params) { - console.debug('List Models Start: ', start, ', Limit: ', limit, ", Search: ", params); - return this._getStore().list(this.get('modelName'), start, limit, params); - }, - listPage(page, params) { - page > 0 || (page = 1); - let me = this; - let pageSize = me.get('pageSize'); - return me.list((page - 1) * pageSize, pageSize, params); - }, - create(model) { - console.debug('Create Model: ', model); - return this._getStore().create(this.get('modelName'), model); - }, - update(model, defaultPromise) { - console.debug('Update Model: ', model); - let me = this; - let p = me._getStore().update(me.get('modelName'), model); - if (defaultPromise) { - p.then((m) => { - console.debug('After Update: ', m); - !(model instanceof FormData) && - Object.keys(m).forEach((prop) => { - Ember.set(model, prop, m[prop]); - }); - me.get('message').alert('Updated successfully'); - }) - } - return p; - }, - del(params) { - console.debug('Update Model: ', params); - return this._getStore().del(this.get('modelName'), params); - }, - ajaxGet(path, params) { - return this._getStore().modelAjaxGet(this.get('modelName'), path, params); - }, - ajaxPost(path, params) { - return this._getStore().modelAjaxPost(this.get('modelName'), path, params); - }, - validate(model, constraints) { - let me = this; - console.debug('Validate Model: ', model); - if (constraints) { - if ($.type(constraints) === 'string') { - constraints = me.get(constraints); - } - else if ($.type(constraints) !== 'object') { - validation = me.get('constraints'); - } - } - else { - constraints = me.get('constraints'); - } - return validate(model, constraints || me.get('constraints')); - }, - createValidate(model) { - console.debug('Create Validate Model: ', model); - let me = this; - let constraints = me.get('createConstraints') || me.get('constraints') || null; - return constraints && validate(model, constraints); - }, - updateValidate(model) { - console.debug('Update Validate Model: ', model); - let me = this; - let constraints = me.get('updateConstraints') || me.get('constraints') || null; - return constraints && validate(model, constraints); - }, - _getStore() { - return this.get('store'); - } -}); diff --git a/web/app/router.js b/web/app/router.js index d6a53e2..82903dc 100644 --- a/web/app/router.js +++ b/web/app/router.js @@ -80,6 +80,10 @@ Router.map(function() { this.route('create'); this.route('edit', {path: '/:id/edit'}); }); + + this.route('export-task', function() { + this.route('list', {path: '/list/:page'}); + }); }); export default Router; diff --git a/web/app/routes/application.js b/web/app/routes/application.js index 725c2ba..cdd6a97 100644 --- a/web/app/routes/application.js +++ b/web/app/routes/application.js @@ -12,18 +12,19 @@ export default Route.extend({ } }, beforeModel: function(transition) { - console.info('Before Application Model.', transition); + console.info('Before application model.', transition); this.transitionIntercept(transition); }, activate() { - console.info('Application Activate.'); + const me = this; + console.info('Application activate.'); $('body').addClass('no-skin'); try{ace.settings.check('navbar', 'fixed');}catch(e){console.log(e)} try{ace.settings.check('main-container', 'fixed');}catch(e){console.log(e)} }, actions: { loading(transition, originRoute) { - console.info('Application Loading...'); + console.info('Application loading...'); // var appCtrl = this.controllerFor('application'); this.router.one('didTransition', function() { // appCtrl.set('loading', false); diff --git a/web/app/routes/customer/list.js b/web/app/routes/customer/list.js index 91a25e8..2ae9c41 100644 --- a/web/app/routes/customer/list.js +++ b/web/app/routes/customer/list.js @@ -1,4 +1,6 @@ -import Ember from 'ember'; +import EmberObject from '@ember/object'; + +import { observer, set } from '@ember/object'; import BaseListRoute from './../base-list'; const cols = ['showId', @@ -20,7 +22,7 @@ const cols = ['showId', ]; const config = { showAll: false, - showAllChanged: Ember.observer('showAll', function() { + showAllChanged: observer('showAll', function() { let me = this; if (!me.get('lock')) { let val = me.get('showAll'); @@ -29,7 +31,7 @@ const config = { }); } }), - colChanged: Ember.observer(...cols.concat(function() { + colChanged: observer(...cols.concat(function() { let me = this; me.set('lock', true); me.set('showAll', cols.map(col => { @@ -60,7 +62,7 @@ config.countOfShowing = cols.filter(col => { return config[col]; }).length + 1; -const TableOptions = Ember.Object.extend(config); +const TableOptions = EmberObject.extend(config); export default BaseListRoute.extend({ queryParams: { @@ -87,10 +89,16 @@ export default BaseListRoute.extend({ }, actions: { expandYtdSales(row) { - Ember.set(row, 'expand', true); + set(row, 'expand', true); }, collapseYtdSales(row) { - Ember.set(row, 'expand', false); + set(row, 'expand', false); + }, + asyncExport() { + const me = this; + me.get('service').ajaxPost('async-export').then(msg => { + me.get('message').alert('Export task created.'); + }); } } }); diff --git a/web/app/routes/export-task/list.js b/web/app/routes/export-task/list.js new file mode 100644 index 0000000..6d603fc --- /dev/null +++ b/web/app/routes/export-task/list.js @@ -0,0 +1,5 @@ +import BaseListRoute from './../base-list'; + +export default BaseListRoute.extend({ + breadcrumbs: [{text: 'Export Tasks'}] +}); diff --git a/web/app/routes/home-page/list.js b/web/app/routes/home-page/list.js index 787f96b..d9f2eba 100644 --- a/web/app/routes/home-page/list.js +++ b/web/app/routes/home-page/list.js @@ -1,4 +1,3 @@ -import Ember from 'ember'; import BaseListRoute from './../base-list'; export default BaseListRoute.extend({ diff --git a/web/app/routes/import-record/list.js b/web/app/routes/import-record/list.js index 343dfbb..8330817 100644 --- a/web/app/routes/import-record/list.js +++ b/web/app/routes/import-record/list.js @@ -1,4 +1,3 @@ -import Ember from 'ember'; import BaseListRoute from './../base-list'; export default BaseListRoute.extend({ diff --git a/web/app/services/export-task/service.js b/web/app/services/export-task/service.js new file mode 100644 index 0000000..cbd9fb9 --- /dev/null +++ b/web/app/services/export-task/service.js @@ -0,0 +1,15 @@ +import BaseService from '../service'; +import $ from 'jquery'; + +export default BaseService.extend({ + modelName: 'ExportTask', + startup: function() { + 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); + } + }); + } +}); diff --git a/web/app/services/import-record/service.js b/web/app/services/import-record/service.js index a42b79f..346ece0 100644 --- a/web/app/services/import-record/service.js +++ b/web/app/services/import-record/service.js @@ -1,7 +1,6 @@ -import Ember from 'ember'; -import BaseServiceMixin from '../../mixins/services/base-service'; +import BaseService from '../service'; -export default Ember.Service.extend(BaseServiceMixin, { +export default BaseService.extend({ modelName: 'ImportRecord', pageSize: 128 }); diff --git a/web/app/services/message.js b/web/app/services/message.js index a16b938..22b4a06 100644 --- a/web/app/services/message.js +++ b/web/app/services/message.js @@ -1,11 +1,20 @@ -import Ember from 'ember'; +import Service from '@ember/service'; import $ from 'jquery' -export default Ember.Service.extend({ +export default Service.extend({ alert(msg) { - this._show_alert_(msg); + toastr.success(msg); + }, + info(msg) { + toastr.info(msg); }, warn(msg) { + toastr.warning(msg); + }, + alert2(msg) { + this._show_alert_(msg); + }, + warn2(msg) { this._show_alert_(msg, '#F6F0F0'); }, _show_alert_(msg, bg) { diff --git a/web/app/services/service.js b/web/app/services/service.js index e5a0751..8b50788 100644 --- a/web/app/services/service.js +++ b/web/app/services/service.js @@ -1,4 +1,88 @@ -import Ember from 'ember'; -import BaseServiceMixin from '../mixins/services/base-service'; +import Service from '@ember/service'; +import { set } from '@ember/object'; +import { typeOf } from '@ember/utils'; +import { inject as service } from '@ember/service'; -export default Ember.Service.extend(BaseServiceMixin, {}); +export default Service.extend({ + store: service(), + message: service(), + pageSize: 32, + constraints: {}, + createConstraints: null, + updateConstraints: null, + find(params) { + console.debug('Find model: ', params); + return this._getStore().find(this.get('modelName'), params); + }, + list(start, limit, params) { + console.debug('List models start: ', start, ', limit: ', limit, ", search: ", params); + return this._getStore().list(this.get('modelName'), start, limit, params); + }, + listPage(page, params) { + page > 0 || (page = 1); + let me = this; + let pageSize = me.get('pageSize'); + return me.list((page - 1) * pageSize, pageSize, params); + }, + create(model) { + console.debug('Create model: ', model); + return this._getStore().create(this.get('modelName'), model); + }, + update(model, defaultPromise) { + console.debug('Update model: ', model); + let me = this; + let p = me._getStore().update(me.get('modelName'), model); + if (defaultPromise) { + p.then((m) => { + console.debug('After update: ', m); + !(model instanceof FormData) && + Object.keys(m).forEach((prop) => { + set(model, prop, m[prop]); + }); + me.get('message').alert('Updated successfully'); + }) + } + return p; + }, + del(params) { + console.debug('Update Model: ', params); + return this._getStore().del(this.get('modelName'), params); + }, + ajaxGet(path, params) { + return this._getStore().modelAjaxGet(this.get('modelName'), path, params); + }, + ajaxPost(path, params) { + return this._getStore().modelAjaxPost(this.get('modelName'), path, params); + }, + validate(model, constraints) { + let me = this; + console.debug('Validate model: ', model); + if (constraints) { + if (typeOf(constraints) === 'string') { + constraints = me.get(constraints); + } + else if (typeOf(constraints) !== 'object') { + validation = me.get('constraints'); + } + } + else { + constraints = me.get('constraints'); + } + return validate(model, constraints || me.get('constraints')); + }, + createValidate(model) { + console.debug('Create validate model: ', model); + let me = this; + let constraints = me.get('createConstraints') || me.get('constraints') || null; + return constraints && validate(model, constraints); + }, + updateValidate(model) { + console.debug('Update validate model: ', model); + let me = this; + let constraints = me.get('updateConstraints') || me.get('constraints') || null; + return constraints && validate(model, constraints); + }, + _getStore() { + return this.get('store'); + } +}); \ No newline at end of file diff --git a/web/app/services/store.js b/web/app/services/store.js index f1de7a7..534791f 100644 --- a/web/app/services/store.js +++ b/web/app/services/store.js @@ -1,7 +1,13 @@ import Ember from 'ember'; +import Service from '@ember/service'; import $ from 'jquery' +import { Promise } from 'rsvp'; +import { dasherize } from '@ember/string'; +import { run } from '@ember/runloop'; +import { typeOf } from '@ember/utils'; -export default Ember.Service.extend({ + +export default Service.extend({ list(modelName, start, limit, params) { var p = { start: start, @@ -44,14 +50,14 @@ export default Ember.Service.extend({ }, _ajax_request(method, url, params) { let me = this; - return new Ember.RSVP.Promise((resolve, reject) => { - let paramsType = $.type(params); + return new Promise((resolve, reject) => { + const paramsType = typeOf(params); me.ajax[method ? method : 'doGet'](url, paramsType === 'string' || paramsType === 'number' ? {id: params} : params, (data) => { - Ember.run(null, resolve, data); + run(null, resolve, data); }, (msg, r) => { reject(msg); me.dialog.error(msg || 'Ajax request erorr caused'); @@ -60,7 +66,7 @@ export default Ember.Service.extend({ }, _pathForType(modelName, path) { return (/^[a-zA-Z_][a-zA-Z0-9_]+$/.test(modelName) ? - Ember.String.dasherize(modelName) : modelName) + + dasherize(modelName) : modelName) + (/^\//.test(path) ? path : '/' + path); } }); diff --git a/web/app/services/tool-service.js b/web/app/services/tool-service.js index 8aa0d67..ae9741c 100644 --- a/web/app/services/tool-service.js +++ b/web/app/services/tool-service.js @@ -1,12 +1,13 @@ -import Ember from 'ember'; +import Service from '@ember/service'; +import { getOwner } from '@ember/application'; import BaseService from './service'; import Ajax from './ajax'; import Store from './store'; -export default Ember.Service.extend({ +export default Service.extend({ getServiceByRouteName: function(routeName) { let me = this; - let container = Ember.getOwner(me); + let container = getOwner(me); let service = container.lookup('service:' + routeName); console.debug(`No Route Service [${routeName}] Found, Try To Find Model Service`); let indexTrimmedRouteName = null; diff --git a/web/app/services/user/service.js b/web/app/services/user/service.js index 6e2daf4..a7947d8 100644 --- a/web/app/services/user/service.js +++ b/web/app/services/user/service.js @@ -1,4 +1,3 @@ -import Ember from 'ember'; import BaseService from '../service'; export default BaseService.extend({ diff --git a/web/app/services/websocket.js b/web/app/services/websocket.js index 441febf..a458e22 100644 --- a/web/app/services/websocket.js +++ b/web/app/services/websocket.js @@ -42,7 +42,7 @@ export default Service.extend({ 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)); + $.trigger('WEBSOCKET', [JSON.parse(msg.body)]); })); me.set('connected', true); }; @@ -61,6 +61,10 @@ export default Service.extend({ console.log('Additional details: ', frame.body); me.set('connected', false); }; + + client.onWebSocketClose = function(event) { + console.log('On websocket close.', event); + }; client.activate(); me.set('client', client); diff --git a/web/app/styles/app.less b/web/app/styles/app.less index ae4f466..298afc6 100644 --- a/web/app/styles/app.less +++ b/web/app/styles/app.less @@ -107,4 +107,21 @@ input[type="number"] { word-wrap: break-word; /* Internet Explorer 5.5+ */ background-color: inherit; border: 0; +} + +.export-task-badge { + position: absolute; + top: 4px; + left: 24px; + width: 14px; + height: 14px; + font-size: 10px; + border-radius: 50%; + color: #fff; + background-color: rgba(255, 0, 0, 0.8); + // rgba(0, 0, 0, 0.7); + + display: flex; + justify-content: center; + align-items: center; } \ No newline at end of file diff --git a/web/app/templates/components/a-btn.hbs b/web/app/templates/components/a-btn.hbs new file mode 100644 index 0000000..fb5c4b1 --- /dev/null +++ b/web/app/templates/components/a-btn.hbs @@ -0,0 +1 @@ +{{yield}} \ No newline at end of file diff --git a/web/app/templates/components/main-container.hbs b/web/app/templates/components/main-container.hbs index 6717cf1..8277bf7 100644 --- a/web/app/templates/components/main-container.hbs +++ b/web/app/templates/components/main-container.hbs @@ -98,6 +98,13 @@ Database Backup +
  • + + + 21 + Export Task {{#if this.exportTaskService.countUndownloaded}}{{this.exportTaskService.countUndownloaded}}{{/if}} + +
  • {{/if}} @@ -153,7 +160,7 @@