add state, #IHVSN
This commit is contained in:
parent
a5a86ba38c
commit
04c3843c9f
@ -5,6 +5,7 @@ import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import javax.validation.Valid;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.pudonghot.ambition.crm.model.CustomerProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.chyxion.tigon.mybatis.Search;
|
||||
@ -221,6 +222,7 @@ public class CustomerController
|
||||
|
||||
if (StringUtils.isBlank(strFilters)) {
|
||||
log.debug("No filters given.");
|
||||
defaultFilter(search, "status");
|
||||
return search;
|
||||
}
|
||||
|
||||
@ -259,6 +261,9 @@ public class CustomerController
|
||||
log.info("Col [{}] filters [{}] found.", col, filters);
|
||||
search.in(col, filters);
|
||||
}
|
||||
else {
|
||||
defaultFilter(search, field);
|
||||
}
|
||||
|
||||
// filter year
|
||||
if (CustomerYearToDateSale.YEAR.equals(col)) {
|
||||
@ -267,4 +272,11 @@ public class CustomerController
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
private void defaultFilter(final Search search, final String field) {
|
||||
// default no NA
|
||||
if ("status".equals(field)) {
|
||||
search.ne(CRITERION_COLS.get(field), CustomerProperty.STATUS_NA_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.pudonghot.ambition.crm.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import me.chyxion.tigon.mybatis.Search;
|
||||
@ -7,11 +8,11 @@ import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import me.chyxion.tigon.model.ViewModel;
|
||||
import me.chyxion.tigon.model.ListResult;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import com.pudonghot.ambition.crm.model.User;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import com.pudonghot.ambition.crm.model.CustomerProperty;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -40,9 +41,9 @@ public class CustomerPropertyController
|
||||
@Max(512)
|
||||
@RequestParam(value = "limit", defaultValue = "16")
|
||||
final int limit,
|
||||
@NotBlank
|
||||
@NotNull
|
||||
@RequestParam("type")
|
||||
final String type,
|
||||
final CustomerProperty.Type type,
|
||||
@RequestParam(value = "enabled", required = false)
|
||||
final String enabled,
|
||||
@RequestParam(value = "search", required = false)
|
||||
@ -57,6 +58,22 @@ public class CustomerPropertyController
|
||||
return listViewModels(search, start, limit, strSearch, null);
|
||||
}
|
||||
|
||||
@RequestMapping("/list-for-select")
|
||||
public List<ViewModel<CustomerProperty>> listForSelect(
|
||||
@NotNull
|
||||
@RequestParam("type")
|
||||
final CustomerProperty.Type type,
|
||||
@RequestParam(value = "enabled", required = false)
|
||||
final String enabled) {
|
||||
final Search search = new Search(CustomerProperty.TYPE, type)
|
||||
.asc(CustomerProperty.SORT);
|
||||
if (StringUtils.isNotBlank(enabled)) {
|
||||
search.eq(CustomerProperty.ENABLED,
|
||||
Boolean.parseBoolean(enabled));
|
||||
}
|
||||
return queryService.listViewModels(search);
|
||||
}
|
||||
|
||||
@RequiresRoles(User.ROLE_ADMIN)
|
||||
@RequestMapping(value = "/create", method = RequestMethod.POST)
|
||||
public ViewModel<CustomerProperty> create(
|
||||
|
@ -80,7 +80,7 @@ public class CustomerPropertyServiceSupport
|
||||
final CustomerProperty status = new CustomerProperty();
|
||||
status.setId(id);
|
||||
status.setName(name);
|
||||
status.setType(CustomerProperty.TYPE_STATUS);
|
||||
status.setType(CustomerProperty.Type.STATUS);
|
||||
status.setEnabled(true);
|
||||
status.setNote(note);
|
||||
status.setCreatedBy(operator);
|
||||
|
@ -2,6 +2,8 @@ package com.pudonghot.ambition.crm.service.support;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.InputStream;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chyxion.tigon.mybatis.Search;
|
||||
import me.chyxion.tigon.model.ViewModel;
|
||||
@ -62,14 +64,26 @@ public class CustomerServiceSupport
|
||||
|
||||
// accounts
|
||||
final List<CustomerPermission> permissions = customerPermissionMapper.list(
|
||||
new Search(CustomerPermission.CUSTOMER_ID, id)
|
||||
.eq(CustomerPermission.ENABLED, true));
|
||||
new Search(CustomerPermission.CUSTOMER_ID, id)
|
||||
.eq(CustomerPermission.ENABLED, true));
|
||||
final List<String> accounts = new ArrayList<>(permissions.size());
|
||||
for (CustomerPermission permission : permissions) {
|
||||
accounts.add(permission.getUserAccount());
|
||||
}
|
||||
viewModel.setAttr("users", userService.listByCustomerId(id));
|
||||
viewModel.setAttr("issues", customerIssueService.listRecent(id, 128));
|
||||
viewModel.setAttr("applications", customerPropertyMapper.listApplication(id)
|
||||
.stream().map(CustomerProperty::getId).collect(Collectors.toList()));
|
||||
viewModel.setAttr("statusList", customerPropertyMapper.list(
|
||||
new Search(CustomerProperty.TYPE,
|
||||
CustomerProperty.Type.STATUS)
|
||||
.eq(CustomerProperty.ENABLED, true)
|
||||
.asc(CustomerProperty.SORT)));
|
||||
viewModel.setAttr("applicationList", customerPropertyMapper.list(
|
||||
new Search(CustomerProperty.TYPE,
|
||||
CustomerProperty.Type.APPLICATION)
|
||||
.eq(CustomerProperty.ENABLED, true)
|
||||
.asc(CustomerProperty.SORT)));
|
||||
}
|
||||
return viewModel;
|
||||
}
|
||||
@ -95,7 +109,7 @@ public class CustomerServiceSupport
|
||||
|
||||
result.setAttr("salespersonList", mapper.listSalesperson());
|
||||
result.setAttr("statusList",
|
||||
customerPropertyMapper.listForFilter(CustomerProperty.TYPE_STATUS));
|
||||
customerPropertyMapper.listForFilter(CustomerProperty.Type.STATUS));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ server.port=8088
|
||||
# MySQL
|
||||
|
||||
datasource.host=127.0.0.1
|
||||
datasource.port=43306
|
||||
datasource.database-name=ambition_crm
|
||||
datasource.port=63306
|
||||
datasource.database-name=ambition_crm_test
|
||||
datasource.username=root
|
||||
datasource.password=696@2^~)oZ@^#*Q
|
||||
|
||||
|
@ -101,6 +101,18 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>**/**Mapper.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
|
@ -1,13 +1,13 @@
|
||||
package com.pudonghot.ambition.crm.mapper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import me.chyxion.tigon.mybatis.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import com.pudonghot.ambition.crm.model.CustomerProperty;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @version 0.0.1
|
||||
* @author Auto Generated <br>
|
||||
@ -16,15 +16,29 @@ import java.util.Map;
|
||||
*/
|
||||
public interface CustomerPropertyMapper extends BaseMapper<String, CustomerProperty> {
|
||||
|
||||
int findNextSort(@Param("type") String type);
|
||||
/**
|
||||
* find next sort
|
||||
* @param type type
|
||||
* @return sort
|
||||
*/
|
||||
int findNextSort(
|
||||
@NotNull
|
||||
@Param("type")
|
||||
CustomerProperty.Type type);
|
||||
|
||||
|
||||
/**
|
||||
* list for customer filter
|
||||
* @param type
|
||||
* @return
|
||||
* @param type type
|
||||
* @return custom props
|
||||
*/
|
||||
List<Map<String, Object>> listForFilter(
|
||||
@NotBlank
|
||||
@NotNull
|
||||
@Param("type")
|
||||
String type);
|
||||
CustomerProperty.Type type);
|
||||
|
||||
List<CustomerProperty> listApplication(
|
||||
@NotBlank
|
||||
@Param("customerId")
|
||||
String customerId);
|
||||
}
|
||||
|
@ -24,4 +24,14 @@
|
||||
where type = #{type}
|
||||
order by sort
|
||||
</select>
|
||||
|
||||
<select id="listApplication" resultType="com.pudonghot.ambition.crm.model.CustomerProperty">
|
||||
select p.*
|
||||
from <include refid="table" /> p
|
||||
join crm_customer_application a
|
||||
on p.id = a.property_id
|
||||
where p.type = 'APPLICATION'
|
||||
and a.id = #{customerId}
|
||||
order by p.sort
|
||||
</select>
|
||||
</mapper>
|
@ -31,7 +31,7 @@
|
||||
p:dataSource-ref="dataSource"
|
||||
p:typeAliasesPackage="com.pudonghot.ambition.crm.model"
|
||||
p:configLocation="classpath:mybatis/mybatis-config.xml"
|
||||
p:mapperLocations="classpath*:mybatis/mappers/**/*-mapper.xml" />
|
||||
p:mapperLocations="classpath*:com/pudonghot/ambition/crm/mapper/*Mapper.xml" />
|
||||
<!-- MyBatis Mappers Auto Scan -->
|
||||
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
|
||||
p:basePackage="com.pudonghot.ambition.crm.mapper"
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pudonghot.ambition.crm.mapper;
|
||||
|
||||
import com.pudonghot.ambition.crm.model.CustomerProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -10,6 +11,8 @@ import org.springframework.test.context.junit4.AbstractTransactionalJUnit4Spring
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @version 0.0.1
|
||||
@ -17,6 +20,7 @@ import java.util.Date;
|
||||
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
|
||||
* Jun 19, 2017 10:32:35 PM
|
||||
*/
|
||||
@Slf4j
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath*:spring/spring-*.xml")
|
||||
public class CustomerPropertyMapperTest extends AbstractTransactionalJUnit4SpringContextTests {
|
||||
@ -25,44 +29,8 @@ public class CustomerPropertyMapperTest extends AbstractTransactionalJUnit4Sprin
|
||||
|
||||
@Test
|
||||
public void mapperTest() {
|
||||
// String id = String.valueOf(new Date().getTime());
|
||||
// init model
|
||||
CustomerProperty m = new CustomerProperty();
|
||||
String id = "id";
|
||||
m.setId(id);
|
||||
m.setDateCreated(new Date());
|
||||
m.setType("s");
|
||||
m.setName("s");
|
||||
m.setSort(1);
|
||||
mapper.insert(m);
|
||||
Assert.assertTrue(mapper.list(null).size() > 0);
|
||||
/*
|
||||
// Your Test Logics
|
||||
CustomerProperty m1 = mapper.find(id);
|
||||
// asserts
|
||||
Assert.assertEquals(id, m1.getId());
|
||||
Assert.assertEquals("s", m.getType());
|
||||
Assert.assertEquals("s", m.getName());
|
||||
Assert.assertEquals(1, m.getSort());
|
||||
// update
|
||||
m.setDateUpdated(new Date());
|
||||
m.setType("S");
|
||||
m.setName("S");
|
||||
m.setSort(2);
|
||||
mapper.update(m);
|
||||
m1 = mapper.find(id);
|
||||
// asserts
|
||||
Assert.assertEquals(id, m1.getId());
|
||||
Assert.assertNotNull(m1.getDateUpdated());
|
||||
Assert.assertEquals("S", m.getType());
|
||||
Assert.assertEquals("S", m.getName());
|
||||
Assert.assertEquals(2, m.getSort());
|
||||
// list
|
||||
Assert.assertTrue(mapper.list(null).size() > 0);
|
||||
// delete
|
||||
mapper.delete(id);
|
||||
m1 = mapper.find(id);
|
||||
Assert.assertNull(m1);
|
||||
*/
|
||||
List<Map<String, Object>> maps =
|
||||
mapper.listForFilter(CustomerProperty.Type.STATUS);
|
||||
log.info("status: [{}].", maps);
|
||||
}
|
||||
}
|
||||
|
38
server/mapper/src/test/resources/log4j2.xml
Normal file
38
server/mapper/src/test/resources/log4j2.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Properties>
|
||||
<Property name="log.level">DEBUG</Property>
|
||||
<Property name="log.dir">.logs</Property>
|
||||
<Property name="pattern">%-d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%t][%c{1}] %m%n</Property>
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="${pattern}" />
|
||||
</Console>
|
||||
<RollingFile name="File"
|
||||
fileName="${log.dir}/${project.artifactId}.log"
|
||||
filePattern="${log.dir}/$${date:yyyy-MM}/${project.artifactId}-%d{yyyy-MM-dd}-%i.log">
|
||||
<PatternLayout pattern="${pattern}" />
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy />
|
||||
<SizeBasedTriggeringPolicy size="16 MB" />
|
||||
</Policies>
|
||||
<DefaultRolloverStrategy max="32" />
|
||||
</RollingFile>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="org.springframework" level="INFO" additivity="false">
|
||||
<AppenderRef ref="File" />
|
||||
</Logger>
|
||||
<Logger name="org.apache" level="WARN" additivity="false">
|
||||
<AppenderRef ref="File" />
|
||||
</Logger>
|
||||
<Logger name="org.hibernate.validator" level="WARN" additivity="false">
|
||||
<AppenderRef ref="File" />
|
||||
</Logger>
|
||||
<Root level="${log.level}" additivity="false">
|
||||
<AppenderRef ref="File" level="${log.level}" />
|
||||
<AppenderRef ref="Console" level="${log.level}" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
@ -1,4 +1,6 @@
|
||||
# MySQL
|
||||
db.url=jdbc:mysql://127.0.0.1:43306/pudong_hot?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
|
||||
db.user=root
|
||||
db.password=696@2^~)oZ@^#*Q
|
||||
datasource.host=127.0.0.1
|
||||
datasource.port=63306
|
||||
datasource.database-name=ambition_crm
|
||||
datasource.username=root
|
||||
datasource.password=696@2^~)oZ@^#*Q
|
||||
|
@ -3,7 +3,9 @@ package com.pudonghot.ambition.crm.form.create;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.chyxion.tigon.form.FC2;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import com.pudonghot.ambition.crm.model.CustomerProperty;
|
||||
|
||||
/**
|
||||
* @version 0.0.1
|
||||
@ -18,8 +20,8 @@ public class CustomerPropertyFormForCreate extends FC2<String> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Properties
|
||||
@NotBlank
|
||||
private String type;
|
||||
@NotNull
|
||||
private CustomerProperty.Type type;
|
||||
@NotBlank
|
||||
private String name;
|
||||
}
|
||||
|
@ -22,7 +22,11 @@ public class CustomerProperty extends M3<String, String> {
|
||||
/**
|
||||
* customer status: 已获得,活动的,市场失败,项目取消,关闭
|
||||
*/
|
||||
public static final String TYPE_STATUS = "STATUS";
|
||||
// public static final String TYPE_STATUS = "STATUS";
|
||||
public enum Type {
|
||||
STATUS,
|
||||
APPLICATION,
|
||||
}
|
||||
|
||||
// system status
|
||||
public static final String STATUS_ACTIVE_ID = "STATUS_ACTIVE";
|
||||
@ -41,7 +45,7 @@ public class CustomerProperty extends M3<String, String> {
|
||||
|
||||
// Properties
|
||||
@NotUpdate
|
||||
private String type;
|
||||
private Type type;
|
||||
private String name;
|
||||
@NotUpdateWhenNull
|
||||
private Integer sort;
|
||||
|
@ -25,7 +25,7 @@
|
||||
<mongodb.version>3.2.0</mongodb.version>
|
||||
<tigon.version>0.0.1-SNAPSHOT</tigon.version>
|
||||
<spring.version>4.3.8.RELEASE</spring.version>
|
||||
<spring-boot.version>1.5.4.RELEASE</spring-boot.version>
|
||||
<spring-boot.version>1.5.10.RELEASE</spring-boot.version>
|
||||
<shiro.version>1.3.2</shiro.version>
|
||||
<aspectj.version>1.8.10</aspectj.version>
|
||||
</properties>
|
||||
|
@ -1,46 +1,54 @@
|
||||
import Ember from 'ember';
|
||||
import BaseComponent from './base-component';
|
||||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default BaseComponent.extend({
|
||||
classNames: ['wizard-actions'],
|
||||
type: 'create',
|
||||
form: true,
|
||||
didReceiveAttrs() {
|
||||
state: service('state'),
|
||||
successMsg: computed.alias('success-message'),
|
||||
postUrl: computed.alias('post-url'),
|
||||
backRouteName: computed.alias('back-route'),
|
||||
backRouteParams: computed.alias('back-route-params'),
|
||||
backToList() {
|
||||
const me = this;
|
||||
me._super(...arguments);
|
||||
let backRouteName = me.get('backRouteName');
|
||||
if (Ember.isNone(backRouteName)) {
|
||||
let listRouteName = me.get('routeName').replace(/[^.]+$/, 'list');
|
||||
// find route
|
||||
if (!me.getRoute(listRouteName)) {
|
||||
// no list route found, find parent
|
||||
listRouteName = listRouteName.replace(/[^.]+\.[^.]+$/, 'list');
|
||||
}
|
||||
me.set('backRouteName', listRouteName);
|
||||
// list route params
|
||||
Ember.isNone(me.get('backRouteParams'))
|
||||
&& me.set('backRouteParams', 1);
|
||||
let listRouteName = me.get('routeName').replace(/[^.]+$/, 'list');
|
||||
// find route
|
||||
if (!me.getRoute(listRouteName)) {
|
||||
// no list route found, find parent
|
||||
listRouteName = listRouteName.replace(/[^.]+\.[^.]+$/, 'list');
|
||||
}
|
||||
me.transitionToRoute(listRouteName, 1);
|
||||
},
|
||||
transitionToRoute(name, params, queryParams) {
|
||||
const me = this;
|
||||
let args = [name];
|
||||
if (!Ember.isNone(params)) {
|
||||
if (Ember.isArray(params)) {
|
||||
args = args.concat(params);
|
||||
}
|
||||
else if (params !== false) {
|
||||
args.push(params);
|
||||
}
|
||||
}
|
||||
Ember.isNone(queryParams) || args.push({queryParams: queryParams});
|
||||
me.get('router').transitionTo(...args);
|
||||
},
|
||||
actions: {
|
||||
goback() {
|
||||
let me = this;
|
||||
let router = me.get('router');
|
||||
let routeName = me.get('backRouteName');
|
||||
let routeParams = me.get('backRouteParams');
|
||||
let queryParams = me.get('backRouteQueryParams');
|
||||
let params = [routeName];
|
||||
if (!Ember.isNone(routeParams)) {
|
||||
if (Ember.isArray(routeParams)) {
|
||||
params = params.concat(routeParams);
|
||||
}
|
||||
else if (routeParams !== false) {
|
||||
params.push(routeParams);
|
||||
}
|
||||
if (routeName) {
|
||||
me.transitionToRoute(routeName,
|
||||
me.get('backRouteParams'),
|
||||
me.get('backRouteQueryParams'));
|
||||
}
|
||||
else {
|
||||
me.get('state').back() || me.backToList();
|
||||
}
|
||||
Ember.isNone(queryParams) ||
|
||||
params.push({queryParams: queryParams});
|
||||
router.transitionTo(...params);
|
||||
},
|
||||
save() {
|
||||
let me = this;
|
||||
@ -88,4 +96,4 @@ export default BaseComponent.extend({
|
||||
getModel() {
|
||||
return this.get('route.controller.model');
|
||||
}
|
||||
});
|
||||
});
|
@ -1,26 +1,106 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import BaseFormInput from './base-form-input';
|
||||
import { set, observer } from '@ember/object'
|
||||
import { isNone } from '@ember/utils'
|
||||
import { uniqBy } from '@ember/object/computed';
|
||||
import { isArray } from '@ember/array';
|
||||
|
||||
export default BaseFormInput.extend({
|
||||
classNames: ['form-group'],
|
||||
classNameBindings: ['hasError:has-error'],
|
||||
didInsertElement() {
|
||||
let me = this;
|
||||
uniqueSelected: uniqBy('options', 'selected'),
|
||||
'value-field': 'value',
|
||||
'text-field': 'text',
|
||||
onSelectionChanged: observer('options.@each.selected', function() {
|
||||
const me = this;
|
||||
const options = me.get('options');
|
||||
me.setVal(me.getSelected());
|
||||
const onChange = me.get('on-change');
|
||||
onChange && onChange(me.getVal(), options);
|
||||
}),
|
||||
didReceiveAttrs() {
|
||||
const me = this;
|
||||
me._super(...arguments);
|
||||
isNone(me.get('options')) && me.set('options', []);
|
||||
},
|
||||
didInsertElement() {
|
||||
const me = this;
|
||||
me._super(...arguments);
|
||||
me.prependEmpty();
|
||||
me.initSelect();
|
||||
|
||||
me.$('select.select2').select2({
|
||||
placeholder: me.get('placeholder') || me.get('label')
|
||||
allowClear: me.get('nullable'),
|
||||
placeholder: me.get('placeholder') || me.get('label') || 'Please select...'
|
||||
}).on('change', function(e) {
|
||||
if (e.added) {
|
||||
Ember.set(me.findOption(e.added.id), 'selected', 'selected');
|
||||
if (e.removed) {
|
||||
me.unselect(me.findOption(e.removed.id));
|
||||
}
|
||||
else if (e.removed) {
|
||||
Ember.set(me.findOption(e.removed.id), 'selected', false);
|
||||
if (e.added) {
|
||||
me.select(me.findOption(e.added.id));
|
||||
}
|
||||
});
|
||||
},
|
||||
findOption(value) {
|
||||
return this.get('options').find(option => option.value == value);
|
||||
didUpdate() {
|
||||
const me = this;
|
||||
me._super(...arguments);
|
||||
me.prependEmpty();
|
||||
me.$('select.select2').select2('val', me.getSelected());
|
||||
},
|
||||
prependEmpty() {
|
||||
const me = this;
|
||||
// prepend empty object for nullable
|
||||
if (me.get('nullable')) {
|
||||
const firstObject = me.get('options.firstObject');
|
||||
if (firstObject
|
||||
&& firstObject[me.get('value-field')]
|
||||
&& firstObject[me.get('text-field')]) {
|
||||
me.get('options').unshiftObject({});
|
||||
}
|
||||
}
|
||||
},
|
||||
initSelect() {
|
||||
const me = this;
|
||||
// init select
|
||||
if (me.get('multiple')) {
|
||||
const vals = me.getVal();
|
||||
if (isArray(vals)) {
|
||||
vals.each(v => me.select(me.findOption(v)));
|
||||
}
|
||||
else {
|
||||
me.setVal(me.getSelected());
|
||||
}
|
||||
}
|
||||
else {
|
||||
const val = me.getVal();
|
||||
if (!isNone(val)) {
|
||||
me.select(me.findOption(val));
|
||||
}
|
||||
else {
|
||||
const selected = me.get('options').find(o => o.selected);
|
||||
if (selected) {
|
||||
me.setVal(selected[me.get('value-field')]);
|
||||
}
|
||||
else {
|
||||
me.select(me.get('options.firstObject'))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
findOption(val) {
|
||||
const me = this;
|
||||
// val may empty of nullable option
|
||||
return val ? me.get('options').find(op => op[me.get('value-field')] == val)
|
||||
: me.get('options.firstObject');
|
||||
},
|
||||
select(op) {
|
||||
op && set(op, 'selected', true);
|
||||
},
|
||||
unselect(op) {
|
||||
op && set(op, 'selected', false);
|
||||
},
|
||||
getSelected() {
|
||||
const me = this;
|
||||
const selected = me.get('options').filter(o => o.selected).mapBy(me.get('value-field'));
|
||||
return selected.length > 1 ? selected : selected.length == 1 ? selected[0] : null;
|
||||
}
|
||||
});
|
||||
|
||||
|
34
web/app/components/option-text.js
Normal file
34
web/app/components/option-text.js
Normal file
@ -0,0 +1,34 @@
|
||||
import Component from '@ember/component';
|
||||
import { filter } from '@ember/object/computed';
|
||||
|
||||
const OptionTextComponent = Component.extend({
|
||||
tagName: '',
|
||||
'value-field': 'value',
|
||||
'text-field': 'text',
|
||||
didReceiveAttrs() {
|
||||
const me = this;
|
||||
me._super(...arguments);
|
||||
let val = me.get('value');
|
||||
if (val) {
|
||||
const option = (me.get('options') || []).findBy(me.get('value-field'), val);
|
||||
if (option) {
|
||||
let text = option[me.get('text-field')];
|
||||
let textExp = me.get('text-exp');
|
||||
me.set('text', textExp ?
|
||||
textExp.replace('$value', option[valueField])
|
||||
.replace('$text', text)
|
||||
.replace(/\$\.\w+/g, field => option[field.replace('$.', '')] || '') :
|
||||
text);
|
||||
}
|
||||
else {
|
||||
me.set('text', 'N/A');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
OptionTextComponent.reopenClass({
|
||||
positionalParams: ['options', 'value', 'value-field', 'text-field', 'text-exp'],
|
||||
});
|
||||
|
||||
export default OptionTextComponent;
|
@ -15,14 +15,43 @@ export default BaseComponent.extend({
|
||||
currPage: Ember.computed('params.page', function() {
|
||||
let me = this;
|
||||
let currPage = parseInt(me.get('params.page'));
|
||||
Ember.Logger.info('Get Curr Page [' + currPage + ']');
|
||||
Ember.Logger.info('Get curr page [' + currPage + ']');
|
||||
return currPage;
|
||||
}),
|
||||
pages: Ember.computed('total', function() {
|
||||
let i = 0;
|
||||
const me = this;
|
||||
const totalPage = me.get('totalPage');
|
||||
const currPage = me.get('currPage');
|
||||
let pages = [];
|
||||
while (i++ < this.get('totalPage')) {
|
||||
pages.push(i);
|
||||
|
||||
if (currPage > 4) {
|
||||
pages.push({page: 1, text: 1});
|
||||
pages.push({page: currPage - 3, text: '...'});
|
||||
pages.push({page: currPage - 2, text: currPage - 2});
|
||||
pages.push({page: currPage - 1, text: currPage - 1});
|
||||
}
|
||||
// from page 1
|
||||
else {
|
||||
let i = 0;
|
||||
while (++i < currPage) {
|
||||
pages.push({page: i, text: i});
|
||||
}
|
||||
}
|
||||
|
||||
pages.push({page: currPage, text: currPage, active: true});
|
||||
|
||||
if (currPage < totalPage - 4) {
|
||||
pages.push({page: currPage + 1, text: currPage + 1});
|
||||
pages.push({page: currPage + 2, text: currPage + 2});
|
||||
pages.push({page: currPage + 3, text: '...'});
|
||||
pages.push({page: totalPage, text: totalPage});
|
||||
}
|
||||
// to the end
|
||||
else {
|
||||
let i = currPage;
|
||||
while (++i <= totalPage) {
|
||||
pages.push({page: i, text: i});
|
||||
}
|
||||
}
|
||||
return pages;
|
||||
}),
|
||||
|
15
web/app/helpers/option-text-exp.js
Normal file
15
web/app/helpers/option-text-exp.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { helper } from '@ember/component/helper';
|
||||
|
||||
export function optionTextExp([option, valueField, textField, textExp]) {
|
||||
const text = option[textField];
|
||||
return textExp ? textExp.replace('$value', option[valueField])
|
||||
.replace('$text', text)
|
||||
.replace(/\$\.\w+/g, (field) => option[field.replace('$.', '')] || '') : text;
|
||||
|
||||
// '1234567890'.replace(/\d/g, function(c) {
|
||||
// return ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'][parseInt(c)];
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
export default helper(optionTextExp);
|
18
web/app/helpers/route-attr.js
Normal file
18
web/app/helpers/route-attr.js
Normal file
@ -0,0 +1,18 @@
|
||||
import Helper from '@ember/component/helper';
|
||||
import { get, computed } from '@ember/object';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { assert } from '@ember/debug';
|
||||
|
||||
export default Helper.extend({
|
||||
router: computed(function() {
|
||||
return getOwner(this).lookup('router:main');
|
||||
}).readOnly(),
|
||||
route: computed(function() {
|
||||
return getOwner(this).lookup('route:' + this.get('router.currentRouteName'));
|
||||
}).readOnly(),
|
||||
compute([attr]) {
|
||||
let route = get(this, 'route');
|
||||
assert('[ember-route-action-helper] Unable to lookup router', route);
|
||||
return get(route, attr);
|
||||
}
|
||||
});
|
@ -5,6 +5,7 @@ export function initialize(app) {
|
||||
app.inject('route', 'message', 'service:message');
|
||||
app.inject('route', 'dialog', 'service:dialog');
|
||||
app.inject('route', 'router', 'router:main');
|
||||
app.inject('route', 'state', 'service:state');
|
||||
|
||||
// controller
|
||||
app.inject('controller', 'ajax', 'service:ajax');
|
||||
|
15
web/app/instance-initializers/state.js
Normal file
15
web/app/instance-initializers/state.js
Normal file
@ -0,0 +1,15 @@
|
||||
import Route from '@ember/routing/route';
|
||||
|
||||
export function initialize(/* appInstance */) {
|
||||
Route.reopen({
|
||||
afterModel() {
|
||||
const me = this;
|
||||
me._super(...arguments);
|
||||
me.get('no-state') || me.get('state').push(me.get('router.currentURL'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
initialize
|
||||
};
|
@ -58,6 +58,12 @@ Router.map(function() {
|
||||
this.route('import-record', function() {
|
||||
this.route('list', {path: '/list/:page'});
|
||||
});
|
||||
|
||||
this.route('customer-application', function() {
|
||||
this.route('list', {path: '/list/:page'});
|
||||
this.route('create');
|
||||
this.route('edit', {path: '/:id/edit'});
|
||||
});
|
||||
});
|
||||
|
||||
export default Router;
|
||||
|
14
web/app/routes/customer-application/create.js
Normal file
14
web/app/routes/customer-application/create.js
Normal file
@ -0,0 +1,14 @@
|
||||
import Ember from 'ember';
|
||||
import BaseRoute from '../base';
|
||||
|
||||
export default BaseRoute.extend({
|
||||
service: Ember.inject.service('customer-property.service'),
|
||||
breadcrumbs: [{route: 'customer-application.list', params: 1, text: 'Customer Application'},
|
||||
{text: 'Create Customer Application'}],
|
||||
model() {
|
||||
return {
|
||||
type: 'APPLICATION',
|
||||
enabled: true
|
||||
};
|
||||
}
|
||||
});
|
11
web/app/routes/customer-application/edit.js
Normal file
11
web/app/routes/customer-application/edit.js
Normal file
@ -0,0 +1,11 @@
|
||||
import Ember from 'ember';
|
||||
import BaseEditRoute from '../base-edit';
|
||||
|
||||
export default BaseEditRoute.extend({
|
||||
service: Ember.inject.service('customer-property.service'),
|
||||
afterModel(model) {
|
||||
this.set('breadcrumbs',
|
||||
[{route: 'customer-application.list', params: 1, text: 'Customer Application'},
|
||||
{text: 'Edit Customer Application[' + model.name + ']'}]);
|
||||
}
|
||||
});
|
9
web/app/routes/customer-application/list.js
Normal file
9
web/app/routes/customer-application/list.js
Normal file
@ -0,0 +1,9 @@
|
||||
import Ember from 'ember';
|
||||
import CustomerPropertyListRoute from './../customer-property/list';
|
||||
|
||||
export default CustomerPropertyListRoute.extend({
|
||||
breadcrumbs: [{text: 'Customer Application'}],
|
||||
extraParams() {
|
||||
return {type: 'APPLICATION'};
|
||||
}
|
||||
});
|
34
web/app/routes/customer-property/list.js
Normal file
34
web/app/routes/customer-property/list.js
Normal file
@ -0,0 +1,34 @@
|
||||
import Ember from 'ember';
|
||||
import BaseListRoute from './../base-list';
|
||||
|
||||
export default BaseListRoute.extend({
|
||||
service: Ember.inject.service('customer-property.service'),
|
||||
actions: {
|
||||
moveUp(it) {
|
||||
let me = this;
|
||||
let data = me.get('controller.model.data');
|
||||
if (data && data.length > 1) {
|
||||
let index = data.indexOf(it);
|
||||
data.removeObject(it);
|
||||
data.insertAt(index - 1, it);
|
||||
me.updateSort();
|
||||
}
|
||||
},
|
||||
moveDown(it) {
|
||||
let me = this;
|
||||
let data = me.get('controller.model.data');
|
||||
if (data && data.length > 1) {
|
||||
let index = data.indexOf(it);
|
||||
data.removeObject(it);
|
||||
data.insertAt(index + 1, it);
|
||||
me.updateSort();
|
||||
}
|
||||
}
|
||||
},
|
||||
updateSort() {
|
||||
let me = this;
|
||||
me.get('ajax').doPost('customer-property/update-sort', {
|
||||
ids: JSON.stringify(me.get('controller.model.data').mapBy('id'))
|
||||
}, false);
|
||||
}
|
||||
});
|
@ -2,11 +2,11 @@ import Ember from 'ember';
|
||||
import BaseRoute from '../base';
|
||||
|
||||
export default BaseRoute.extend({
|
||||
service: Ember.inject.service('customer-property.service'),
|
||||
breadcrumbs: [{route: 'customer-status.list', params: 1, text: 'Customer Status'},
|
||||
{text: 'Create Customer Status'}],
|
||||
model() {
|
||||
return {
|
||||
gender: 'M',
|
||||
type: 'STATUS',
|
||||
enabled: true
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ import Ember from 'ember';
|
||||
import BaseEditRoute from '../base-edit';
|
||||
|
||||
export default BaseEditRoute.extend({
|
||||
service: Ember.inject.service('customer-property.service'),
|
||||
afterModel(model) {
|
||||
this.set('breadcrumbs',
|
||||
[{route: 'customer-status.list', params: 1, text: 'Customer Status'},
|
||||
|
@ -2,12 +2,12 @@ import Ember from 'ember';
|
||||
import BaseListSelectRoute from '../base-list-select';
|
||||
|
||||
export default BaseListSelectRoute.extend({
|
||||
service: Ember.inject.service('customer-property.service'),
|
||||
extraParams() {
|
||||
return {
|
||||
type: 'STATUS',
|
||||
enabled: true
|
||||
};
|
||||
},
|
||||
templateName: 'customer-status/list-select',
|
||||
service: Ember.inject.service('customer-status.service')
|
||||
templateName: 'customer-status/list-select'
|
||||
});
|
||||
|
@ -1,37 +1,9 @@
|
||||
import Ember from 'ember';
|
||||
import BaseListRoute from './../base-list';
|
||||
import CustomerPropertyListRoute from './../customer-property/list';
|
||||
|
||||
export default BaseListRoute.extend({
|
||||
export default CustomerPropertyListRoute.extend({
|
||||
breadcrumbs: [{text: 'Customer Status'}],
|
||||
extraParams() {
|
||||
return {type: 'STATUS'};
|
||||
},
|
||||
actions: {
|
||||
moveUp(it) {
|
||||
let me = this;
|
||||
let data = me.get('controller.model.data');
|
||||
if (data && data.length > 1) {
|
||||
let index = data.indexOf(it);
|
||||
data.removeObject(it);
|
||||
data.insertAt(index - 1, it);
|
||||
me.updateSort();
|
||||
}
|
||||
},
|
||||
moveDown(it) {
|
||||
let me = this;
|
||||
let data = me.get('controller.model.data');
|
||||
if (data && data.length > 1) {
|
||||
let index = data.indexOf(it);
|
||||
data.removeObject(it);
|
||||
data.insertAt(index + 1, it);
|
||||
me.updateSort();
|
||||
}
|
||||
}
|
||||
},
|
||||
updateSort() {
|
||||
let me = this;
|
||||
me.get('ajax').doPost('customer-property/update-sort', {
|
||||
ids: JSON.stringify(me.get('controller.model.data').mapBy('id'))
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
|
@ -6,5 +6,8 @@ export default BaseEditRoute.extend({
|
||||
this.set('breadcrumbs',
|
||||
[{route: 'customer.list', params: 1, text: 'Customers'},
|
||||
{text: 'Edit Customer [' + model.id + ']'}]);
|
||||
model.applicationList.forEach(a => {
|
||||
a.selected = model.applications.includes(a.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ const cols = ['showId',
|
||||
'showIssue1',
|
||||
'showIssue2',
|
||||
'showIssue3',
|
||||
'showApplication',
|
||||
];
|
||||
const config = {
|
||||
showAll: false,
|
||||
@ -44,7 +45,15 @@ const config = {
|
||||
};
|
||||
|
||||
cols.forEach((col) => {
|
||||
config[col] = !['showCountryCode', 'showState', 'showCity'].includes(col);
|
||||
config[col] = ![
|
||||
'showIssue2',
|
||||
'showIssue3',
|
||||
'showDateAdded',
|
||||
'showYears',
|
||||
'showCountryCode',
|
||||
'showRegion',
|
||||
'showState',
|
||||
].includes(col);
|
||||
});
|
||||
config.countOfShowing = cols.filter(col => {
|
||||
return config[col];
|
||||
|
29
web/app/services/state.js
Normal file
29
web/app/services/state.js
Normal file
@ -0,0 +1,29 @@
|
||||
import Service from '@ember/service';
|
||||
import { getOwner } from '@ember/application';
|
||||
|
||||
export default Service.extend({
|
||||
states: [],
|
||||
max: 16,
|
||||
previous() {
|
||||
return this.get('states.lastObject');
|
||||
},
|
||||
push(url) {
|
||||
if (url) {
|
||||
const me = this;
|
||||
me.get('states').pushObject(url);
|
||||
while (me.get('states.length') > me.get('max')) {
|
||||
me.get('states').shiftObject();
|
||||
}
|
||||
}
|
||||
},
|
||||
back() {
|
||||
const me = this;
|
||||
const url = me.previous();
|
||||
// if (pre && pre.retry();
|
||||
if (url) {
|
||||
const router = getOwner(this).lookup('router:main');
|
||||
router.transitionTo(url);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
});
|
@ -1,16 +1,25 @@
|
||||
<label for="{{name}}" class="{{get this 'label-class'}} control-label no-padding-right"> {{label}} </label>
|
||||
<label class="{{get this 'label-class'}} control-label no-padding-right">{{label}}</label>
|
||||
<div class="{{get this 'input-class'}} no-padding-right">
|
||||
<div class="row col-xs-12 no-padding">
|
||||
<div class="col-xs-{{get this 'col-width'}} no-padding-right">
|
||||
<select name=name
|
||||
multiple={{multiple}}
|
||||
<select multiple={{multiple}}
|
||||
data-placeholder={{if placeholder placeholder label}}
|
||||
class="select2"
|
||||
style="width: 100%;">
|
||||
{{#each options as |option|}}
|
||||
<option value={{option.value}} selected={{option.selected}}>{{option.text}}</option>
|
||||
<option value={{get option (get this 'value-field')}} selected={{if option.selected 'selected'}}>
|
||||
{{!text-exp: $text($value)}}
|
||||
{{#if (get option (get this 'value-field'))}}
|
||||
{{option-text-exp option (get this 'value-field') (get this 'text-field') (get this 'text-exp')}}
|
||||
{{/if}}
|
||||
</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
{{#each options as |option|}}
|
||||
{{#if option.selected}}
|
||||
<input type="hidden" name="{{name}}" value="{{get option (get this 'value-field')}}" />
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -64,6 +64,12 @@
|
||||
<span class="menu-text"> Customer Status </span>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
{{#link-to 'customer-application.list' 1}}
|
||||
<i class="menu-icon fa fa-cube blue"></i>
|
||||
<span class="menu-text"> Customer Application </span>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
{{#link-to 'import-record.list' 1}}
|
||||
<i class="menu-icon fa fa-th-list blue"></i>
|
||||
|
1
web/app/templates/components/option-text.hbs
Normal file
1
web/app/templates/components/option-text.hbs
Normal file
@ -0,0 +1 @@
|
||||
{{text}}
|
@ -7,6 +7,7 @@
|
||||
No Record
|
||||
{{/if}}
|
||||
</h6>
|
||||
|
||||
<ul class="pagination pull-right no-margin">
|
||||
<li class="prev">
|
||||
<a href="#" {{action 'gotoPage' prevPage}}>
|
||||
@ -15,9 +16,9 @@
|
||||
</li>
|
||||
|
||||
{{#each pages as |page|}}
|
||||
<li class="{{if (eq page currPage) 'active'}}">
|
||||
<a href="#" {{action 'gotoPage' page}}>
|
||||
{{page}}
|
||||
<li class="{{if page.active 'active'}}">
|
||||
<a href="#" {{action 'gotoPage' page.page}}>
|
||||
{{page.text}}
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
|
8
web/app/templates/customer-application/create.hbs
Normal file
8
web/app/templates/customer-application/create.hbs
Normal file
@ -0,0 +1,8 @@
|
||||
{{#form-content}}
|
||||
{{form-input type='hidden' name='type'}}
|
||||
{{form-input name='name' label='Name'}}
|
||||
{{form-input-enabled label='Enabled' enabledText='TRUE' disabledText='FALSE'}}
|
||||
{{form-input name='note' label='Remark'}}
|
||||
<hr />
|
||||
{{form-footer-buttons}}
|
||||
{{/form-content}}
|
9
web/app/templates/customer-application/edit.hbs
Normal file
9
web/app/templates/customer-application/edit.hbs
Normal file
@ -0,0 +1,9 @@
|
||||
{{#form-content}}
|
||||
{{input type='hidden' name='id' value=model.id}}
|
||||
{{form-input type='hidden' name='type'}}
|
||||
{{form-input name='name' label='Name'}}
|
||||
{{form-input-enabled label='Enabled' enabledText='TRUE' disabledText='FALSE'}}
|
||||
{{form-input name='note' label='Remark'}}
|
||||
<hr />
|
||||
{{form-footer-buttons type='update'}}
|
||||
{{/form-content}}
|
107
web/app/templates/customer-application/list.hbs
Normal file
107
web/app/templates/customer-application/list.hbs
Normal file
@ -0,0 +1,107 @@
|
||||
{{#main-content}}
|
||||
<div class="widget-box transparent">
|
||||
{{#grid-header}}
|
||||
<li>
|
||||
{{#link-to 'customer-application.create'}}
|
||||
<i class="ace-icon fa fa-plus-circle bigger-110 green"></i>
|
||||
Create Customer Application
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/grid-header}}
|
||||
|
||||
<div class="widget-body">
|
||||
<!-- #section:custom/scrollbar -->
|
||||
<div class="widget-main no-padding table-responsive no-border">
|
||||
<table class="table table-striped table-bordered table-hover dataTable" style="border: 1px solid #ddd;">
|
||||
<thead class="thin-border-bottom">
|
||||
<tr>
|
||||
<th>
|
||||
Name
|
||||
</th>
|
||||
<th>
|
||||
<i class="ace-icon fa fa-sticky-note-o bigger-110 hidden-480"></i>
|
||||
Remark
|
||||
</th>
|
||||
<th>
|
||||
<i class="ace-icon fa fa-exchange bigger-110 hidden-480"></i>
|
||||
Enabled
|
||||
</th>
|
||||
<th>
|
||||
<i class="ace-icon fa fa-cogs bigger-110 hidden-480"></i>
|
||||
Settings
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{#each model.data as |it|}}
|
||||
<tr>
|
||||
<td>
|
||||
{{it.name}}
|
||||
</td>
|
||||
<td>
|
||||
{{editable-cell model=it field='note'}}
|
||||
</td>
|
||||
<td>
|
||||
{{status-cell model=it enabledText='TRUE' disabledText='FALSE'}}
|
||||
</td>
|
||||
<td>
|
||||
<div class="hidden-sm hidden-xs btn-group">
|
||||
{{status-toggle-button model=it}}
|
||||
{{#link-to 'customer-application.edit' it.id class='btn btn-xs btn-info' title='Edit'}}
|
||||
<i class="ace-icon fa fa-pencil bigger-120"></i>
|
||||
{{/link-to}}
|
||||
{{#if (not-eq model.data.firstObject.id it.id)}}
|
||||
<button class="btn btn-xs btn-purple" title="Move Up" {{action (route-action 'moveUp' it)}}>
|
||||
<i class="ace-icon fa fa-arrow-up bigger-120"></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
{{#if (not-eq model.data.lastObject.id it.id)}}
|
||||
<button class="btn btn-xs" title="Move Down" {{action (route-action 'moveDown' it)}}>
|
||||
<i class="ace-icon fa fa-arrow-down bigger-120"></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="hidden-md hidden-lg">
|
||||
<div class="inline pos-rel">
|
||||
|
||||
<button class="btn btn-minier btn-primary dropdown-toggle" data-toggle="dropdown" data-position="auto">
|
||||
<i class="ace-icon fa fa-cog icon-only bigger-110"></i>
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-only-icon dropdown-yellow dropdown-menu-right dropdown-caret dropdown-close">
|
||||
<li>
|
||||
{{status-toggle-button model=it iconOnly=true}}
|
||||
</li>
|
||||
<li>
|
||||
{{#link-to 'customer-status.edit' it.id class='tooltip-info' data-rel='tooltip' title='Edit'}}
|
||||
<span class="blue">
|
||||
<i class="ace-icon fa fa-pencil-square-o bigger-120"></i>
|
||||
</span>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
{{#if (not-eq model.data.firstObject.id it.id)}}
|
||||
<a class="tooltip-info" title="Move Up" {{action (route-action 'moveUp' it)}}>
|
||||
<i class="ace-icon fa fa-arrow-up bigger-120"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#if (not-eq model.data.lastObject.id it.id)}}
|
||||
<a class="tooltip-info" title="Move Down" {{action (route-action 'moveDown' it)}}>
|
||||
<i class="ace-icon fa fa-arrow-down bigger-120"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{pagination-bar}}
|
||||
</div>
|
||||
</div>
|
||||
{{/main-content}}
|
@ -3,6 +3,7 @@
|
||||
{{#grid-header}}
|
||||
<li>
|
||||
{{#link-to 'customer-status.create'}}
|
||||
<i class="ace-icon fa fa-plus-circle bigger-110 green"></i>
|
||||
Create Customer Status
|
||||
{{/link-to}}
|
||||
</li>
|
||||
|
@ -9,12 +9,23 @@
|
||||
{{form-input name='salesperson' label='Salesperson' readonly='readonly'}}
|
||||
{{form-input type='hidden' name='enabled'}}
|
||||
|
||||
{{form-input-modal-select
|
||||
listRoute='customer.edit.customer-status-select'
|
||||
idField='status'
|
||||
nameField='statusText'
|
||||
btnIcon='fa-file-image-o'
|
||||
label='Status'}}
|
||||
{{form-input-select2
|
||||
multiple=true
|
||||
name='applications'
|
||||
label='Application'
|
||||
nullable=true
|
||||
options=model.applicationList
|
||||
value-field='id'
|
||||
text-field='name'
|
||||
}}
|
||||
|
||||
{{form-input-select2
|
||||
name='status'
|
||||
label='Status'
|
||||
options=model.statusList
|
||||
value-field='id'
|
||||
text-field='name'
|
||||
}}
|
||||
<hr />
|
||||
{{form-footer-buttons type='update'}}
|
||||
{{/form-content}}
|
||||
|
@ -39,12 +39,48 @@
|
||||
<table class="table table-striped table-bordered table-hover" style="border: 1px solid #ddd;">
|
||||
<thead class="thin-border-bottom">
|
||||
<tr>
|
||||
{{!--
|
||||
1 ID
|
||||
2 Name
|
||||
3 Sales(3Yrs)
|
||||
4 Comment
|
||||
5 Application
|
||||
6 Status
|
||||
7 Added
|
||||
8 Year
|
||||
9 Country
|
||||
10 State
|
||||
11 City
|
||||
12 MS
|
||||
13 Region
|
||||
14 Slspsn
|
||||
--}}
|
||||
{{#if tableOptions.showId}}
|
||||
{{sortable-th name='id' text='ID'}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showName}}
|
||||
<th style='min-width: 86px; max-width: 168px;'>Name</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showYtdSale}}
|
||||
{{sortable-th name='sumYtdSales' text='Sales(3Yrs)' style='min-width: 126px;'}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue1}}
|
||||
<th>Comment</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue2}}
|
||||
<th>Comment 2</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue3}}
|
||||
<th>Comment 3</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showApplication}}
|
||||
<th>Application</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showStatus}}
|
||||
{{#sortable-th name='status' style='min-width: 96px;'}}
|
||||
{{th-filter name='status' text='Status' label='Status Filter' options=model.statusList}}
|
||||
{{/sortable-th}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showDateAdded}}
|
||||
{{#sortable-th name='dateAdded' style='min-width: 96px;'}}
|
||||
{{th-filter name='dateAdded' text='Added' label='Added Filter' options=model.dateAddedList}}
|
||||
@ -55,9 +91,6 @@
|
||||
{{th-filter name='year' text='Year' label='Year Filter' options=model.latestYearList}}
|
||||
{{/sortable-th}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showYtdSale}}
|
||||
{{sortable-th name='sumYtdSales' text='Sales(3Yrs)' style='min-width: 126px;'}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showCountryCode}}
|
||||
<th>
|
||||
{{th-filter name='countryCode' text='Country' label='Country Filter' options=model.countryCodeList}}
|
||||
@ -88,20 +121,6 @@
|
||||
{{th-filter name='salesperson' text='Slspsn' label='Salesperson Filter' options=model.salespersonList}}
|
||||
{{/sortable-th}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showStatus}}
|
||||
{{#sortable-th name='status' style='min-width: 96px;'}}
|
||||
{{th-filter name='status' text='Status' label='Status Filter' options=model.statusList}}
|
||||
{{/sortable-th}}
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue1}}
|
||||
<th>Comment 1</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue2}}
|
||||
<th>Comment 2</th>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue3}}
|
||||
<th>Comment 3</th>
|
||||
{{/if}}
|
||||
<th>
|
||||
<i class="ace-icon fa fa-cogs bigger-110 hidden-480"></i>
|
||||
Settings
|
||||
@ -124,23 +143,6 @@
|
||||
{{it.name}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showDateAdded}}
|
||||
<td>
|
||||
{{date-cell value=it.dateAdded format='YYYY'}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showYears}}
|
||||
<td>
|
||||
{{!--
|
||||
{{#if (eq it.years.length 1)}}
|
||||
{{it.years.firstObject}}
|
||||
{{else if (gt it.years.length 1)}}
|
||||
{{it.years.firstObject}}-{{it.years.lastObject}}
|
||||
{{/if}}
|
||||
--}}
|
||||
{{it.year}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showYtdSale}}
|
||||
<td>
|
||||
{{#if it.countYtdSales}}
|
||||
@ -157,41 +159,6 @@
|
||||
{{number-us it.sumYtdSales}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showCountryCode}}
|
||||
<td>
|
||||
{{it.countryCode}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showState}}
|
||||
<td>
|
||||
{{it.state}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showCity}}
|
||||
<td>
|
||||
{{it.city}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showMs}}
|
||||
<td>
|
||||
{{it.ms}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showRegion}}
|
||||
<td>
|
||||
{{it.region}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showSalesperson}}
|
||||
<td>
|
||||
{{it.salesperson}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showStatus}}
|
||||
<td>
|
||||
{{it.statusText}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showIssue1}}
|
||||
<td style="max-width: 36px; white-space: initial;">
|
||||
{{#if it.issue1}}
|
||||
@ -240,6 +207,63 @@
|
||||
{{/if}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showApplication}}
|
||||
<td>
|
||||
{{it.application}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showStatus}}
|
||||
<td>
|
||||
{{it.statusText}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showDateAdded}}
|
||||
<td>
|
||||
{{date-cell value=it.dateAdded format='YYYY'}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showYears}}
|
||||
<td>
|
||||
{{!--
|
||||
{{#if (eq it.years.length 1)}}
|
||||
{{it.years.firstObject}}
|
||||
{{else if (gt it.years.length 1)}}
|
||||
{{it.years.firstObject}}-{{it.years.lastObject}}
|
||||
{{/if}}
|
||||
--}}
|
||||
{{it.year}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showCountryCode}}
|
||||
<td>
|
||||
{{it.countryCode}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showState}}
|
||||
<td>
|
||||
{{it.state}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showCity}}
|
||||
<td>
|
||||
{{it.city}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showMs}}
|
||||
<td>
|
||||
{{it.ms}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showRegion}}
|
||||
<td>
|
||||
{{it.region}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if tableOptions.showSalesperson}}
|
||||
<td>
|
||||
{{it.salesperson}}
|
||||
</td>
|
||||
{{/if}}
|
||||
<td>
|
||||
<div class="hidden-sm hidden-xs btn-group">
|
||||
{{#link-to 'customer-issue.create' it.id class='btn btn-xs btn-success' data-rel='tooltip' title='Write Comment'}}
|
||||
|
@ -12,21 +12,23 @@
|
||||
<div class="col-xs-5 col-sm-5">
|
||||
<div class="control-group">
|
||||
{{ace-checkbox label='ID' value=model.tableOptions.showId}}
|
||||
{{ace-checkbox label='Name' value=model.tableOptions.showName}}
|
||||
{{ace-checkbox label='Year' value=model.tableOptions.showYears}}
|
||||
{{ace-checkbox label='Date Added' value=model.tableOptions.showDateAdded}}
|
||||
{{ace-checkbox label='YTD Sales' value=model.tableOptions.showYtdSale}}
|
||||
{{ace-checkbox label='Application' value=model.tableOptions.showApplication}}
|
||||
{{ace-checkbox label='Date Added' value=model.tableOptions.showDateAdded}}
|
||||
{{ace-checkbox label='Country' value=model.tableOptions.showCountryCode}}
|
||||
{{ace-checkbox label='State' value=model.tableOptions.showState}}
|
||||
{{ace-checkbox label='City' value=model.tableOptions.showCity}}
|
||||
{{ace-checkbox label='Region' value=model.tableOptions.showRegion}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-5 col-sm-5">
|
||||
<div class="control-group">
|
||||
{{ace-checkbox label='City' value=model.tableOptions.showCity}}
|
||||
{{ace-checkbox label='MS' value=model.tableOptions.showMs}}
|
||||
{{ace-checkbox label='Region' value=model.tableOptions.showRegion}}
|
||||
{{ace-checkbox label='Salesperson' value=model.tableOptions.showSalesperson}}
|
||||
{{ace-checkbox label='Name' value=model.tableOptions.showName}}
|
||||
{{ace-checkbox label='Comment' value=model.tableOptions.showIssue1}}
|
||||
{{ace-checkbox label='Status' value=model.tableOptions.showStatus}}
|
||||
{{ace-checkbox label='Year' value=model.tableOptions.showYears}}
|
||||
{{ace-checkbox label='State' value=model.tableOptions.showState}}
|
||||
{{ace-checkbox label='MS' value=model.tableOptions.showMs}}
|
||||
{{ace-checkbox label='Salesperson' value=model.tableOptions.showSalesperson}}
|
||||
{{ace-checkbox label='Select All' value=model.tableOptions.showAll}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@
|
||||
{{#grid-header}}
|
||||
<li>
|
||||
{{#link-to 'user.create'}}
|
||||
<i class="ace-icon fa fa-plus-circle bigger-110 green"></i>
|
||||
Create User
|
||||
{{/link-to}}
|
||||
</li>
|
||||
|
1102
web/package-lock.json
generated
1102
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -23,16 +23,18 @@
|
||||
"ember-cli": "~2.14.2",
|
||||
"ember-cli-app-version": "^3.0.0",
|
||||
"ember-cli-babel": "^6.3.0",
|
||||
"ember-cli-shims": "^1.1.0",
|
||||
"ember-cli-dependency-checker": "^1.3.0",
|
||||
"ember-cli-eslint": "^3.0.0",
|
||||
"ember-cli-htmlbars": "^2.0.1",
|
||||
"ember-cli-htmlbars-inline-precompile": "^0.4.3",
|
||||
"ember-cli-inject-live-reload": "^1.4.1",
|
||||
"ember-cli-jshint": "^1.0.0",
|
||||
"ember-cli-less": "^1.5.5",
|
||||
"ember-cli-moment-shim": "1.2.0",
|
||||
"ember-cli-qunit": "^4.0.0",
|
||||
"ember-cli-release": "0.2.8",
|
||||
"ember-cli-shims": "^1.1.0",
|
||||
"ember-cli-sri": "^2.1.0",
|
||||
"ember-cli-uglify": "^1.2.0",
|
||||
"ember-export-application-global": "^2.0.0",
|
||||
"ember-load-initializers": "^1.0.0",
|
||||
@ -40,14 +42,12 @@
|
||||
"ember-radio-button": "1.1.1",
|
||||
"ember-resolver": "^4.0.0",
|
||||
"ember-route-action-helper": "2.0.3",
|
||||
"ember-source": "~2.14.1",
|
||||
"ember-source": "~2.16.0",
|
||||
"ember-truth-helpers": "1.1.0",
|
||||
"emberx-select": "3.1.0",
|
||||
"emberx-select": "3.0.1",
|
||||
"glob": "^4.5.3",
|
||||
"loader.js": "^4.2.3",
|
||||
"morgan": "^1.7.0",
|
||||
"ember-cli-sri": "^2.1.0",
|
||||
"valid-url": "^1.0.9"
|
||||
"morgan": "^1.7.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"engines": {
|
||||
|
26
web/tests/unit/instance-initializers/state-test.js
Normal file
26
web/tests/unit/instance-initializers/state-test.js
Normal file
@ -0,0 +1,26 @@
|
||||
import Application from '@ember/application';
|
||||
import { run } from '@ember/runloop';
|
||||
import { initialize } from 'ambition-crm/instance-initializers/state';
|
||||
import { module, test } from 'qunit';
|
||||
import destroyApp from '../../helpers/destroy-app';
|
||||
|
||||
module('Unit | Instance Initializer | state', {
|
||||
beforeEach() {
|
||||
run(() => {
|
||||
this.application = Application.create();
|
||||
this.appInstance = this.application.buildInstance();
|
||||
});
|
||||
},
|
||||
afterEach() {
|
||||
run(this.appInstance, 'destroy');
|
||||
destroyApp(this.application);
|
||||
}
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it works', function(assert) {
|
||||
initialize(this.appInstance);
|
||||
|
||||
// you would normally confirm the results of the initializer here
|
||||
assert.ok(true);
|
||||
});
|
11
web/tests/unit/routes/customer-application/create-test.js
Normal file
11
web/tests/unit/routes/customer-application/create-test.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:customer-application/create', 'Unit | Route | customer application/create', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
11
web/tests/unit/routes/customer-application/edit-test.js
Normal file
11
web/tests/unit/routes/customer-application/edit-test.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:customer-application/edit', 'Unit | Route | customer application/edit', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
11
web/tests/unit/routes/customer-application/list-test.js
Normal file
11
web/tests/unit/routes/customer-application/list-test.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:customer-application/list', 'Unit | Route | customer application/list', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
12
web/tests/unit/services/state-test.js
Normal file
12
web/tests/unit/services/state-test.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('service:state', 'Unit | Service | state', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['service:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let service = this.subject();
|
||||
assert.ok(service);
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user