This commit is contained in:
东皇 2018-02-14 13:58:55 +08:00
parent 04c3843c9f
commit 12c9b995cd
36 changed files with 541 additions and 233 deletions

View File

@ -1,11 +1,8 @@
package com.pudonghot.ambition.crm.controller;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.*;
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;
@ -14,12 +11,13 @@ import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
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 com.pudonghot.ambition.crm.model.User;
import org.springframework.stereotype.Controller;
import com.pudonghot.ambition.crm.model.Customer;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.multipart.MultipartFile;
import com.pudonghot.ambition.crm.model.CustomerProperty;
import com.pudonghot.ambition.crm.service.CustomerService;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMethod;
@ -74,6 +72,8 @@ public class CustomerController
CRITERION_COLS.put(Customer.CITY, "customer.city");
CRITERION_COLS.put("status", "prop.id");
CRITERION_COLS.put("ytdSale", CustomerYearToDateSale.YTD_SALE);
CRITERION_COLS.put("application", "application");
CRITERION_COLS.put("issue", "issue.artificial");
}
@RequestMapping("/list")
@ -244,6 +244,8 @@ public class CustomerController
filter(search, joFilters, "city");
filter(search, joFilters, "salesperson");
filter(search, joFilters, "status");
filter(search, joFilters, "application");
filter(search, joFilters, "issue", Boolean[].class);
return search;
}
@ -259,7 +261,12 @@ public class CustomerController
joFilters.getObject(field, clazz);
if (filters != null && filters.length > 0) {
log.info("Col [{}] filters [{}] found.", col, filters);
search.in(col, filters);
if ("application".equals(col)) {
search.setAttr("APPLICATIONS", filters);
}
else {
in(search, col, filters);
}
}
else {
defaultFilter(search, field);
@ -279,4 +286,30 @@ public class CustomerController
search.ne(CRITERION_COLS.get(field), CustomerProperty.STATUS_NA_ID);
}
}
private void in(final Search search, final String col, final Object[] values) {
final Set<Object> setValues = new HashSet<>(Arrays.asList(values));
final Iterator<Object> valIt = setValues.iterator();
if (setValues.size() == 1) {
final Object val = valIt.next();
search.eq(col, "null".equals(val) ? null : val);
}
else {
boolean nullValue = false;
while (valIt.hasNext()) {
final Object val = valIt.next();
if (val == null || "null".equals(val)) {
nullValue = true;
valIt.remove();
break;
}
}
if (nullValue) {
search.and(new Search(col, setValues).or(col, null));
}
else {
search.in(col, setValues);
}
}
}
}

View File

@ -2,6 +2,7 @@ package com.pudonghot.ambition.crm.service.support;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import javax.validation.constraints.Min;
import me.chyxion.tigon.model.ViewModel;
import org.apache.commons.lang3.StringUtils;
@ -30,6 +31,21 @@ public class CustomerIssueServiceSupport
@Autowired
private UserService userService;
/**
* {@inheritDoc}
*/
@Override
public ViewModel<CustomerIssue> update(final CustomerIssueFormForUpdate form) {
final String id = form.getId();
final CustomerIssue issue = find(id);
Assert.state(issue != null, "No issue [" + id + "] found");
if (!issue.getIssue().equals(form.getIssue())) {
return super.update(form);
}
log.info("Issue [{}] not changed", issue);
return toViewModel(issue);
}
/**
* {@inheritDoc}
*/

View File

@ -2,9 +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 org.springframework.util.Assert;
import me.chyxion.tigon.mybatis.Search;
import me.chyxion.tigon.model.ViewModel;
import org.apache.commons.csv.CSVRecord;
@ -50,6 +49,8 @@ public class CustomerServiceSupport
private ImportRecordMapper importRecordMapper;
@Autowired
private CustomerIssueMapper customerIssueMapper;
@Autowired
private CustomerApplicationMapper customerApplicationMapper;
/**
* override find by id with find by search
@ -72,18 +73,19 @@ public class CustomerServiceSupport
}
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,
viewModel.setAttr("statusList",
customerPropertyMapper.list(
new Search(CustomerProperty.TYPE,
CustomerProperty.Type.STATUS)
.asc(CustomerProperty.SORT)));
viewModel.setAttr("applicationList",
customerPropertyMapper.list(
new Search(CustomerProperty.TYPE,
CustomerProperty.Type.APPLICATION)
.eq(CustomerProperty.ENABLED, true)
.asc(CustomerProperty.SORT)));
.asc(CustomerProperty.SORT)));
}
return viewModel;
}
@ -94,7 +96,7 @@ public class CustomerServiceSupport
@Override
public ListResult<ViewModel<Customer>> listViewModelsPage(Search search) {
final String account = search.getAttr(User.ACCOUNT);
ListResult<ViewModel<Customer>> result =
final ListResult<ViewModel<Customer>> result =
new ListResult<>(toViewModel(
mapper.listForShow(search, account)),
mapper.countForShow(search, account));
@ -106,14 +108,60 @@ public class CustomerServiceSupport
result.setAttr("countryCodeList", mapper.listCountryCode());
result.setAttr("stateList", mapper.listState());
result.setAttr("cityList", mapper.listCity());
result.setAttr("salespersonList", mapper.listSalesperson());
result.setAttr("statusList",
customerPropertyMapper.listForFilter(CustomerProperty.Type.STATUS));
final List<CustomerProperty> statusList =
customerPropertyMapper.list(
new Search(CustomerProperty.TYPE,
CustomerProperty.Type.STATUS)
.asc(CustomerProperty.SORT));
final CustomerProperty noneStatus = new CustomerProperty();
noneStatus.setId("null");
noneStatus.setName("None");
noneStatus.setEnabled(true);
noneStatus.setType(CustomerProperty.Type.STATUS);
statusList.add(noneStatus);
result.setAttr("statusList", statusList);
result.setAttr("applicationList", customerPropertyMapper.list(
new Search(CustomerProperty.TYPE,
CustomerProperty.Type.APPLICATION)
.asc(CustomerProperty.SORT)));
return result;
}
/**
* {@inheritDoc}
*/
@Override
public ViewModel<Customer> update(final CustomerFormForUpdate form) {
final String customerId = form.getId();
customerApplicationMapper.delete(
new Search(CustomerApplication.CUSTOMER_ID, customerId));
final List<String> applications = form.getApplications();
if (applications != null) {
final String operator = form.getUpdatedBy();
final Date now = new Date();
for (final String applicationId : applications) {
CustomerProperty customerProperty =
customerPropertyMapper.find(new Search(applicationId)
.eq(CustomerProperty.TYPE,
CustomerProperty.Type.APPLICATION));
Assert.state(customerProperty != null,
"No customer application [" + applicationId + "] found");
final CustomerApplication application = new CustomerApplication();
application.setId(idSeq.get());
application.setCustomerId(customerId);
application.setPropertyId(applicationId);
application.setCreatedBy(operator);
application.setDateCreated(now);
customerApplicationMapper.insert(application);
}
}
return super.update(form);
}
/**
* {@inheritDoc}
*/
@ -290,8 +338,9 @@ public class CustomerServiceSupport
if (customerIssueMapper.count(
new Search(CustomerIssue.CUSTOMER_ID, customerId)
.eq(CustomerIssue.ENABLED, true)) < 1) {
CustomerIssue ci = new CustomerIssue();
final CustomerIssue ci = new CustomerIssue();
ci.setId(idSeq.get());
ci.setArtificial(false);
ci.setCustomerId(customerId);
ci.setEnabled(true);
ci.setCreatedBy(operator);

View File

@ -0,0 +1,14 @@
package com.pudonghot.ambition.crm.mapper;
import me.chyxion.tigon.mybatis.BaseMapper;
import com.pudonghot.ambition.crm.model.CustomerApplication;
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Feb 13, 2018 10:21:57 AM
*/
public interface CustomerApplicationMapper extends BaseMapper<String, CustomerApplication> {
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Feb 13, 2018 10:21:57 AM
*/
-->
<!DOCTYPE mapper PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pudonghot.ambition.crm.mapper.CustomerApplicationMapper">
</mapper>

View File

@ -12,145 +12,23 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pudonghot.ambition.crm.mapper.CustomerMapper">
<select id="findForShow" resultType="com.pudonghot.ambition.crm.model.Customer">
select
<foreach collection="new com.pudonghot.ambition.crm.model.Customer().cols('customer')"
item="col" separator=", ">
${col}
</foreach>
, prop.name status_text,
<!-- latest year -->
(select max(year)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1) year,
<!-- all years list -->
(select group_concat(year order by year asc separator ',')
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1
group by customer_id) years,
<!-- all sales list -->
(select group_concat(ytd_sale order by year asc separator ',')
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1
group by customer_id) ytd_sales,
<!-- recent 3 years sales -->
(select sum(ytd_sale)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and year between year(now()) - 2 and year(now())
and enabled = 1) sum_ytd_sales,
<!-- sales count of years -->
(select count(1)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1) count_ytd_sales
from <include refid="table" /> customer
select <include refid="showCols" />
left join crm_customer_property prop
on customer.status = prop.id
<include refid="lastIssueLeftJoin" />
where customer.id = #{id}
</select>
<select id="listForShow" resultType="com.pudonghot.ambition.crm.model.Customer">
select distinct
<foreach collection="new com.pudonghot.ambition.crm.model.Customer().cols('customer')"
item="col" separator=", ">
${col}
</foreach>
, prop.name status_text,
prop.sort status_sort,
<!-- latest year -->
(select max(year)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1) year,
<!-- all years list -->
(select group_concat(year order by year asc separator ',')
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1
group by customer_id) years,
<!-- all sales list -->
(select group_concat(ytd_sale order by year asc separator ',')
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1
group by customer_id) ytd_sales,
<!-- recent 3 years sales -->
(select sum(ytd_sale)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and year between year(now()) - 2 and year(now())
and enabled = 1
) sum_ytd_sales,
<!-- sales count of years -->
(select count(1)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1) count_ytd_sales
from <include refid="table" /> customer
<if test="s.getAttr('YTD_SALE') != null">
left join (select customer_id, max(year) year
from crm_customer_year_to_date_sale
where enabled = 1
group by customer_id
) t
on customer.id = t.customer_id
</if>
left join crm_customer_property prop
on customer.status = prop.id
<if test="account != null">
join crm_customer_permission perm on
customer.id = perm.customer_id
and perm.enabled = 1
and perm.user_account = #{account}
</if>
select distinct <include refid="showCols" />
<include refid="showFilter" />
<include refid="Tigon.search" />
</select>
<select id="countForShow" resultType="int">
select count(distinct customer.id)
from <include refid="table" /> customer
<!-- latest year -->
<if test="s.getAttr('YTD_SALE') != null">
join (select customer_id, max(year) year
from crm_customer_year_to_date_sale
where enabled = 1
group by customer_id
) t
on customer.id = customer_id
</if>
left join crm_customer_property prop
on customer.status = prop.id
<if test="account != null">
join crm_customer_permission perm on
customer.id = perm.customer_id
and perm.enabled = 1
and perm.user_account = #{account}
</if>
<include refid="showFilter" />
<include refid="Tigon.searchForCount" />
</select>
@ -259,5 +137,106 @@
where enabled = 1
and (status is null or status in ('STATUS_ACTIVE', 'STATUS_OCCASIONAL'))
</select>
<sql id="showCols">
<foreach collection="new com.pudonghot.ambition.crm.model.Customer().cols('customer')" item="col" separator=", ">
${col}
</foreach>
, prop.name status_text,
prop.sort status_sort,
issue.artificial artificial_issue,
<!-- latest year -->
(select max(year)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1) year,
<!-- all years list -->
(select group_concat(year order by year asc separator ',')
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1
group by customer_id) years,
<!-- all sales list -->
(select group_concat(ytd_sale order by year asc separator ',')
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1
group by customer_id) ytd_sales,
<!-- sum 3 years sales -->
(select sum(ytd_sale)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and year between year(now()) - 2 and year(now())
and enabled = 1) sum_ytd_sales,
<!-- sales count of years -->
(select count(1)
from crm_customer_year_to_date_sale
where customer_id = customer.id
and enabled = 1) count_ytd_sales,
<!-- applications -->
(select group_concat(p.id order by p.sort separator ',')
from crm_customer_application a
join crm_customer_property p
on a.property_id = p.id
where a.customer_id = customer.id
group by a.customer_id) applications
from <include refid="table" /> customer
</sql>
<sql id="showFilter">
<if test="s.getAttr('APPLICATIONS') != null">
join (select distinct customer_id
from crm_customer_application
where property_id in
<foreach item="appId" collection="s.getAttr('APPLICATIONS')" open="(" close=")" separator=",">
#{appId}
</foreach>
) app
on customer.id = app.customer_id
</if>
<if test="s.getAttr('YTD_SALE') != null">
left join (select customer_id, max(year) year
from crm_customer_year_to_date_sale
where enabled = 1
group by customer_id) t
on customer.id = t.customer_id
</if>
left join crm_customer_property prop
on customer.status = prop.id
<!-- Last Issue -->
<include refid="lastIssueLeftJoin" />
<if test="account != null">
join crm_customer_permission perm on
customer.id = perm.customer_id
and perm.enabled = 1
and perm.user_account = #{account}
</if>
</sql>
<sql id="lastIssueLeftJoin">
left join (
select a.*
from crm_customer_issue a
left join crm_customer_issue b
on a.customer_id = b.customer_id
and ifnull(a.date_updated, a.date_created)
<![CDATA[<]]>
ifnull(b.date_updated, b.date_created)
where a.enabled = 1
and b.id is null
) issue
on customer.id = issue.customer_id
</sql>
</mapper>

View File

@ -1,12 +1,9 @@
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;
/**
* @version 0.0.1
@ -25,20 +22,4 @@ public interface CustomerPropertyMapper extends BaseMapper<String, CustomerPrope
@NotNull
@Param("type")
CustomerProperty.Type type);
/**
* list for customer filter
* @param type type
* @return custom props
*/
List<Map<String, Object>> listForFilter(
@NotNull
@Param("type")
CustomerProperty.Type type);
List<CustomerProperty> listApplication(
@NotBlank
@Param("customerId")
String customerId);
}

View File

@ -17,21 +17,4 @@
from <include refid="table" />
where type = #{type}
</select>
<select id="listForFilter" resultType="map">
select id value, name text
from <include refid="table" />
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>

View File

@ -2,7 +2,7 @@
# Database
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

View File

@ -0,0 +1,64 @@
package com.pudonghot.ambition.crm.mapper;
import org.junit.Assert;
import org.junit.Test;
import java.util.Date;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.pudonghot.ambition.crm.mapper.CustomerApplicationMapper;
import com.pudonghot.ambition.crm.model.CustomerApplication;
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Feb 13, 2018 10:21:57 AM
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring/spring-*.xml")
public class CustomerApplicationMapperTest extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private CustomerApplicationMapper mapper;
@Test
public void mapperTest() {
// String id = String.valueOf(new Date().getTime());
// init model
CustomerApplication m = new CustomerApplication();
String id = "id";
m.setId(id);
m.setDateCreated(new Date());
m.setCustomerId("s");
m.setPropertyId("s");
mapper.insert(m);
Assert.assertTrue(mapper.list(null).size() > 0);
/*
// Your Test Logics
CustomerApplication m1 = mapper.find(id);
// asserts
Assert.assertEquals(id, m1.getId());
Assert.assertEquals("s", m.getCustomerId());
Assert.assertEquals("s", m.getPropertyId());
// update
m.setDateUpdated(new Date());
m.setCustomerId("S");
m.setPropertyId("S");
mapper.update(m);
m1 = mapper.find(id);
// asserts
Assert.assertEquals(id, m1.getId());
Assert.assertNotNull(m1.getDateUpdated());
Assert.assertEquals("S", m.getCustomerId());
Assert.assertEquals("S", m.getPropertyId());
// list
Assert.assertTrue(mapper.list(null).size() > 0);
// delete
mapper.delete(id);
m1 = mapper.find(id);
Assert.assertNull(m1);
*/
}
}

View File

@ -29,8 +29,5 @@ public class CustomerPropertyMapperTest extends AbstractTransactionalJUnit4Sprin
@Test
public void mapperTest() {
List<Map<String, Object>> maps =
mapper.listForFilter(CustomerProperty.Type.STATUS);
log.info("status: [{}].", maps);
}
}

View File

@ -25,4 +25,5 @@ public class CustomerIssueFormForCreate extends FC2<String> {
@NotBlank
@Length(max = 2048)
private String issue;
private boolean artificial = true;
}

View File

@ -2,6 +2,7 @@ package com.pudonghot.ambition.crm.form.update;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import me.chyxion.tigon.form.FU2;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
@ -39,4 +40,5 @@ public class CustomerFormForUpdate extends FU2<String, String> {
@EmptyToNull
@Length(max = 36)
private String status;
private List<String> applications;
}

View File

@ -21,4 +21,5 @@ public class CustomerIssueFormForUpdate extends FU2<String, String> {
@NotBlank
@Length(max = 2048)
private String issue;
private boolean artificial = true;
}

View File

@ -55,4 +55,8 @@ public class Customer extends M3<String, String> {
private int sumYtdSales;
@Transient
private int countYtdSales;
@Transient
private String applications;
@Transient
private boolean artificialIssue;
}

View File

@ -0,0 +1,28 @@
package com.pudonghot.ambition.crm.model;
import lombok.Getter;
import lombok.Setter;
import me.chyxion.tigon.mybatis.Table;
import me.chyxion.tigon.model.M3;
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Feb 13, 2018 10:20:17 AM
*/
@Getter
@Setter
@Table("crm_customer_application")
public class CustomerApplication extends M3<String, String> {
private static final long serialVersionUID = 1L;
// Column Names
public static final String CUSTOMER_ID = "customer_id";
public static final String PROPERTY_ID = "property_id";
// Properties
private String customerId;
private String propertyId;
}

View File

@ -2,8 +2,8 @@ package com.pudonghot.ambition.crm.model;
import lombok.Getter;
import lombok.Setter;
import me.chyxion.tigon.mybatis.Table;
import me.chyxion.tigon.model.M3;
import me.chyxion.tigon.mybatis.Table;
/**
* @version 0.0.1
@ -20,9 +20,10 @@ public class CustomerIssue extends M3<String, String> {
// Column Names
public static final String CUSTOMER_ID = "customer_id";
public static final String ISSUE = "issue";
public static final String ARTIFICIAL = "artificial";
// Properties
private String customerId;
private String issue;
private boolean artificial;
}

View File

@ -2,7 +2,7 @@
# Database
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

View File

@ -13,6 +13,8 @@ export default BaseComponent.extend({
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'),
backToList() {
const me = this;
let listRouteName = me.get('routeName').replace(/[^.]+$/, 'list');

View File

@ -64,7 +64,7 @@ export default BaseFormInput.extend({
if (me.get('multiple')) {
const vals = me.getVal();
if (isArray(vals)) {
vals.each(v => me.select(me.findOption(v)));
vals.forEach(v => me.select(me.findOption(v)));
}
else {
me.setVal(me.getSelected());
@ -101,6 +101,6 @@ export default BaseFormInput.extend({
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;
return me.get('multiple') ? selected : selected[0];
}
});

View File

@ -1,4 +1,5 @@
import Ember from 'ember';
import { set, computed } from '@ember/object';
import BaseComponentMixin from '../mixins/components/base-component';
export default Ember.Component.extend(BaseComponentMixin, {
@ -6,15 +7,19 @@ export default Ember.Component.extend(BaseComponentMixin, {
classNames: ['cursor-pointer'],
'dialog-title': 'Data Filter',
'full-width': false,
filtered: Ember.computed('options.@each.selected', function() {
return this.get('options').filterBy('selected', true).length > 0;
'value-field': 'value',
'text-field': 'text',
filtered: computed('options.@each.selected', function() {
const options = this.get('options');
return options && options.filterBy('selected', 'selected').length > 0;
}),
didReceiveAttrs() {
let me = this;
let filters = me.getFilters()[me.get('name')];
if (filters && filters.length) {
const valField = me.get('value-field');
me.get('options').forEach(option => {
Ember.set(option, 'selected', filters.includes(option.value));
filters.find(val => val == option[valField]) && set(option, 'selected', 'selected');
});
}
},
@ -39,7 +44,8 @@ export default Ember.Component.extend(BaseComponentMixin, {
let me = this;
me.set('showModal', false);
let filters = me.getFilters();
filters[me.get('name')] = me.get('options').filter(f => f.selected).map(f => f.value);
const valField = me.get('value-field');
filters[me.get('name')] = me.get('options').filter(f => f.selected).map(f => f[valField]);
me.set('route.controller.filters', JSON.stringify(filters));
me.get('router').transitionTo(me.get('routeName'), 1);
}

View File

@ -8,10 +8,19 @@ export default Helper.extend({
return getOwner(this).lookup('router:main');
}).readOnly(),
route: computed(function() {
return getOwner(this).lookup('route:' + this.get('router.currentRouteName'));
return this.getRoute(this.get('router.currentRouteName'));
}).readOnly(),
compute([attr]) {
let route = get(this, 'route');
getRoute(name) {
return getOwner(this).lookup('route:' + name);
},
compute([attr, routeName]) {
let route;
if (routeName) {
route = this.getRoute(routeName);
}
else {
route = get(this, 'route');
}
assert('[ember-route-action-helper] Unable to lookup router', route);
return get(route, attr);
}

View File

@ -0,0 +1,7 @@
import { helper } from '@ember/component/helper';
export function strSplit([str, sep]) {
return str ? str.split(sep || ',') : [];
}
export default helper(strSplit);

View File

@ -1,11 +1,16 @@
import Route from '@ember/routing/route';
import { on } from '@ember/object/evented';
export function initialize(/* appInstance */) {
Route.reopen({
afterModel() {
afterModel(model, transition) {
const me = this;
me._super(...arguments);
me.get('no-state') || me.get('state').push(me.get('router.currentURL'));
const routeName = me.get('fullRouteName');
transition.then(function() {
console.log('transition route: ', routeName, me.get('router.currentURL'));
});
}
});
}

View File

@ -6,8 +6,31 @@ 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);
if (model.applications) {
model.applicationsArray = model.applications.split(',');
model.applicationList.forEach(a => {
a.selected = model.applicationsArray.includes(a.id);
});
}
else {
model.applicationsArray = [];
}
Ember.addObserver(model, 'applicationsArray', function() {
Ember.Logger.info('Model application changed: ', model);
model.applications = model.applicationsArray.join(',');
me.get('service').update(model, true);
});
Ember.addObserver(model, 'status', function() {
Ember.Logger.info('Model status changed: ', model);
if (model.status) {
model.applications = model.applicationsArray.join(',');
me.get('service').update(model, true);
}
});
}
});

View File

@ -72,6 +72,16 @@ export default BaseListRoute.extend({
},
breadcrumbs: [{text: 'Customers'}],
tableOptions: TableOptions.create(),
afterModel(model, transition) {
const me = this;
model.issueOptions = [{value: 'true', text: 'Artificial'},
{value: 'false', text: 'System'},
{value: 'null', text: 'None'}];
transition.then(function() {
// store current url
me.set('state.CUSTOMER_LIST_ROUTE', me.get('router.currentURL'));
});
},
setupController(controller) {
let me = this;
me._super(...arguments);

View File

@ -8,10 +8,30 @@ export default BaseEditRoute.extend({
me.set('breadcrumbs',
[{route: 'customer.list', params: 1, text: 'Customers'},
{text: 'Show Customer [' + model.id + ']'}]);
Ember.addObserver(model, 'status', function() {
Ember.Logger.info('Model Status Changed: ', model);
if (model.applications) {
model.applicationsArray = model.applications.split(',');
model.applicationList.forEach(a => {
a.selected = model.applicationsArray.includes(a.id);
});
}
else {
model.applicationsArray = [];
}
Ember.addObserver(model, 'applicationsArray', function() {
Ember.Logger.info('Model application changed: ', model);
model.applications = model.applicationsArray.join(',');
me.get('service').update(model, true);
});
Ember.addObserver(model, 'status', function() {
Ember.Logger.info('Model status changed: ', model);
if (model.status) {
model.applications = model.applicationsArray.join(',');
me.get('service').update(model, true);
}
});
Ember.set(model, 'userAccounts', Ember.get(model, 'users').mapBy('account').join(', '));
},
actions: {
@ -24,6 +44,16 @@ export default BaseEditRoute.extend({
me.get('controller.model.issues').removeObject(issue);
});
});
},
backToList() {
const me = this;
const url = me.get('state.CUSTOMER_LIST_ROUTE');
if (url) {
me.transitionTo(url);
}
else {
me.transitionTo('customer.list', 1);
}
}
}
});

View File

@ -19,7 +19,6 @@ export default Service.extend({
back() {
const me = this;
const url = me.previous();
// if (pre && pre.retry();
if (url) {
const router = getOwner(this).lookup('router:main');
router.transitionTo(url);

View File

@ -1,12 +1,12 @@
{{#unless hideGoback}}
<button class="btn btn-prev" {{action 'goback'}}>
{{#unless not-goback}}
<button class="btn btn-prev" {{action (if on-goback on-goback 'goback')}}>
<i class="ace-icon fa fa-arrow-left"></i>
Goback
</button>
{{/unless}}
{{#unless hideSubmit}}
<button class="btn btn-success btn-next" {{action 'save'}}>
{{#unless no-submit}}
<button class="btn btn-success btn-next" {{action (if on-submit on-submit 'save')}}>
Submit
<i class="ace-icon fa fa-arrow-right icon-on-right"></i>
</button>

View File

@ -1,13 +1,19 @@
<span class="{{if filtered 'green'}} {{if (get this 'full-width') 'col-xs-12 no-padding'}}" data-rel="tooltip" title="Filter" {{action 'onClick'}}>
<span class="{{if filtered 'green'}} {{if (get this 'full-width') 'col-xs-12 no-padding'}}" data-rel="tooltip" title="Data Filter" {{action 'onClick'}}>
{{text}}
</span>
{{#if showModal}}
{{#modal-dialog title=(get this 'dialog-title') submit=(action 'onModalSubmit') on-close=(action 'onModalClose') transitionToParentRouteAfterClose=false}}
{{#modal-dialog title=(get this 'dialog-title') submit=(action 'onModalSubmit') on-close=(action 'onModalClose') close-to-parent=false}}
<div class="widget-body">
<div class="widget-main">
<form class="form-horizontal">
{{!form-input-chosen-select multiple=true col-width=12 label=(if label label text) options=options}}
{{form-input-select2 multiple=true col-width=12 label=(if label label text) options=options}}
{{form-input-select2
multiple=true
col-width=12
label=(if label label text)
options=options
value-field=(get this 'value-field')
text-field=(get this 'text-field')
}}
</form>
</div>
</div>

View File

@ -2,5 +2,6 @@
{{form-input type='hidden' name='customerId'}}
{{form-input name='issue' label='Comment' type='textarea'}}
<hr />
{{form-footer-buttons backRouteName='customer.show' backRouteParams=model.customerId}}
{{!form-footer-buttons backRouteName='customer.show' backRouteParams=model.customerId}}
{{form-footer-buttons}}
{{/form-content}}

View File

@ -3,5 +3,6 @@
{{form-input type='hidden' name='enabled'}}
{{form-input name='issue' label='Comment' type='textarea'}}
<hr />
{{form-footer-buttons type='update' backRouteName='customer.show' backRouteParams=model.customerId}}
{{!form-footer-buttons type='update' backRouteName='customer.show' backRouteParams=model.customerId}}
{{form-footer-buttons type='update'}}
{{/form-content}}

View File

@ -13,7 +13,6 @@
multiple=true
name='applications'
label='Application'
nullable=true
options=model.applicationList
value-field='id'
text-field='name'

View File

@ -65,7 +65,9 @@
{{sortable-th name='sumYtdSales' text='Sales(3Yrs)' style='min-width: 126px;'}}
{{/if}}
{{#if tableOptions.showIssue1}}
<th>Comment</th>
<th>
{{th-filter name='issue' text='Comment' label='Comment Filter' options=model.issueOptions}}
</th>
{{/if}}
{{#if tableOptions.showIssue2}}
<th>Comment 2</th>
@ -74,11 +76,23 @@
<th>Comment 3</th>
{{/if}}
{{#if tableOptions.showApplication}}
<th>Application</th>
<th>
{{th-filter name='application'
text='Application'
label='Application Filter'
options=model.applicationList
value-field='id'
text-field='name'}}
</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}}
{{th-filter name='status'
text='Status'
label='Status Filter'
options=model.statusList
value-field='id'
text-field='name'}}
{{/sortable-th}}
{{/if}}
{{#if tableOptions.showDateAdded}}
@ -209,7 +223,9 @@
{{/if}}
{{#if tableOptions.showApplication}}
<td>
{{it.application}}
{{#each (str-split it.applications) as |a|}}
{{option-text model.applicationList a 'id' 'name'}}
{{/each}}
</td>
{{/if}}
{{#if tableOptions.showStatus}}

View File

@ -8,12 +8,22 @@
{{form-input type='show' name='region' label='Region'}}
{{form-input type='show' name='salesperson' label='Salesperson'}}
{{form-input-modal-select
listRoute='customer.show.customer-status-select'
idField='status'
nameField='statusText'
btnIcon='fa-file-image-o'
label='Status'}}
{{form-input-select2
multiple=true
name='applicationsArray'
label='Application'
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'
}}
{{form-input type='show' label='Users' name='userAccounts'}}
{{!--
@ -136,6 +146,6 @@
</div>
{{/form-input}}
<hr />
{{form-footer-buttons hideSubmit=true}}
{{form-footer-buttons no-submit=true on-goback=(route-action 'backToList')}}
{{/form-content}}
{{outlet}}

View File

@ -0,0 +1,17 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('str-split', 'helper:str-split', {
integration: true
});
// Replace this with your real tests.
test('it renders', function(assert) {
this.set('inputValue', '1234');
this.render(hbs`{{str-split inputValue}}`);
assert.equal(this.$().text().trim(), '1234');
});