diff --git a/.gitignore b/.gitignore index f5a5cbd..9fcd666 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # See http://help.github.com/ignore-files/ for more about ignoring files. +/files + # compiled output /web/dist /web/tmp diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java index 73059f9..ca3ab38 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/ApplicationController.java @@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils; import com.pudonghot.ambition.crm.model.User; import org.springframework.stereotype.Controller; import com.pudonghot.ambition.crm.model.Application; -import org.springframework.web.multipart.MultipartFile; import org.apache.shiro.authz.annotation.RequiresRoles; import com.pudonghot.ambition.crm.model.CustomerProperty; import org.springframework.web.bind.annotation.RequestParam; @@ -71,34 +70,14 @@ public class ApplicationController @RequestMapping(value = "/create", method = RequestMethod.POST) public void create( @Valid ApplicationFormForCreate form) { - ((ApplicationService) queryService).create(form, null); - } - - @RequiresRoles(User.ROLE_ADMIN) - @RequestMapping(value = "/create-with-images", method = RequestMethod.POST) - public void create( - @Valid - ApplicationFormForCreate form, - @RequestParam("images") - MultipartFile[] images) { - - ((ApplicationService) queryService).create(form, images); + ((ApplicationService) queryService).create(form); } @RequiresRoles(User.ROLE_ADMIN) @RequestMapping(value = "/update", method = RequestMethod.POST) public void update( - @Valid ApplicationFormForUpdate form) { - ((ApplicationService) queryService).update(form, null); - } - - @RequiresRoles(User.ROLE_ADMIN) - @RequestMapping(value = "/update-with-images", method = RequestMethod.POST) - public void update( - @Valid ApplicationFormForUpdate form, - @RequestParam("images") - MultipartFile[] images) { - ((ApplicationService) queryService).update(form, images); + @Valid ApplicationFormForUpdate form) { + ((ApplicationService) queryService).update(form); } /** diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/FileController.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/FileController.java index d136fa0..1a63aa0 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/FileController.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/controller/FileController.java @@ -33,11 +33,11 @@ public class FileController { public Object file(HttpServletRequest request) { String reqUri = request.getRequestURI(); Assert.state(reqUri.length() > 3, "File name could not be blank"); - String fileName = reqUri.substring((request.getContextPath() + "/f/").length()); + final String fileName = reqUri.substring( + (request.getContextPath() + "/f/").length()).replaceAll("\\.\\w+$", ""); log.info("Get file [{}].", fileName); - final FileInfo fileInfo = fileInfoMapper.find(new Search(FileInfo.NAME, - fileName.replaceAll("\\.\\w+$", ""))); + final FileInfo fileInfo = fileInfoMapper.find(new Search(FileInfo.NAME, fileName)); ResourceModel rm = null; if (fileInfo != null) { File file = fileApi.getFile(fileName); @@ -47,7 +47,7 @@ public class FileController { rm.setName(fileInfo.getDownloadName()); } } - return rm != null ? + return rm != null ? rm : ResponseEntity.notFound().build(); } } diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ApplicationService.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ApplicationService.java index 74179b1..135fc3e 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ApplicationService.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/ApplicationService.java @@ -1,12 +1,8 @@ package com.pudonghot.ambition.crm.service; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - -import com.pudonghot.ambition.crm.form.update.ApplicationFormForUpdate; -import me.chyxion.tigon.service.BaseCrudService; import com.pudonghot.ambition.crm.model.Application; -import org.springframework.web.multipart.MultipartFile; +import me.chyxion.tigon.service.BaseCrudByFormService; +import com.pudonghot.ambition.crm.form.update.ApplicationFormForUpdate; import com.pudonghot.ambition.crm.form.create.ApplicationFormForCreate; /** @@ -15,10 +11,6 @@ import com.pudonghot.ambition.crm.form.create.ApplicationFormForCreate; * Jun 23, 2017 21:35:24 */ public interface ApplicationService - extends BaseCrudService { - - void create(@NotNull @Valid ApplicationFormForCreate form, MultipartFile[] images); - - void update(@NotNull @Valid ApplicationFormForUpdate form, MultipartFile[] images); + extends BaseCrudByFormService { } diff --git a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ApplicationServiceSupport.java b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ApplicationServiceSupport.java index 9d6cd4a..2c888cc 100644 --- a/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ApplicationServiceSupport.java +++ b/server/crm/src/main/java/com/pudonghot/ambition/crm/service/support/ApplicationServiceSupport.java @@ -4,6 +4,7 @@ import java.util.Date; import java.io.IOException; import java.io.InputStream; import lombok.extern.slf4j.Slf4j; +import me.chyxion.tigon.model.ViewModel; import org.springframework.stereotype.Service; import com.pudonghot.ambition.file.AmbitionFileApi; import com.pudonghot.ambition.crm.model.Application; @@ -37,17 +38,20 @@ public class ApplicationServiceSupport * {@inheritDoc} */ @Override - public void create(final ApplicationFormForCreate form, final MultipartFile[] images) { + public ViewModel create(final ApplicationFormForCreate form) { final String id = idSeq.get(); final Application application = form.copy(new Application()); application.setId(id); final Date now = new Date(); application.setDateUpdated(now); + final MultipartFile[] images = form.getImages(); if (images != null) { final String createdBy = form.getCreatedBy(); int sort = 0; final String imageFolder = imageFolder(id); + final String[] imageTitles = form.getImageTitles(); + int i = 0; for (final MultipartFile image : images) { if (!image.isEmpty()) { try (final InputStream ins = image.getInputStream()) { @@ -57,26 +61,29 @@ public class ApplicationServiceSupport appImage.setId(imageId); appImage.setApplicationId(id); appImage.setSort(sort++); + appImage.setNote(imageTitles[i]); appImage.setCreatedBy(createdBy); appImage.setDateCreated(now); imageMapper.insert(appImage); } - catch (IOException e) { + catch (final IOException e) { throw new IllegalStateException( "Read upload image [" + image.getOriginalFilename() + "] error cased", e); } } + ++i; } } mapper.insert(application); + return toViewModel(application); } /** * {@inheritDoc} */ @Override - public void update(final ApplicationFormForUpdate form, final MultipartFile[] images) { - + public ViewModel update(final ApplicationFormForUpdate form) { + return null; } private String imageFolder(final String appId) { diff --git a/server/file-disk/src/main/java/com/pudonghot/ambition/file/disk/DiskFileSupport.java b/server/file-disk/src/main/java/com/pudonghot/ambition/file/disk/DiskFileSupport.java index bffba4b..4945fb0 100644 --- a/server/file-disk/src/main/java/com/pudonghot/ambition/file/disk/DiskFileSupport.java +++ b/server/file-disk/src/main/java/com/pudonghot/ambition/file/disk/DiskFileSupport.java @@ -172,7 +172,7 @@ public class DiskFileSupport final FileInfo fileInfo = fileInfoMapper.find(nameSearch(name)); Assert.state(fileInfo != null, "No File [" + name + "] Found"); - return getFile(fileInfo.getFilePath(), fileInfo.getFormat()); + return new File(getFileDir(), fileInfo.getFilePath()); } /** @@ -221,12 +221,6 @@ public class DiskFileSupport return new Search(FileInfo.NAME, name); } - private File getFile(final String name, String format) { - return new File(getFileDir(), - StringUtils.isNotBlank(format) ? - name + "." + format : name); - } - File getFileDir() { File baseFileDir = new File(baseDir); if (!baseFileDir.exists()) { @@ -279,9 +273,9 @@ public class DiskFileSupport String filePath = null; if (StringUtils.isNotBlank(name)) { - log.debug("Name [{}] Is Not Blank.", name); + log.debug("Name [{}] is not blank.", name); if (name.startsWith(basePath)) { - log.debug("Name Starts With Base Path [{}], Trim.", basePath); + log.debug("Name starts with base path [{}], trim.", basePath); filePath = name.replaceFirst(basePath, ""); } else { diff --git a/server/model/src/main/java/com/pudonghot/ambition/crm/form/create/ApplicationFormForCreate.java b/server/model/src/main/java/com/pudonghot/ambition/crm/form/create/ApplicationFormForCreate.java index 3206a18..e6d91d3 100644 --- a/server/model/src/main/java/com/pudonghot/ambition/crm/form/create/ApplicationFormForCreate.java +++ b/server/model/src/main/java/com/pudonghot/ambition/crm/form/create/ApplicationFormForCreate.java @@ -3,7 +3,10 @@ package com.pudonghot.ambition.crm.form.create; import lombok.Getter; import lombok.Setter; import me.chyxion.tigon.form.FC2; +import me.chyxion.tigon.format.annotation.Trim; import org.hibernate.validator.constraints.NotBlank; +import me.chyxion.tigon.format.annotation.EmptyToNull; +import org.springframework.web.multipart.MultipartFile; /** * @author Shaun Chyxion
@@ -16,8 +19,15 @@ public class ApplicationFormForCreate extends FC2 { private static final long serialVersionUID = 1L; // Properties + @Trim @NotBlank private String name; + @Trim + @EmptyToNull private String content; + @Trim + @EmptyToNull private String owner; + private String[] imageTitles; + private MultipartFile[] images; } diff --git a/server/model/src/main/java/com/pudonghot/ambition/crm/form/update/ApplicationFormForUpdate.java b/server/model/src/main/java/com/pudonghot/ambition/crm/form/update/ApplicationFormForUpdate.java index 4b2e84f..bf4490f 100644 --- a/server/model/src/main/java/com/pudonghot/ambition/crm/form/update/ApplicationFormForUpdate.java +++ b/server/model/src/main/java/com/pudonghot/ambition/crm/form/update/ApplicationFormForUpdate.java @@ -3,8 +3,11 @@ package com.pudonghot.ambition.crm.form.update; import lombok.Getter; import lombok.Setter; import me.chyxion.tigon.form.FU2; +import me.chyxion.tigon.format.annotation.Trim; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotBlank; +import me.chyxion.tigon.format.annotation.EmptyToNull; +import org.springframework.web.multipart.MultipartFile; /** * @version 0.0.1 @@ -21,4 +24,12 @@ public class ApplicationFormForUpdate extends FU2 { @NotBlank @Length(max = 64) private String name; + @Trim + @EmptyToNull + private String content; + @Trim + @EmptyToNull + private String owner; + private String[] imageTitles; + private MultipartFile[] images; } diff --git a/web/app/components/image-input.js b/web/app/components/image-input.js index 9f91061..0a3e6b8 100644 --- a/web/app/components/image-input.js +++ b/web/app/components/image-input.js @@ -1,7 +1,10 @@ import Ember from 'ember'; import Component from '@ember/component'; +import { computed } from '@ember/object'; export default Component.extend({ + image: {}, + value: computed.alias('image.file'), didReceiveAttrs() { const me = this; me._super(...arguments); diff --git a/web/app/routes/customer-application/create.js b/web/app/routes/customer-application/create.js index aa16eef..c172484 100644 --- a/web/app/routes/customer-application/create.js +++ b/web/app/routes/customer-application/create.js @@ -1,25 +1,29 @@ import Ember from 'ember'; import BaseRoute from '../base'; +import EmberObject, { computed } from '@ember/object'; 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'}], + modelClass: EmberObject.extend({ + hasImage: computed('images.@each.file', function() { + return this.get('images').filter(image => image.file).length > 0; + }) + }), model() { - return { - type: 'APPLICATION', + return this.get('modelClass').create({ enabled: true, images: [{}] - }; + }); }, actions: { addImage() { const me = this; me.get('controller.model.images').pushObject({}); }, - removeImage(img) { + removeImage(image) { const me = this; - me.get('controller.model.images').removeObject(img); + me.get('controller.model.images').removeObject(image); }, } }); diff --git a/web/app/routes/customer-application/list.js b/web/app/routes/customer-application/list.js index 8a2149f..18c105f 100644 --- a/web/app/routes/customer-application/list.js +++ b/web/app/routes/customer-application/list.js @@ -1,9 +1,9 @@ import Ember from 'ember'; -import CustomerPropertyListRoute from './../customer-property/list'; +import BaseListRoute from './../base-list'; -export default CustomerPropertyListRoute.extend({ +export default BaseListRoute.extend({ breadcrumbs: [{text: 'Customer Application'}], - model(params) { - return this.get('store').ajaxGet('customer-property/app-list', params); - } + // model(params) { + // return this.get('store').ajaxGet('customer-property/app-list', params); + // } }); diff --git a/web/app/services/customer-application/service.js b/web/app/services/customer-application/service.js new file mode 100644 index 0000000..e26a37f --- /dev/null +++ b/web/app/services/customer-application/service.js @@ -0,0 +1,15 @@ +import Ember from 'ember'; +import BaseService from '../service'; + +export default BaseService.extend({ + modelName: 'Application', + constraints: { + name: { + presence: true, + length: { + minimum: 1, + maximum: 36 + } + } + } +}); diff --git a/web/app/templates/customer-application/create.hbs b/web/app/templates/customer-application/create.hbs index 74f2a42..ddbc999 100644 --- a/web/app/templates/customer-application/create.hbs +++ b/web/app/templates/customer-application/create.hbs @@ -17,16 +17,16 @@
- {{#each model.images as |img|}} + {{#each model.images as |image i|}}
- {{input name='imageTitle' class='width-80' placeholder='Image title'}} + {{input name=(concat 'imageTitles[' i ']') class='width-80' placeholder='Image title' value=image.title}}   - +
- {{image-input name='image'}} + {{image-input name=(concat 'images[' i ']') image=image}}
{{/each}} @@ -34,8 +34,6 @@
{{/form-input}} - {{!form-input type='image' name='images' label='Image' input-class='col-xs-2'}} - {{!form-input-enabled label='Enabled' enabledText='TRUE' disabledText='FALSE'}} {{form-input name='note' label='Remark'}}
{{form-footer-buttons}} diff --git a/web/app/templates/customer-application/list.hbs b/web/app/templates/customer-application/list.hbs index 2d2dc75..6244002 100644 --- a/web/app/templates/customer-application/list.hbs +++ b/web/app/templates/customer-application/list.hbs @@ -117,7 +117,7 @@ - {{!pagination-bar}} + {{pagination-bar}} {{/main-content}} diff --git a/web/tests/unit/services/customer-application/service-test.js b/web/tests/unit/services/customer-application/service-test.js new file mode 100644 index 0000000..17f1d12 --- /dev/null +++ b/web/tests/unit/services/customer-application/service-test.js @@ -0,0 +1,12 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('service:customer-application/service', 'Unit | Service | customer application/service', { + // 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); +});