응답 관리 그룹 추가
This commit is contained in:
@@ -0,0 +1,129 @@
|
|||||||
|
package com.eactive.testmaster.api.controller;
|
||||||
|
|
||||||
|
import com.eactive.testmaster.api.dto.MockRouteGroupSearch;
|
||||||
|
import com.eactive.testmaster.api.entity.MockRouteGroup;
|
||||||
|
import com.eactive.testmaster.api.repository.MockRouteGroupRepository;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/mgmt/routes/group")
|
||||||
|
public class MockRouteGroupController {
|
||||||
|
|
||||||
|
private static final String GROUP = "group";
|
||||||
|
private static final String GROUP_LIST_VIEW = "page/routes/groupList";
|
||||||
|
private static final String GROUP_EDIT = "page/routes/groupEdit";
|
||||||
|
private static final String REDIRECT_TO_LIST = "redirect:/mgmt/routes/group/list_view.do";
|
||||||
|
|
||||||
|
private final MockRouteGroupRepository mockRouteGroupRepository;
|
||||||
|
private final MockRouteGroupValidator mockRouteGroupValidator;
|
||||||
|
|
||||||
|
public MockRouteGroupController(MockRouteGroupRepository mockRouteGroupRepository,
|
||||||
|
MockRouteGroupValidator mockRouteGroupValidator) {
|
||||||
|
this.mockRouteGroupRepository = mockRouteGroupRepository;
|
||||||
|
this.mockRouteGroupValidator = mockRouteGroupValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@InitBinder("group")
|
||||||
|
public void initBinder(WebDataBinder binder) {
|
||||||
|
binder.setValidator(mockRouteGroupValidator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list_view.do")
|
||||||
|
@Secured("ROLE_MANAGE_ROUTE")
|
||||||
|
public ModelAndView listView(@ModelAttribute("groupSearch") MockRouteGroupSearch groupSearch,
|
||||||
|
Pageable pageable) {
|
||||||
|
ModelAndView mav = new ModelAndView(GROUP_LIST_VIEW);
|
||||||
|
Page<MockRouteGroup> page = mockRouteGroupRepository.findAll(
|
||||||
|
groupSearch.buildSpecification(), pageable);
|
||||||
|
mav.addObject("page", page);
|
||||||
|
mav.addObject("pageable", pageable);
|
||||||
|
mav.addObject("modelSearch", groupSearch);
|
||||||
|
return mav;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/create_view.do")
|
||||||
|
@Secured("ROLE_MANAGE_ROUTE")
|
||||||
|
public ModelAndView createView() {
|
||||||
|
ModelAndView mav = new ModelAndView(GROUP_EDIT);
|
||||||
|
mav.addObject(GROUP, new MockRouteGroup());
|
||||||
|
return mav;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/update_view.do")
|
||||||
|
@Secured("ROLE_MANAGE_ROUTE")
|
||||||
|
public ModelAndView updateView(@RequestParam("id") String id) {
|
||||||
|
ModelAndView mav = new ModelAndView(GROUP_EDIT);
|
||||||
|
MockRouteGroup group = mockRouteGroupRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Group not found"));
|
||||||
|
mav.addObject(GROUP, group);
|
||||||
|
return mav;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/register.do")
|
||||||
|
@Secured("ROLE_MANAGE_ROUTE")
|
||||||
|
public String register(@Valid @ModelAttribute(GROUP) MockRouteGroup group,
|
||||||
|
BindingResult bindingResult,
|
||||||
|
ModelMap model) {
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
model.addAttribute(GROUP, group);
|
||||||
|
return GROUP_EDIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mockRouteGroupRepository.save(group);
|
||||||
|
return REDIRECT_TO_LIST;
|
||||||
|
} catch (Exception e) {
|
||||||
|
bindingResult.rejectValue("id", "error.save.failed",
|
||||||
|
"Failed to save group: " + e.getMessage());
|
||||||
|
model.addAttribute(GROUP, group);
|
||||||
|
return GROUP_EDIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/update.do")
|
||||||
|
@Secured("ROLE_MANAGE_ROUTE")
|
||||||
|
public String update(@RequestParam("id") String id,
|
||||||
|
@Valid @ModelAttribute(GROUP) MockRouteGroup group,
|
||||||
|
BindingResult bindingResult,
|
||||||
|
ModelMap model) {
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
model.addAttribute(GROUP, group);
|
||||||
|
return GROUP_EDIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
MockRouteGroup existingGroup = mockRouteGroupRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Group not found"));
|
||||||
|
existingGroup.setName(group.getName());
|
||||||
|
mockRouteGroupRepository.save(existingGroup);
|
||||||
|
return REDIRECT_TO_LIST;
|
||||||
|
} catch (Exception e) {
|
||||||
|
bindingResult.rejectValue("name", "error.update.failed",
|
||||||
|
"Failed to update group: " + e.getMessage());
|
||||||
|
model.addAttribute(GROUP, group);
|
||||||
|
return GROUP_EDIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete.do")
|
||||||
|
@Secured("ROLE_MANAGE_ROUTE")
|
||||||
|
public String delete(@RequestParam("checkedIdForDel") List<String> ids) {
|
||||||
|
try {
|
||||||
|
mockRouteGroupRepository.deleteAllById(ids);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Log error but continue
|
||||||
|
}
|
||||||
|
return REDIRECT_TO_LIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
package com.eactive.testmaster.api.controller;
|
||||||
|
|
||||||
|
import com.eactive.testmaster.api.dto.MockRouteGroupSearch;
|
||||||
|
import com.eactive.testmaster.api.entity.MockRouteGroup;
|
||||||
|
import com.eactive.testmaster.api.repository.MockRouteGroupRepository;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.BeanPropertyBindingResult;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/mock-route-groups")
|
||||||
|
public class MockRouteGroupRestController {
|
||||||
|
|
||||||
|
private final MockRouteGroupRepository mockRouteGroupRepository;
|
||||||
|
private final MockRouteGroupValidator mockRouteGroupValidator;
|
||||||
|
|
||||||
|
public MockRouteGroupRestController(MockRouteGroupRepository mockRouteGroupRepository,
|
||||||
|
MockRouteGroupValidator mockRouteGroupValidator) {
|
||||||
|
this.mockRouteGroupRepository = mockRouteGroupRepository;
|
||||||
|
this.mockRouteGroupValidator = mockRouteGroupValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<Page<MockRouteGroup>> listGroups(
|
||||||
|
@RequestParam(required = false) String name,
|
||||||
|
@RequestParam(defaultValue = "0") int page,
|
||||||
|
@RequestParam(defaultValue = "10") int size) {
|
||||||
|
|
||||||
|
MockRouteGroupSearch search = new MockRouteGroupSearch();
|
||||||
|
search.setName(name);
|
||||||
|
|
||||||
|
Pageable pageable = PageRequest.of(page, size);
|
||||||
|
Page<MockRouteGroup> groups = mockRouteGroupRepository.findAll(
|
||||||
|
search.buildSpecification(),
|
||||||
|
pageable
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<MockRouteGroup> getGroup(@PathVariable String id) {
|
||||||
|
return mockRouteGroupRepository.findById(id)
|
||||||
|
.map(ResponseEntity::ok)
|
||||||
|
.orElse(ResponseEntity.notFound().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<?> createGroup(@RequestBody MockRouteGroup group) {
|
||||||
|
// Validate using the custom validator
|
||||||
|
Errors errors = new BeanPropertyBindingResult(group, "group");
|
||||||
|
mockRouteGroupValidator.validate(group, errors);
|
||||||
|
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
Map<String, String> validationErrors = new HashMap<>();
|
||||||
|
errors.getFieldErrors().forEach(error ->
|
||||||
|
validationErrors.put(error.getField(), error.getDefaultMessage())
|
||||||
|
);
|
||||||
|
return ResponseEntity.badRequest().body(validationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
MockRouteGroup saved = mockRouteGroupRepository.save(group);
|
||||||
|
return ResponseEntity.ok(saved);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body("Failed to create group: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/update/{id}")
|
||||||
|
public ResponseEntity<?> updateGroup(
|
||||||
|
@PathVariable String id, @RequestBody MockRouteGroup group) {
|
||||||
|
|
||||||
|
// Validate using the custom validator
|
||||||
|
Errors errors = new BeanPropertyBindingResult(group, "group");
|
||||||
|
mockRouteGroupValidator.validate(group, errors);
|
||||||
|
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
Map<String, String> validationErrors = new HashMap<>();
|
||||||
|
errors.getFieldErrors().forEach(error ->
|
||||||
|
validationErrors.put(error.getField(), error.getDefaultMessage())
|
||||||
|
);
|
||||||
|
return ResponseEntity.badRequest().body(validationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return mockRouteGroupRepository.findById(id)
|
||||||
|
.map(existingGroup -> {
|
||||||
|
existingGroup.setName(group.getName());
|
||||||
|
MockRouteGroup updated = mockRouteGroupRepository.save(existingGroup);
|
||||||
|
return ResponseEntity.ok(updated);
|
||||||
|
})
|
||||||
|
.orElse(ResponseEntity.notFound().build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body("Failed to update group: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public ResponseEntity<Void> deleteGroups(@RequestBody List<String> ids) {
|
||||||
|
try {
|
||||||
|
mockRouteGroupRepository.deleteAllById(ids);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.eactive.testmaster.api.controller;
|
||||||
|
|
||||||
|
import com.eactive.testmaster.api.entity.MockRouteGroup;
|
||||||
|
import com.eactive.testmaster.api.repository.MockRouteGroupRepository;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MockRouteGroupValidator implements Validator {
|
||||||
|
|
||||||
|
private final MockRouteGroupRepository mockRouteGroupRepository;
|
||||||
|
|
||||||
|
public MockRouteGroupValidator(MockRouteGroupRepository mockRouteGroupRepository) {
|
||||||
|
this.mockRouteGroupRepository = mockRouteGroupRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> clazz) {
|
||||||
|
return MockRouteGroup.class.equals(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(Object target, Errors errors) {
|
||||||
|
MockRouteGroup group = (MockRouteGroup) target;
|
||||||
|
|
||||||
|
// Validate ID
|
||||||
|
if (group.getId() == null || group.getId().trim().isEmpty()) {
|
||||||
|
errors.rejectValue("id", "error.id.required", "Group ID is required");
|
||||||
|
} else if (!group.getId().matches("^[a-zA-Z0-9_-]+$")) {
|
||||||
|
errors.rejectValue("id", "error.id.invalid", "Group ID must contain only letters, numbers, underscores, and hyphens");
|
||||||
|
} else if (group.getId().length() > 50) {
|
||||||
|
errors.rejectValue("id", "error.id.length", "Group ID must not exceed 50 characters");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate Name
|
||||||
|
if (group.getName() == null || group.getName().trim().isEmpty()) {
|
||||||
|
errors.rejectValue("name", "error.name.required", "Group name is required");
|
||||||
|
} else if (group.getName().length() > 100) {
|
||||||
|
errors.rejectValue("name", "error.name.length", "Group name must not exceed 100 characters");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate ID on creation
|
||||||
|
if (group.getId() != null && !errors.hasFieldErrors("id")) {
|
||||||
|
mockRouteGroupRepository.findById(group.getId())
|
||||||
|
.ifPresent(existingGroup -> errors.rejectValue("id", "error.id.duplicate", "Group ID already exists"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import com.eactive.testmaster.api.dto.MockRouteSearch;
|
|||||||
import com.eactive.testmaster.api.dto.MockRouteUpdateDTO;
|
import com.eactive.testmaster.api.dto.MockRouteUpdateDTO;
|
||||||
import com.eactive.testmaster.api.entity.MockRoute;
|
import com.eactive.testmaster.api.entity.MockRoute;
|
||||||
import com.eactive.testmaster.api.mapper.MockRouteMapper;
|
import com.eactive.testmaster.api.mapper.MockRouteMapper;
|
||||||
|
import com.eactive.testmaster.api.repository.MockRouteGroupRepository;
|
||||||
import com.eactive.testmaster.api.service.MockRouteService;
|
import com.eactive.testmaster.api.service.MockRouteService;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
@@ -43,11 +44,14 @@ public class MockRouteMgmtController {
|
|||||||
|
|
||||||
private final MockApiHandlerMapping mockApiHandlerMapping;
|
private final MockApiHandlerMapping mockApiHandlerMapping;
|
||||||
|
|
||||||
public MockRouteMgmtController(MockRouteService mockRouteService, Validator validator, MockRouteMapper mockRouteMapper, MockApiHandlerMapping mockApiHandlerMapping) {
|
private final MockRouteGroupRepository mockRouteGroupRepository;
|
||||||
|
|
||||||
|
public MockRouteMgmtController(MockRouteService mockRouteService, Validator validator, MockRouteMapper mockRouteMapper, MockApiHandlerMapping mockApiHandlerMapping, MockRouteGroupRepository mockRouteGroupRepository) {
|
||||||
this.mockRouteService = mockRouteService;
|
this.mockRouteService = mockRouteService;
|
||||||
this.validator = validator;
|
this.validator = validator;
|
||||||
this.mockRouteMapper = mockRouteMapper;
|
this.mockRouteMapper = mockRouteMapper;
|
||||||
this.mockApiHandlerMapping = mockApiHandlerMapping;
|
this.mockApiHandlerMapping = mockApiHandlerMapping;
|
||||||
|
this.mockRouteGroupRepository = mockRouteGroupRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String MOCK_ROUTE_EDIT = "page/routes/mockRouteEdit";
|
public static final String MOCK_ROUTE_EDIT = "page/routes/mockRouteEdit";
|
||||||
@@ -61,6 +65,7 @@ public class MockRouteMgmtController {
|
|||||||
mav.addObject("page", page);
|
mav.addObject("page", page);
|
||||||
mav.addObject("pageable", pageable);
|
mav.addObject("pageable", pageable);
|
||||||
mav.addObject("modelSearch", mockRouteSearch);
|
mav.addObject("modelSearch", mockRouteSearch);
|
||||||
|
mav.addObject("groupList", mockRouteGroupRepository.findAll());
|
||||||
|
|
||||||
return mav;
|
return mav;
|
||||||
}
|
}
|
||||||
@@ -74,6 +79,7 @@ public class MockRouteMgmtController {
|
|||||||
defaultResponse.setDefaultResponse("true");
|
defaultResponse.setDefaultResponse("true");
|
||||||
defaultRoute.getResponses().add(defaultResponse);
|
defaultRoute.getResponses().add(defaultResponse);
|
||||||
mav.addObject(MOCK_ROUTE, defaultRoute);
|
mav.addObject(MOCK_ROUTE, defaultRoute);
|
||||||
|
mav.addObject("groupList", mockRouteGroupRepository.findAll());
|
||||||
return mav;
|
return mav;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +90,7 @@ public class MockRouteMgmtController {
|
|||||||
ModelAndView mav = new ModelAndView(MOCK_ROUTE_EDIT);
|
ModelAndView mav = new ModelAndView(MOCK_ROUTE_EDIT);
|
||||||
MockRoute found = mockRouteService.findById(id);
|
MockRoute found = mockRouteService.findById(id);
|
||||||
mav.addObject(MOCK_ROUTE, mockRouteMapper.map(found));
|
mav.addObject(MOCK_ROUTE, mockRouteMapper.map(found));
|
||||||
|
mav.addObject("groupList", mockRouteGroupRepository.findAll());
|
||||||
return mav;
|
return mav;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +103,7 @@ public class MockRouteMgmtController {
|
|||||||
MockRouteRegisterDTO dto = mockRouteMapper.map(found);
|
MockRouteRegisterDTO dto = mockRouteMapper.map(found);
|
||||||
dto.setId(null);
|
dto.setId(null);
|
||||||
mav.addObject(MOCK_ROUTE, dto);
|
mav.addObject(MOCK_ROUTE, dto);
|
||||||
|
mav.addObject("groupList", mockRouteGroupRepository.findAll());
|
||||||
|
|
||||||
return mav;
|
return mav;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.eactive.testmaster.api.dto;
|
||||||
|
|
||||||
|
import com.eactive.testmaster.common.search.BaseSearch;
|
||||||
|
import com.eactive.testmaster.common.search.ColumnSearchModel;
|
||||||
|
import com.eactive.testmaster.common.search.SearchCondition;
|
||||||
|
import com.eactive.testmaster.common.search.SearchModel;
|
||||||
|
import com.eactive.testmaster.api.entity.MockRouteGroup;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MockRouteGroupSearch implements BaseSearch<MockRouteGroup> {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SearchModel> buildSearchCondition() {
|
||||||
|
List<SearchModel> models = new ArrayList<>();
|
||||||
|
models.add(new ColumnSearchModel("id", SearchCondition.LIKE, id));
|
||||||
|
models.add(new ColumnSearchModel("name", SearchCondition.LIKE, name));
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -20,6 +20,8 @@ public class MockRouteRegisterDTO {
|
|||||||
@NotEmpty
|
@NotEmpty
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
private String group;
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
private String requestScript;
|
private String requestScript;
|
||||||
@@ -82,4 +84,12 @@ public class MockRouteRegisterDTO {
|
|||||||
public void setRequestScript(String requestScript) {
|
public void setRequestScript(String requestScript) {
|
||||||
this.requestScript = requestScript;
|
this.requestScript = requestScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,13 @@ public class MockRouteSearch implements BaseSearch<MockRoute> {
|
|||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
private String group;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SearchModel> buildSearchCondition() {
|
public List<SearchModel> buildSearchCondition() {
|
||||||
List<SearchModel> models = new ArrayList<>();
|
List<SearchModel> models = new ArrayList<>();
|
||||||
models.add(new ColumnSearchModel("name", SearchCondition.LIKE, name));
|
models.add(new ColumnSearchModel("name", SearchCondition.LIKE, name));
|
||||||
|
models.add(new ColumnSearchModel("group", SearchCondition.EQUAL, group));
|
||||||
return models;
|
return models;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,4 +30,11 @@ public class MockRouteSearch implements BaseSearch<MockRoute> {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public class MockRouteUpdateDTO {
|
|||||||
|
|
||||||
private String requestScript;
|
private String requestScript;
|
||||||
|
|
||||||
|
private String group;
|
||||||
|
|
||||||
@Size(min = 1, message = "Response must have at least one item")
|
@Size(min = 1, message = "Response must have at least one item")
|
||||||
private List<MockResponseDTO> responses = new ArrayList<>();
|
private List<MockResponseDTO> responses = new ArrayList<>();
|
||||||
@@ -81,4 +82,12 @@ public class MockRouteUpdateDTO {
|
|||||||
public void setRequestScript(String requestScript) {
|
public void setRequestScript(String requestScript) {
|
||||||
this.requestScript = requestScript;
|
this.requestScript = requestScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonManagedReference;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
@@ -30,6 +31,9 @@ public class MockRoute {
|
|||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = "MOCK_GROUP")
|
||||||
|
private String group;
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
private String requestScript;
|
private String requestScript;
|
||||||
|
|
||||||
@@ -85,7 +89,6 @@ public class MockRoute {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getRequestScript() {
|
public String getRequestScript() {
|
||||||
return requestScript;
|
return requestScript;
|
||||||
}
|
}
|
||||||
@@ -93,4 +96,12 @@ public class MockRoute {
|
|||||||
public void setRequestScript(String requestScript) {
|
public void setRequestScript(String requestScript) {
|
||||||
this.requestScript = requestScript;
|
this.requestScript = requestScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.eactive.testmaster.api.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "MOCK_ROUTE_GROUP")
|
||||||
|
public class MockRouteGroup {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.eactive.testmaster.api.repository;
|
||||||
|
|
||||||
|
import com.eactive.testmaster.api.entity.MockRouteGroup;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
|
||||||
|
public interface MockRouteGroupRepository extends JpaRepository<MockRouteGroup, String>, JpaSpecificationExecutor<MockRouteGroup> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -75,6 +75,7 @@ public class MockRouteService {
|
|||||||
route.setName(updated.getName());
|
route.setName(updated.getName());
|
||||||
route.setDescription(updated.getDescription());
|
route.setDescription(updated.getDescription());
|
||||||
route.setRequestScript(updated.getRequestScript());
|
route.setRequestScript(updated.getRequestScript());
|
||||||
|
route.setGroup(updated.getGroup());
|
||||||
if (!route.getPathPattern().startsWith("/")) {
|
if (!route.getPathPattern().startsWith("/")) {
|
||||||
route.setPathPattern("/" + route.getPathPattern());
|
route.setPathPattern("/" + route.getPathPattern());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/default_layout}">
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<section layout:fragment="contentFragment">
|
||||||
|
<div class="container-fluid mt-2">
|
||||||
|
<form name="groupForm" id="groupForm"
|
||||||
|
th:action="${group.id == null}?@{/mgmt/routes/group/register.do}:@{/mgmt/routes/group/update.do}"
|
||||||
|
th:object='${group}' method="post">
|
||||||
|
<div class="card col-md">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 th:if="${group.id == null}">API 그룹 등록</h3>
|
||||||
|
<h3 th:if="${group.id != null}">API 그룹 수정</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||||
|
<input type="hidden" name="id" th:value="${group.id}" th:if="${group.id != null}">
|
||||||
|
|
||||||
|
<div class="form-floating mt-2">
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
th:classappend="${#fields.hasErrors('id')}? 'is-invalid'"
|
||||||
|
th:field="*{id}" required th:readonly="${group.id != null}"/>
|
||||||
|
<label for="id" class="form-label must">그룹 ID</label>
|
||||||
|
<th:block th:each="err : ${#fields.errors('id')}">
|
||||||
|
<div th:text="${err}" class="invalid-feedback"></div>
|
||||||
|
</th:block>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating mt-2">
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
th:classappend="${#fields.hasErrors('name')}? 'is-invalid'"
|
||||||
|
th:field="*{name}" required/>
|
||||||
|
<label for="name" class="form-label must">그룹명</label>
|
||||||
|
<th:block th:each="err : ${#fields.errors('name')}">
|
||||||
|
<div th:text="${err}" class="invalid-feedback"></div>
|
||||||
|
</th:block>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<button type="button" class="btn btn-primary btn_list">
|
||||||
|
<i class="fa-solid fa-list"></i> 목록
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary btn_register">
|
||||||
|
<i class="fa-sharp fa-solid fa-floppy-disk"></i> 저장
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<th:block layout:fragment="contentScript">
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
let fnRegister = document.querySelector(".btn_register");
|
||||||
|
let fnList = document.querySelector(".btn_list");
|
||||||
|
|
||||||
|
fnRegister.addEventListener("click", function (event) {
|
||||||
|
let form = document.getElementById("groupForm");
|
||||||
|
if (!form.checkValidity()) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
} else {
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
form.classList.add('was-validated');
|
||||||
|
});
|
||||||
|
|
||||||
|
fnList.addEventListener("click", function () {
|
||||||
|
location.href = "[[@{/mgmt/routes/group/list_view.do}]]";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/default_layout}">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<section layout:fragment="contentFragment">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5><span style="font-weight: bold">API 그룹 목록</span></h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<form role="form" class="row g-3" name="searchForm" th:action="@{/mgmt/routes/group/list_view.do}" method="get">
|
||||||
|
<input name="page" type="hidden" value="1"/>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button type="button" class="btn btn-primary btn_delete">
|
||||||
|
<i class="fa-sharp fa-solid fa-trash"></i> [[#{title.delete}]]
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button type="button" class="btn btn-primary btn_add">
|
||||||
|
<i class="fa-sharp fa-solid fa-plus"></i> [[#{button.create}]]
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<form name="listForm">
|
||||||
|
<input name="id" type="hidden"/>
|
||||||
|
<input name="checkedIdForDel" type="hidden"/>
|
||||||
|
<input id="csrf" type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||||
|
<table class="table table-hover pt-table">
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 5%;">
|
||||||
|
<col style="width: 5%;">
|
||||||
|
<col style="width: 20%;">
|
||||||
|
<col>
|
||||||
|
<col style="width: 12%;">
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><div class="text-center">번호</div></th>
|
||||||
|
<th>
|
||||||
|
<div class="text-center">
|
||||||
|
<input type="checkbox" name="checkAll" class="form-check-input" onclick="fncCheckAll()" th:title="#{input.selectAll.title}">
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<th><div class="text-center">ID</div></th>
|
||||||
|
<th><div class="text-center">이름</div></th>
|
||||||
|
<th><div class="text-center">비고</div></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="row, status : ${page.content}">
|
||||||
|
<td class="text-center" th:text="${page.getNumber() * page.getSize() + status.count}"></td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<input type="checkbox" name="checkField" class="form-check-input" title="선택"/>
|
||||||
|
<input name="checkId" type="hidden" th:value="${row.id}"/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span th:text="${row.id}"></span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span th:text="${row.name}"></span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<button type="button" class="btn btn-primary btn-sm me-2" th:onclick="fnSelectItem([[${row.id}]])" th:value="#{button.update}">
|
||||||
|
<i class="fa-sharp fa-solid fa-edit"></i> [[#{button.update}]]
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr th:if="${page.content.size() == 0}">
|
||||||
|
<td colspan="5" th:text="#{common.nodata.msg}"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div th:replace="~{fragment/pagination :: pagination(jsFunction='fn_select_page')}"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<th:block layout:fragment="contentScript">
|
||||||
|
<script>
|
||||||
|
function fn_select_page(pageNo) {
|
||||||
|
document.searchForm.page.value = pageNo;
|
||||||
|
document.searchForm.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fnSelectItem(id) {
|
||||||
|
location.href = "[[@{/mgmt/routes/group/update_view.do}]]" + "?id=" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
let fnDelete = document.querySelector(".btn_delete");
|
||||||
|
let fnAdd = document.querySelector(".btn_add");
|
||||||
|
|
||||||
|
fnDelete.addEventListener("click", function () {
|
||||||
|
var checkField = document.listForm.checkField;
|
||||||
|
var id = document.listForm.checkId;
|
||||||
|
var checkedIds = "";
|
||||||
|
var checkedCount = 0;
|
||||||
|
if (checkField) {
|
||||||
|
if (checkField.length > 1) {
|
||||||
|
for (var i = 0; i < checkField.length; i++) {
|
||||||
|
if (checkField[i].checked) {
|
||||||
|
checkedIds += ((checkedCount == 0 ? "" : ",") + id[i].value);
|
||||||
|
checkedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (checkField.checked) {
|
||||||
|
checkedIds = id.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (checkedIds.length > 0) {
|
||||||
|
if (confirm("[[#{common.delete.msg}]]")) {
|
||||||
|
document.listForm.checkedIdForDel.value = checkedIds;
|
||||||
|
document.listForm.method = 'POST';
|
||||||
|
document.listForm.action = '[[@{/mgmt/routes/group/delete.do}]]';
|
||||||
|
document.listForm.submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fnAdd.addEventListener("click", function () {
|
||||||
|
location.href = '[[@{/mgmt/routes/group/create_view.do}]]';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
|
</html>
|
||||||
@@ -36,6 +36,18 @@
|
|||||||
<div th:text="${err}" class="invalid-feedback"></div>
|
<div th:text="${err}" class="invalid-feedback"></div>
|
||||||
</th:block>
|
</th:block>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-floating mt-2">
|
||||||
|
<select class="form-select" name="group" th:value="${mockRoute.group}">
|
||||||
|
<option value="" th:selected="${#strings.isEmpty(mockRoute.group)}">선택</option>
|
||||||
|
<!-- 그룹 목록 반복 -->
|
||||||
|
<option th:each="group : ${groupList}"
|
||||||
|
th:value="${group.id}"
|
||||||
|
th:text="${group.name}"
|
||||||
|
th:selected="${mockRoute.group} == ${group.id}">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label for="group" class="form-label must" >그룹</label>
|
||||||
|
</div>
|
||||||
<div class="d-flex align-items-center mt-2">
|
<div class="d-flex align-items-center mt-2">
|
||||||
<div class="form-floating col-md-1 me-2">
|
<div class="form-floating col-md-1 me-2">
|
||||||
<select name="method" class="form-select" th:if="${mockRoute.id == null}"
|
<select name="method" class="form-select" th:if="${mockRoute.id == null}"
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<form role="form" class="row g-3" name="searchForm" th:action="@{/mgmt/routes/list_view.do}" method="get" th:object="${modelSearch}">
|
<form role="form" class="row g-3" name="searchForm" th:action="@{/mgmt/routes/list_view.do}" method="get" th:object="${modelSearch}">
|
||||||
<input name="page" type="hidden" value="1"/>
|
<input name="page" type="hidden" value="1"/>
|
||||||
|
<div class="col-auto">
|
||||||
|
<select class="form-select" name="group" th:value="${modelSearch.group}">
|
||||||
|
<option value="" th:selected="${#strings.isEmpty(modelSearch.group)}">선택</option>
|
||||||
|
|
||||||
|
<!-- 그룹 목록 반복 -->
|
||||||
|
<option th:each="group : ${groupList}"
|
||||||
|
th:value="${group.id}"
|
||||||
|
th:text="${group.name}"
|
||||||
|
th:selected="${modelSearch.group} == ${group.id}">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<input class="form-control" name="name" placeholder="이름" type="text" size="35" th:title="#{title.search}+ '' + #{input.input}"
|
<input class="form-control" name="name" placeholder="이름" type="text" size="35" th:title="#{title.search}+ '' + #{input.input}"
|
||||||
th:value="${modelSearch.name}"
|
th:value="${modelSearch.name}"
|
||||||
@@ -31,6 +43,9 @@
|
|||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<button type="button" class="btn btn-primary btn_add"><i class="fa-sharp fa-solid fa-plus"></i> [[#{button.create}]]</button><!-- 등록 -->
|
<button type="button" class="btn btn-primary btn_add"><i class="fa-sharp fa-solid fa-plus"></i> [[#{button.create}]]</button><!-- 등록 -->
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button type="button" class="btn btn-primary btn_add_group"><i class="fa-sharp fa-solid fa-plus"></i>그룹 관리</button><!-- 등록 -->
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,6 +58,7 @@
|
|||||||
<input id="csrf" type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
<input id="csrf" type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||||
<table class="table table-hover pt-table">
|
<table class="table table-hover pt-table">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
|
<col style="width: 5%;">
|
||||||
<col style="width: 5%;">
|
<col style="width: 5%;">
|
||||||
<col style="width: 5%;">
|
<col style="width: 5%;">
|
||||||
<col style="width: 10%;">
|
<col style="width: 10%;">
|
||||||
@@ -58,6 +74,7 @@
|
|||||||
<input type="checkbox" name="checkAll" class="form-check-input" onclick="fncCheckAll()" th:title="#{input.selectAll.title}">
|
<input type="checkbox" name="checkAll" class="form-check-input" onclick="fncCheckAll()" th:title="#{input.selectAll.title}">
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
<th><div class="text-center">group</div></th>
|
||||||
<th><div class="text-center">method</div></th>
|
<th><div class="text-center">method</div></th>
|
||||||
<th><div class="text-center">path</div></th>
|
<th><div class="text-center">path</div></th>
|
||||||
<th><div class="text-center">이름</div></th>
|
<th><div class="text-center">이름</div></th>
|
||||||
@@ -73,6 +90,14 @@
|
|||||||
<input name="checkId" type="hidden" th:value="${row.id}"/>
|
<input name="checkId" type="hidden" th:value="${row.id}"/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<span th:each="group : ${groupList}"
|
||||||
|
th:if="${group.id} == ${row.group}"
|
||||||
|
th:text="${group.name}">그룹 미지정</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex justify-content-center">
|
<div class="d-flex justify-content-center">
|
||||||
<span th:text="${row.method}"></span>
|
<span th:text="${row.method}"></span>
|
||||||
@@ -138,6 +163,7 @@
|
|||||||
let fnSearch = document.querySelector(".btn_search");
|
let fnSearch = document.querySelector(".btn_search");
|
||||||
let fnDelete = document.querySelector(".btn_delete");
|
let fnDelete = document.querySelector(".btn_delete");
|
||||||
let fnAdd = document.querySelector(".btn_add");
|
let fnAdd = document.querySelector(".btn_add");
|
||||||
|
let fnAddGroup = document.querySelector(".btn_add_group");
|
||||||
|
|
||||||
fnSearch.addEventListener("click", function () {
|
fnSearch.addEventListener("click", function () {
|
||||||
document.searchForm.page.value = 1;
|
document.searchForm.page.value = 1;
|
||||||
@@ -176,6 +202,10 @@
|
|||||||
fnAdd.addEventListener("click", function () {
|
fnAdd.addEventListener("click", function () {
|
||||||
location.href = '[[@{/mgmt/routes/create_view.do}]]';
|
location.href = '[[@{/mgmt/routes/create_view.do}]]';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fnAddGroup.addEventListener("click", function () {
|
||||||
|
location.href = '[[@{/mgmt/routes/group/list_view.do}]]';
|
||||||
|
});
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user