Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"getLength": true,
"getExport": true,
"isPrintLog": true,
"getUrlPath": true,
"editQuestionInstanceCtrl": true
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/epam/eighty/repository/TopicRepository.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.epam.eighty.repository;

import org.springframework.data.domain.Slice;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.stereotype.Repository;

import com.epam.eighty.domain.Topic;
Expand All @@ -10,4 +12,6 @@
@Repository("topicRepo")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's no need to mark interfaces with @repository as u have already has

<neo4j:repositories base-package="com.epam.eighty.repository" />

in your config file which is used to enabled repository support.
I'm not sure and this needs to be clarified but it's possible that repository beans is instantiated twice. Update: this's false as u scan repository package only once.
Plus, it's not a good idea to manually hardcode bean names.

public interface TopicRepository extends BaseRepository<Topic, Long> {

@Query(value = "MATCH (root:`Topic`) WHERE ID(root) = {0} return root UNION ALL MATCH (root:`Topic`)-[:`contains`*]->(topic:`Topic`) WHERE ID(topic) = {0} RETURN root", elementClass = Topic.class)
Slice<Topic> getRootTopicsForTopic(Long id);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe getParentTopicsForTopic ?

}
3 changes: 3 additions & 0 deletions src/main/java/com/epam/eighty/service/TopicService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.epam.eighty.service;

import java.util.List;
import java.util.Optional;
import java.util.Set;

Expand All @@ -16,4 +17,6 @@ public interface TopicService {
void updateTopic(Topic topic);
void deleteTopic(Long id);
Topic createTopic(Topic topic, Long id);
Long getIdOfLastNotDeletedTopic(List<Long> topicIds);
Topic getTopicWithChildsTillTopicWithId(Long id);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too complex name, let's discuss it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe getTopicWithChildrenToCurrentTopic or getRootWithSubtopicsToCurrentTopic but I'm not sure that they are suitable they are too complex and it is not clear what id param means. What are your variants?

}
30 changes: 30 additions & 0 deletions src/main/java/com/epam/eighty/service/impl/TopicServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.epam.eighty.service.impl;

import java.util.List;
import java.util.Optional;
import java.util.Set;

Expand Down Expand Up @@ -70,4 +71,33 @@ public Topic createTopic(final Topic topic, final Long id) {
return topic;
}

@Override
public Long getIdOfLastNotDeletedTopic(List<Long> topicIds) {
for(Long id: topicIds) {
Optional<Topic> topic = topicRepo.findOne(id);
if(topic.isPresent()) {
return id;
}
}
return null;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will be more beautiful and efficient to do this with stream.
It will be better return Optional instead of null.

}

@Override
public Topic getTopicWithChildsTillTopicWithId(Long id) {
Optional<Topic> root = topicRepo.findBySchemaPropertyValue("title", "root");
List<Topic> path = topicRepo.getRootTopicsForTopic(id).getContent();
root.ifPresent(r -> {
topicsFetchIfNeeded(r, path);
});
return root.get();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

U will get exception if root is empty.

}

private void topicsFetchIfNeeded(Topic topic, List<Topic> path) {
topic.getTopics().forEach(t -> {
template.fetch(t);
if(path.contains(t)) {
topicsFetchIfNeeded(t, path);
}
});
}
}
26 changes: 26 additions & 0 deletions src/main/java/com/epam/eighty/web/api/TopicController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.epam.eighty.web.api;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

import javax.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -101,6 +102,19 @@ public Topic createTopic(@ApiParam(name = "topic", required = true, value = "top
return topicService.createTopic(topic, id);
}

@ApiOperation(value = "Create topic", notes = "Create topic", httpMethod = "POST", response = Topic.class, consumes = "application/json")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "application/json question"),
@ApiResponse(code = 400, message = "Bad request"), })
@Timed
@RequestMapping(value = "/notRemoved", method = RequestMethod.POST)
@ResponseBody
@CacheEvict(value = "topic", allEntries = true)
public Long getIdOfLastNotDeletedTopic(@ApiParam(name = "topicIds", required = true, value = "topicIds") @RequestBody final List<Long> topicIds,
final HttpServletResponse response) {
return topicService.getIdOfLastNotDeletedTopic(topicIds);
}

@ApiOperation(value = "Update topic", notes = "Update topic", httpMethod = "PUT", response = Topic.class, consumes = "application/json")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "application/json question"),
Expand All @@ -115,4 +129,16 @@ public Topic updateTopic(@ApiParam(name = "topic", required = true, value = "top
return topic;
}

@ApiOperation(value = "Find path for topic by id", notes = "Get path for topic by id", httpMethod = "GET", response = Topic.class, produces = "application/json")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "application/json topic"),
@ApiResponse(code = 400, message = "Bad request"),
@ApiResponse(code = 404, message = "Not found") })
@Timed
@RequestMapping(value = "/path/{id}", method = RequestMethod.GET)
@ResponseBody
@Cacheable(value = "topic", key = "'path.' + #id")
public Topic getPath(@ApiParam(name = "topicId", required = true, value = "topic id") @PathVariable("id") final Long id) {
return topicService.getTopicWithChildsTillTopicWithId(id);
}
}
12 changes: 6 additions & 6 deletions src/main/webapp/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,18 @@ angular.module('eightyControllers', ['ui.router', 'ui.bootstrap']);
return customersFactory.getCustomers();
}

getAllQuestionsWithTag.$inject = ['$stateParams', 'crudFactory'];
function getAllQuestionsWithTag($stateParams, crudFactory) {
var questions = crudFactory.questions().allQuestionsWithTag({tagName: replaceDOT($stateParams.tagName)}).$promise;
getAllQuestionsWithTag.$inject = ['$stateParams', 'questionsFactory'];
function getAllQuestionsWithTag($stateParams, questionsFactory) {
var questions = questionsFactory.getAllQuestionsWithTag($stateParams);
questions.then(undefined, function (error) {
printLog(error);
});
return questions;
}

getAllQuestionsFromCustomer.$inject = ['$stateParams', 'crudFactory'];
function getAllQuestionsFromCustomer($stateParams, crudFactory) {
var questions = crudFactory.questions().allQuestionsFromCustomer({customerName: replaceDOT($stateParams.customerName)}).$promise;
getAllQuestionsFromCustomer.$inject = ['$stateParams', 'questionsFactory'];
function getAllQuestionsFromCustomer($stateParams, questionsFactory) {
var questions = questionsFactory.getAllQuestionsFromCustomer($stateParams);
questions.then(undefined, function (error) {
printLog(error);
});
Expand Down
6 changes: 4 additions & 2 deletions src/main/webapp/js/dataService/crud.factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@
* - `{object}` `get({Number} id)` — Request for topic with given id.
* - `{object}` `update({object} topic)` — Request for update the given topic.
*/
function topic () {
function topic() {
return $resource('topics/:id', {}, {
get: {method: 'GET', params: {id: '@id'}},
getLastNotRemoved: { method: 'POST', url: 'topics/notRemoved' },
update: { method: 'PUT', url: 'topics' },
create: { method: 'POST', params: {id: '@id'}}
create: { method: 'POST', params: {id: '@id'}},
getPath: { method: 'GET', url: 'topics/path/:id', params: {id: '@id'}}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
}

function rateUp(questionUI) {
questionsFactory.rateUp(questionUI);
questionsFactory.rateUp(questionUI, vm);
}

function editQuestion(question) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/webapp/js/questions/questions.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
}

function rateUp(questionUI) {
questionsFactory.rateUp(questionUI);
questionsFactory.rateUp(questionUI, vm);
}

function exportQuestion(question) {
Expand Down
79 changes: 73 additions & 6 deletions src/main/webapp/js/questions/questions.factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
.module('eightyFactories')
.factory('questionsFactory', questionsFactory);

questionsFactory.$inject = ['$modal', '$stateParams', '$rootScope', 'crudFactory', 'modalData', 'utility'];

function questionsFactory($modal, $stateParams, $rootScope, crudFactory, modalData, utility) {
questionsFactory.$inject = ['$document', '$modal', '$stateParams', '$rootScope', 'crudFactory', 'modalData', 'utility'];

function questionsFactory($document, $modal, $stateParams, $rootScope, crudFactory, modalData, utility) {
var publicMethods = {
checkCollapsed: checkCollapsed,
checkInSet: checkInSet,
Expand All @@ -32,7 +31,9 @@
loadTagsAndCustomersByTopic: loadTagsAndCustomersByTopic,
getTopic: getTopic,
saveQuestionChanges: saveQuestionChanges,
deleteQuestion: deleteQuestion
deleteQuestion: deleteQuestion,
getAllQuestionsWithTag: getAllQuestionsWithTag,
getAllQuestionsFromCustomer: getAllQuestionsFromCustomer
};
return publicMethods;

Expand All @@ -47,7 +48,7 @@
function checkInSet(key, obj) {
return utility.containsInSet(key, obj);
}
function rateUp(questionUI) {
function rateUp(questionUI, vm) {
if (questionUI.like === null) {
questionUI.like = 0;
}
Expand All @@ -62,9 +63,74 @@
utility.updateInSet('exportSet', question);
}
}, function(error) {
printLog(error);
if (error.status === 404) {
errorAlert('Question is not found!', $modal);
reloadPageAfterQuestionWasRemoved(vm);
}
});
}

function reloadPageAfterQuestionWasRemoved(vm) {
$rootScope.$broadcast('topTags-update');
var str_url = $document[0].URL;
var topics_url = '#/topics/';
var tags_url = '#/questionsWithTag/';
var customers_url = '#/questionsFromCustomer/';
if(str_url.search(topics_url) !== -1) {
reloadQuestionsAndTopicTagsOnTopicsPage(vm, getUrlPath(str_url, topics_url));
}
if(str_url.search(tags_url) !== -1) {
reloadQuestionsOnQuestionsWithTagPage(vm, getUrlPath(str_url, tags_url));
}
if(str_url.search(customers_url) !== -1) {
reloadQuestionsOnQuestionsFromCustomerPage(vm, getUrlPath(str_url, customers_url));
}
if(vm.questionsForExport) {
reloadQuestionsForExport(vm);
}
}

function reloadQuestionsAndTopicTagsOnTopicsPage(vm, topicId) {
$rootScope.$broadcast('topicTags-update');
$stateParams.id = topicId;
loadQuestions(vm, 0);
}
function reloadQuestionsOnQuestionsWithTagPage(vm, tagName) {
$stateParams.tagName = tagName;
getAllQuestionsWithTag($stateParams).then(function(set) {
vm.questions = set;
});
}
function reloadQuestionsOnQuestionsFromCustomerPage(vm, customer) {
$stateParams.customerName = customer;
getAllQuestionsFromCustomer($stateParams).then(function(set) {
vm.questions = set;
});
}
function reloadQuestionsForExport(vm) {
crudFactory.questions().query().$promise.then(function(allQuestions) {
for(var i = vm.questionsForExport.length - 1; i >= 0; i--) {
var question = vm.questionsForExport[i];
if(!containsInSet(allQuestions, question)) {
vm.questionsForExport.splice(i, 1);
utility.removeFromSet('exportSet', question);
} else {
var questionFromAllQuestions = allQuestions[getIndex(allQuestions, question)];
if(questionFromAllQuestions !== question) {
vm.questionsForExport[i] = allQuestions[getIndex(allQuestions, question)];
utility.updateInSet('exportSet', questionFromAllQuestions);
}
}
}
});
}
function getAllQuestionsWithTag($stateParams) {
return crudFactory.questions().allQuestionsWithTag({tagName: replaceDOT($stateParams.tagName)}).$promise;
}
function getAllQuestionsFromCustomer($stateParams) {
return crudFactory.questions().allQuestionsFromCustomer({customerName: replaceDOT($stateParams.customerName)}).$promise;
}

function editQuestion(question, vm) {
modalData.setShouldBeOpen(true);

Expand Down Expand Up @@ -140,6 +206,7 @@
if ($stateParams.id) {
crudFactory.questions().allQuestions({id: $stateParams.id, page: page, size: scrollAddOption.count, sort: scrollAddOption.sort})
.$promise.then(function (set) {
scope.questions = [];
if ((page === 0) && (set.length === 0)) {
page = -1;
scope.message = 'No questions';
Expand Down
8 changes: 5 additions & 3 deletions src/main/webapp/js/topicTree/treeNavigation.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

function activate() {
crudFactory.topic().get({id: ''}).$promise.then(function(topic) {
vm.treedata = treeNavigationFactory.getTreeTopics(topic);
vm.treedata = treeNavigationFactory.getTreeTopics(topic);
}, function(error) {
printLog(error);
});
Expand All @@ -39,13 +39,15 @@
treeNode.topics = treeNavigationFactory.getTreeTopics(topic);
vm.treeControl.expand_branch(treeNode);
}, function(error) {
printLog(error);
if (error.status === 404) {
treeNavigationFactory.reloadTopics(treeNode, vm);
}
});
}

function editTopic(node) {
modalData.setShouldBeOpen(true);
treeNavigationFactory.editTopic(node);
treeNavigationFactory.editTopic(node, vm);
}

function addTopic(node) {
Expand Down
Loading