diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/TextEntityResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/TextEntityResource.java index 9a5ffbd4a37ceca23274260106d6e94cb89ce86f..0967a34d2018521c167dee3d84e85bceb86594c5 100644 --- a/vipra-backend/src/main/java/de/vipra/rest/resource/TextEntityResource.java +++ b/vipra-backend/src/main/java/de/vipra/rest/resource/TextEntityResource.java @@ -51,7 +51,8 @@ public class TextEntityResource { @Produces(MediaType.APPLICATION_JSON) public Response getEntities(@QueryParam("topicModel") final String topicModel, @QueryParam("skip") final Integer skip, @QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("id") final String sortBy, - @QueryParam("fields") final String fields, @QueryParam("char") final String startChar, @QueryParam("contains") final String contains) { + @QueryParam("fields") final String fields, @QueryParam("char") final String startChar, @QueryParam("contains") final String contains, + @QueryParam("word") final Boolean isWord) { final ResponseWrapper<List<TextEntityFull>> res = new ResponseWrapper<>(); if (topicModel == null || topicModel.trim().isEmpty()) { @@ -82,6 +83,9 @@ public class TextEntityResource { if (contains != null && !contains.isEmpty()) query.contains("entity", contains, true); + if (isWord != null) + query.eq("isWord", isWord); + final List<TextEntityFull> entities = dbEntities.getMultiple(query); if ((skip != null && skip > 0) || (limit != null && limit > 0)) diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/WordResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/WordResource.java index 9f13b3ac7550d8c0a455e114bb48dfb675fa225a..f4c304b40dfc02e408725dc2985b8613978a379e 100644 --- a/vipra-backend/src/main/java/de/vipra/rest/resource/WordResource.java +++ b/vipra-backend/src/main/java/de/vipra/rest/resource/WordResource.java @@ -47,7 +47,8 @@ public class WordResource { @Produces(MediaType.APPLICATION_JSON) public Response getWords(@QueryParam("topicModel") final String topicModel, @QueryParam("skip") final Integer skip, @QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("id") final String sortBy, - @QueryParam("fields") final String fields, @QueryParam("char") final String startChar, @QueryParam("contains") final String contains) { + @QueryParam("fields") final String fields, @QueryParam("char") final String startChar, @QueryParam("contains") final String contains, + @QueryParam("entity") final Boolean isEntity) { final ResponseWrapper<List<WordFull>> res = new ResponseWrapper<>(); if (topicModel == null || topicModel.trim().isEmpty()) { @@ -78,6 +79,9 @@ public class WordResource { if (contains != null && !contains.isEmpty()) query.contains("word", contains, true); + if (isEntity != null) + query.eq("isEntity", isEntity); + final List<WordFull> words = dbWords.getMultiple(query); if ((skip != null && skip > 0) || (limit != null && limit > 0)) diff --git a/vipra-cmd/runcfg/CMD.launch b/vipra-cmd/runcfg/CMD.launch index b4a690b51c621da0f8688a35d60797482c2706e2..440130a4ab4849763715ad1839e89ee24512c608 100644 --- a/vipra-cmd/runcfg/CMD.launch +++ b/vipra-cmd/runcfg/CMD.launch @@ -11,7 +11,7 @@ </listAttribute> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="de.vipra.cmd.Main"/> -<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-AM"/> +<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-S test -cI /home/eike/repos/master/ma-impl/docker/data/test-1.json"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="vipra-cmd"/> <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/> diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java index 6d11d986fddcbb648a910670a795054145532c51..7daac5c01aa12ae5cbd4a43e5df2a0419ebed4ec 100644 --- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java +++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java @@ -100,6 +100,7 @@ public class ImportCommand implements Command { private Processor processor; private ArticleBuffer buffer; private Set<TextEntityFull> newTextEntities; + private Set<WordFull> wordEntities; /** * Import command to import articles into the database, do topic modeling @@ -227,10 +228,17 @@ public class ImportCommand implements Command { // replace entity surface form by resource form textEntityCount.getEntity().setEntity(newTextEntity.getEntity()); - // add entities as words if not already words - if (newTextEntity.getIsWord() && !wordCounts.contains(newTextEntity.getEntity())) { - final ArticleWord newArticleWord = new ArticleWord(newTextEntity.getEntity(), textEntityCount.getCount()); - articleWords.add(newArticleWord); + if (newTextEntity.getIsWord()) { + // mark word as entity + final WordFull wordEntity = new WordFull(newTextEntity.getEntity(), topicModel); + wordEntity.setIsEntity(true); + wordEntities.add(wordEntity); + + // add entities as words if not already words + if (!wordCounts.contains(newTextEntity.getEntity())) { + final ArticleWord newArticleWord = new ArticleWord(newTextEntity.getEntity(), textEntityCount.getCount()); + articleWords.add(newArticleWord); + } } } @@ -344,6 +352,7 @@ public class ImportCommand implements Command { throw new Exception("Topic model with name '" + modelConfig.getName() + "' not found."); topicModel = new TopicModel(topicModelFull.getId()); newTextEntities = new HashSet<>(); + wordEntities = new HashSet<>(); final Timer timer = new Timer(); timer.restart(); @@ -370,6 +379,11 @@ public class ImportCommand implements Command { } dbWords.createMultiple(newWords); + /* + * mark words as entities + */ + dbWords.updateMultiple(wordEntities, "isEntity", true); + /* * add new windows */ diff --git a/vipra-ui/app/html/articles/entities.html b/vipra-ui/app/html/articles/entities.html index 13de7b7631fd7705813f0196e5ab8e3f52428b54..2289d5769c9751408de14647cff363a101ecc627 100644 --- a/vipra-ui/app/html/articles/entities.html +++ b/vipra-ui/app/html/articles/entities.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'articles.show.entities'"> <div class="page-header no-border"> - <span class="label label-default">Article</span> + <span class="label label-default article-color">Article</span> <h1 ng-bind="::article.title"></h1> </div> <div> diff --git a/vipra-ui/app/html/articles/index.html b/vipra-ui/app/html/articles/index.html index fa42a19b59d91fbb8da3026f10b991c06b13f317..fb929327cd0615ef90f9d9a32568cd1897afc161 100644 --- a/vipra-ui/app/html/articles/index.html +++ b/vipra-ui/app/html/articles/index.html @@ -12,8 +12,7 @@ <div class="col-md-9 col-sm-12"> <div class="panel panel-default"> <div class="panel-heading clearfix"> - Found - <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database. + Found <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database </div> <table class="table table-hover table-condensed table-fixed"> <tbody> @@ -43,31 +42,33 @@ </div> <hr> <div class="form-group"> - <div class="btn-group btn-group-justified"> - <input type="text" class="form-control" ng-model="articlesIndexModels.contains" placeholder="Filter..." ng-model-options="{debounce:300}"> - <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="articlesIndexModels.contains=''" analytics-on analytics-event="Entities Filter (clear)" analytics-category="Filter actions"></span> - </div> - </div> - <div class="form-group"> - <label for="initial">Initial letter</label> - <char-selector id="initial" ng-model="articlesIndexModels.startChar"/> - </div> - <div class="form-group"> - <label>Sort by</label> + <label class="control-label">Sort by</label> <div class="input-group"> - <select class="form-control" ng-model="articlesIndexModels.sortkey"> + <sorter ng-model="articlesIndexModels.sortkey"> <option value="title">Title</option> <option value="date">Date</option> <option value="created">Added</option> <option value="topicsCount"># of topics</option> - </select> + </sorter> <span class="input-group-btn"> <sort-dir ng-model="articlesIndexModels.sortdir" /> </span> </div> </div> + <hr> + <div class="form-group"> + <label class="control-label">Filter</label> + <div class="btn-group btn-group-justified"> + <input type="text" class="form-control" ng-model="articlesIndexModels.contains" placeholder="Filter..." ng-model-options="{debounce:300}"> + <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="articlesIndexModels.contains=''" analytics-on analytics-event="Entities Filter (clear)" analytics-category="Filter actions"></span> + </div> + </div> + <div class="form-group"> + <label class="control-label" for="initial">Initial letter</label> + <char-selector id="initial" ng-model="articlesIndexModels.startChar"/> + </div> <div class="form-group"> - <label>From/to date</label> + <label class="control-label">From/to date</label> <div class="input-group date" id="fromDate" bs-datetimepicker ng-model="articlesIndexModels.fromDate"> <input type="text" class="form-control" placeholder="From date"> <span class="input-group-addon"> diff --git a/vipra-ui/app/html/articles/show.html b/vipra-ui/app/html/articles/show.html index b95e11333563c858cacb5d0facf3b9e9d0d44521..2393176fa3cc2edd414c162ca8ab8180cf58f008 100644 --- a/vipra-ui/app/html/articles/show.html +++ b/vipra-ui/app/html/articles/show.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'articles.show'"> <div class="page-header no-border"> - <span class="label label-default">Article</span> + <span class="label label-default article-color">Article</span> <h1 ng-bind="::article.title"></h1> </div> <div> diff --git a/vipra-ui/app/html/articles/words.html b/vipra-ui/app/html/articles/words.html index ccdf7b9beade0a6250cc1df34e7ff3814bad7b9e..d00a440b18e428b5987d05fcd991969aea0a5b96 100644 --- a/vipra-ui/app/html/articles/words.html +++ b/vipra-ui/app/html/articles/words.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'articles.show.words'"> <div class="page-header no-border"> - <span class="label label-default">Article</span> + <span class="label label-default article-color">Article</span> <h1 ng-bind="::article.title"></h1> </div> <div> @@ -37,7 +37,7 @@ <table class="table table-bordered table-condensed table-fixed"> <thead> <tr> - <th ng-model="articlesShowModels.wordsSort" sort-by="id">Word</th> + <th ng-model="articlesShowModels.wordsSort" sort-by="word">Word</th> <th ng-model="articlesShowModels.wordsSort" sort-by="count">Count</th> <th>Share</th> <th>Reduced share <info text="Word share applied on the processed text"/></th> @@ -46,7 +46,7 @@ <tbody> <tr ng-repeat="word in words | orderBy:articlesShowModels.wordsSort track by word.word"> <td> - <word-link word="::word" /> + <word-link label="false" word="::word" /> </td> <td ng-bind="::word.count"></td> <td ng-bind-template="{{::Vipra.toPercent(word.count/article.stats.wordCount, 2)}}%"></td> diff --git a/vipra-ui/app/html/directives/char-selector.html b/vipra-ui/app/html/directives/char-selector.html index 0b173e190aa5864855efa13ad075b1e241bf9e84..5a21e5e5e9741eacfc75643d8cd83766a4c17a9b 100644 --- a/vipra-ui/app/html/directives/char-selector.html +++ b/vipra-ui/app/html/directives/char-selector.html @@ -1,5 +1,5 @@ <div class="input-group"> - <select class="form-control" ng-model="ngModel"> + <select class="form-control" ng-model="ngModel" ng-change="charChanged()"> <option value="" analytics-on analytics-event="Char selector ()" analytics-category="Filter actions">All</option> <option value="A" analytics-on analytics-event="Char selector (A)" analytics-category="Filter actions">A</option> <option value="B" analytics-on analytics-event="Char selector (B)" analytics-category="Filter actions">B</option> diff --git a/vipra-ui/app/html/directives/entity-link.html b/vipra-ui/app/html/directives/entity-link.html index 2abd24c2f03477e60c21625142fec7cd0cba9692..fcf593f86ade17bfa14ad48fcf71e91467ea9530 100644 --- a/vipra-ui/app/html/directives/entity-link.html +++ b/vipra-ui/app/html/directives/entity-link.html @@ -1,7 +1,11 @@ <div class="link-wrapper"> <span class="menu-padding ellipsis"> - <a class="entity-link" ui-sref="entities.show({id:entity.entity})" ng-attr-title="{{::entity.entity}}"> - <span class="title" ng-bind="::entity.entity"></span> + <div class="pull-right" ng-if="::showLabel"> + <a class="label label-default word-color" ui-sref="words.show({id:id})" ng-if="entity.isWord">W</a> + <a class="label label-default entity-color" ui-sref="entities.show({id:id})">E</a> + </div> + <a class="entity-link" ui-sref="entities.show({id:id})" ng-attr-title="{{::id}}"> + <span class="title" ng-bind="::id"></span> <ng-transclude/> </a> </span> diff --git a/vipra-ui/app/html/directives/entity-menu.html b/vipra-ui/app/html/directives/entity-menu.html index 1d205f726fd44be870cb1a86b550bc802450a95c..11e89f94b4a5d1a56fc2b27d1715b478a0edc2a7 100644 --- a/vipra-ui/app/html/directives/entity-menu.html +++ b/vipra-ui/app/html/directives/entity-menu.html @@ -3,10 +3,8 @@ <i class="fa fa-caret-down"></i> </a> <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}"> - <li><a ui-sref="entities.show({id:entity.entity})">Show</a></li> - <li ng-if="entity.isWord"><a ui-sref="words.show({id:entity.entity})">Show word</a></li> - <li><a ui-sref="entities.show.articles({id:entity.entity})">Articles</a></li> - <li role="separator" class="divider"></li> - <li><a ng-href="{{entity.url}}" target="_blank"><span class="dbpedia-logo"></span> DBPedia</a></li> + <li><a ui-sref="entities.show({id:id})">Show</a></li> + <li ng-if="entity.isWord"><a ui-sref="words.show({id:id})">Show word</a></li> + <li><a ui-sref="entities.show.articles({id:id})">Articles</a></li> </ul> </div> \ No newline at end of file diff --git a/vipra-ui/app/html/directives/sort-dir.html b/vipra-ui/app/html/directives/sort-dir.html index 8ef9475570ad86f0896e9667e309b128bcff5f22..ff291eb29e73bb138ba2aca9033e882f526fb49d 100644 --- a/vipra-ui/app/html/directives/sort-dir.html +++ b/vipra-ui/app/html/directives/sort-dir.html @@ -1,3 +1,3 @@ <button class="btn btn-default" type="button" tabindex="0" ng-click="ngModel=!ngModel; $event.stopPropagation()" analytics-on analytics-event="Sort direction" analytics-category="Filter actions"> - <i class="fa" ng-class="{'fa-sort-amount-desc':ngModel,'fa-sort-amount-asc':!ngModel}"></i> + <i class="fa" ng-class="{'fa-sort-amount-desc':!ngModel,'fa-sort-amount-asc':ngModel}"></i> </button> \ No newline at end of file diff --git a/vipra-ui/app/html/directives/sorter.html b/vipra-ui/app/html/directives/sorter.html new file mode 100644 index 0000000000000000000000000000000000000000..a42e60394ceabfe7e7bb2c88e93b59b7933661d7 --- /dev/null +++ b/vipra-ui/app/html/directives/sorter.html @@ -0,0 +1 @@ +<select class="form-control" ng-transclude></select> \ No newline at end of file diff --git a/vipra-ui/app/html/directives/word-link.html b/vipra-ui/app/html/directives/word-link.html index ef93cf21f8d0ab6ff5355603a29f648b711bfc4e..35aae914b3a42c5992a0129b974bfa02745ded70 100644 --- a/vipra-ui/app/html/directives/word-link.html +++ b/vipra-ui/app/html/directives/word-link.html @@ -1,6 +1,10 @@ <div class="link-wrapper"> <span class="ellipsis" ng-class="{'menu-padding':showMenu}"> - <a class="title" ui-sref="words.show({id: id})" ng-bind="id" ng-attr-title="{{::id}}"></a> + <div class="pull-right" ng-if="::showLabel"> + <a class="label label-default entity-color" ui-sref="entities.show({id:id})" ng-if="word.isEntity">E</a> + <a class="label label-default word-color" ui-sref="words.show({id:id})">W</a> + </div> + <a class="title" ui-sref="words.show({id:id})" ng-bind="id" ng-attr-title="{{::id}}"></a> </span> <word-menu class="menu-button" word="word" ng-if="::showMenu" /> </div> \ No newline at end of file diff --git a/vipra-ui/app/html/directives/word-menu.html b/vipra-ui/app/html/directives/word-menu.html index d6f17117fae0b682dbaf8082228ee55225974b1e..cab3e5aae755297a5de6f80047e1c4c02433abf6 100644 --- a/vipra-ui/app/html/directives/word-menu.html +++ b/vipra-ui/app/html/directives/word-menu.html @@ -4,6 +4,7 @@ </a> <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}"> <li><a ui-sref="words.show({id:id})">Show</a></li> + <li ng-if="word.isEntity"><a ui-sref="entities.show({id:id})">Show entity</a></li> <li><a ui-sref="words.show.topics({id:id})">Topics</a></li> <li><a ui-sref="words.show.articles({id:id})">Articles</a></li> </ul> diff --git a/vipra-ui/app/html/entities/articles.html b/vipra-ui/app/html/entities/articles.html index 65ae82528392b015dbd3acb3968d838a13bfaea1..9d0ea6034ee73d50f582923110b54312c7a96b73 100644 --- a/vipra-ui/app/html/entities/articles.html +++ b/vipra-ui/app/html/entities/articles.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'entities.show.articles'"> <div class="page-header no-border"> - <span class="label label-default">Entity</span> + <span class="label label-default entity-color">Entity</span> <a class="label label-default" ng-if="entity.isWord" ui-sref="words.show({id:id})">Word</a> <h1 ng-bind="::id"></h1> </div> diff --git a/vipra-ui/app/html/entities/index.html b/vipra-ui/app/html/entities/index.html index a8d5d2ab0f78670c896d200f884f9f0c076a5330..b7bb112bc9a9d6b1dc471d68960db9ac48cd5833 100644 --- a/vipra-ui/app/html/entities/index.html +++ b/vipra-ui/app/html/entities/index.html @@ -43,24 +43,41 @@ </div> <hr> <div class="form-group"> + <label class="control-label">Sort by</label> + <div class="input-group"> + <sorter ng-model="entitiesIndexModels.sortkey"> + <option value="entity">Entity</option> + </sorter> + <span class="input-group-btn"> + <sort-dir ng-model="entitiesIndexModels.sortdir" /> + </span> + </div> + </div> + <hr> + <div class="form-group"> + <label class="control-label">Filter</label> <div class="btn-group btn-group-justified"> <input type="text" class="form-control" ng-model="entitiesIndexModels.contains" placeholder="Filter..." ng-model-options="{debounce:300}"> <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="entitiesIndexModels.contains=''" analytics-on analytics-event="Entities Filter (clear)" analytics-category="Filter actions"></span> </div> </div> <div class="form-group"> - <label for="initial">Initial letter</label> + <label class="control-label" for="initial">Initial letter</label> <char-selector id="initial" ng-model="entitiesIndexModels.startChar"/> </div> <div class="form-group"> - <label>Sort by</label> - <div class="input-group"> - <select class="form-control" ng-model="entitiesIndexModels.sortkey"> - <option value="id">Entity</option> - </select> - <span class="input-group-btn"> - <sort-dir ng-model="entitiesIndexModels.sortdir" /> - </span> + <label class="control-label">Type</label> + <div class="radio"> + <input type="radio" name="typeFilter" value="1" id="typeAll" ng-model="entitiesIndexModels.type" checked> + <label for="typeAll">All</label> + </div> + <div class="radio"> + <input type="radio" name="typeFilter" value="2" id="typeWords" ng-model="entitiesIndexModels.type"> + <label for="typeWords"><span class="label label-default entity-color">E</span></label> + </div> + <div class="radio"> + <input type="radio" name="typeFilter" value="3" id="typeWordsEntities" ng-model="entitiesIndexModels.type"> + <label for="typeWordsEntities"><span class="label label-default entity-color">E</span> <span class="label label-default word-color">W</span></label> </div> </div> </div> diff --git a/vipra-ui/app/html/entities/show.html b/vipra-ui/app/html/entities/show.html index 2dfffa79322afe2efe4be09c3a5d7e83b7ecd067..c9aa47c3b698b97c5a1a7be59a4804adaf7a22e9 100644 --- a/vipra-ui/app/html/entities/show.html +++ b/vipra-ui/app/html/entities/show.html @@ -1,8 +1,8 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'entities.show'"> <div class="page-header no-border"> - <span class="label label-default">Entity</span> - <a class="label label-default" ng-if="entity.isWord" ui-sref="words.show({id:entity.entity})">Word</a> + <span class="label label-default entity-color">Entity</span> + <a class="label label-default word-color" ng-if="entity.isWord" ui-sref="words.show({id:entity.entity})">Word</a> <h1 ng-bind="::entity.entity"></h1> </div> <div> @@ -38,7 +38,7 @@ <th class="infocol">Word</th> <td> <span ng-bind-template="{{ entity.isWord ? 'Yes' : 'No' }}"></span> - <word-link word="::entity.entity" ng-if="entity.isWord" /> + <word-link class="inline-link" word="::entity.entity" label="false" ng-if="entity.isWord" /> </td> </tr> <tr> diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html index 87657d31358c6443908702998f110b788b449388..621a5d41294f179b201c8b1df761920d64a98f0b 100644 --- a/vipra-ui/app/html/explorer.html +++ b/vipra-ui/app/html/explorer.html @@ -111,7 +111,6 @@ <div class="topbar"> <small>Sequence:</small> <sequence-dropdown ng-model="explorerModels.activeSequence" sequences="explorerModels.activeTopic.sequences"></sequence-dropdown> - <button class="btn btn-sm btn-default" ng-click="clearSequence()" ng-disabled="!explorerModels.activeSequence" analytics-on analytics-event="Explorer Sequence (clear)" analytics-category="Filter actions">Clear</button> </div> <table class="table table-bordered table-condensed table-fixed table-hover"> <thead> diff --git a/vipra-ui/app/html/topics/articles.html b/vipra-ui/app/html/topics/articles.html index a5d41b22e23d327d7abf1df984760f38343423aa..dc41d34d77de4fad16b640b14f3ab546f40a2482 100644 --- a/vipra-ui/app/html/topics/articles.html +++ b/vipra-ui/app/html/topics/articles.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'topics.show.articles'"> <div class="page-header no-border"> - <span class="label label-default">Topic</span> + <span class="label label-default topic-color">Topic</span> <h1 ng-bind="topic.name"></h1> </div> <div> diff --git a/vipra-ui/app/html/topics/index.html b/vipra-ui/app/html/topics/index.html index 10412713aa45ba1f7b1a8d6c4717964c9c9171c3..8c9025b57515d175f858e42fc1c8e644564387a4 100644 --- a/vipra-ui/app/html/topics/index.html +++ b/vipra-ui/app/html/topics/index.html @@ -43,28 +43,30 @@ </div> <hr> <div class="form-group"> - <div class="btn-group btn-group-justified"> - <input type="text" class="form-control" ng-model="topicsIndexModels.contains" placeholder="Filter..." ng-model-options="{debounce:300}"> - <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="topicsIndexModels.contains=''" analytics-on analytics-event="Entities Filter (clear)" analytics-category="Filter actions"></span> - </div> - </div> - <div class="form-group"> - <label for="initial">Initial letter</label> - <char-selector id="initial" ng-model="topicsIndexModels.startChar"/> - </div> - <div class="form-group"> - <label>Sort by</label> + <label class="control-label">Sort by</label> <div class="input-group"> - <select class="form-control" ng-model="topicsIndexModels.sortkey"> + <sorter ng-model="topicsIndexModels.sortkey"> <option value="name">Name</option> <option value="created">Added</option> <option value="articlesCount"># of articles</option> - </select> + </sorter> <span class="input-group-btn"> <sort-dir ng-model="topicsIndexModels.sortdir" /> </span> </div> </div> + <hr> + <div class="form-group"> + <label class="control-label">Filter</label> + <div class="btn-group btn-group-justified"> + <input type="text" class="form-control" ng-model="topicsIndexModels.contains" placeholder="Filter..." ng-model-options="{debounce:300}"> + <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="topicsIndexModels.contains=''" analytics-on analytics-event="Entities Filter (clear)" analytics-category="Filter actions"></span> + </div> + </div> + <div class="form-group"> + <label class="control-label" for="initial">Initial letter</label> + <char-selector id="initial" ng-model="topicsIndexModels.startChar"/> + </div> </div> </div> </div> diff --git a/vipra-ui/app/html/topics/sequences.html b/vipra-ui/app/html/topics/sequences.html index 38c772fbe728a0a9b3bbecff9bfc65df10d01ac8..323625964f8b92ac99ddf311ec413304862ef2af 100644 --- a/vipra-ui/app/html/topics/sequences.html +++ b/vipra-ui/app/html/topics/sequences.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'topics.show.sequences'"> <div class="page-header no-border"> - <span class="label label-default">Topic</span> + <span class="label label-default topic-color">Topic</span> <h1 ng-bind="topic.name"></h1> </div> <div> @@ -45,7 +45,7 @@ <tbody> <tr class="compare-row" ng-repeat="word in sequence.words | orderBy:topicsShowModels.seqSortWords track by word.word" ng-attr-word="{{::word.word}}"> <td> - <word-link word="::word" /> + <word-link label="false" word="::word" /> </td> <td ng-bind="word.probability.toFixed(4)"></td> </tr> @@ -93,7 +93,7 @@ <tbody> <tr class="compare-row" ng-repeat="word in sequenceCompare.words | orderBy:topicsShowModels.seqSortWords track by word.word" ng-attr-word="{{::word.word}}"> <td> - <word-link word="::word" /> + <word-link label="false" word="::word" /> </td> <td ng-bind="word.probability.toFixed(4)"></td> </tr> diff --git a/vipra-ui/app/html/topics/show.html b/vipra-ui/app/html/topics/show.html index 515c53108ac04b80b2e5b0c43e8990288447645d..e4bafb68d42cb8b7cb5bf7ebba94be2c2f5ea38c 100644 --- a/vipra-ui/app/html/topics/show.html +++ b/vipra-ui/app/html/topics/show.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container topic-show" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'topics.show'"> <div class="page-header no-border"> - <span class="label label-default">Topic</span> + <span class="label label-default topic-color">Topic</span> <h1> <div ng-bind="topic.name" ng-hide="isRename"></div> <div class="input-group input-group-lg" ng-show="isRename" ng-cloak> diff --git a/vipra-ui/app/html/words/articles.html b/vipra-ui/app/html/words/articles.html index 17b8e78a7c895d4ee329366d122a4ab2a218f3bc..15a238283b30559030f9bc71ce245c88f90dc732 100644 --- a/vipra-ui/app/html/words/articles.html +++ b/vipra-ui/app/html/words/articles.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'words.show.articles'"> <div class="page-header no-border"> - <span class="label label-default">Word</span> + <span class="label label-default word-color">Word</span> <h1 ng-bind="::word"></h1> </div> <div> diff --git a/vipra-ui/app/html/words/index.html b/vipra-ui/app/html/words/index.html index 13f25ab27306d835f5c979e8661ad116ff488ae0..e32d77fb568a56ff7d29f3084466381f7e76aba5 100644 --- a/vipra-ui/app/html/words/index.html +++ b/vipra-ui/app/html/words/index.html @@ -43,24 +43,41 @@ </div> <hr> <div class="form-group"> + <label class="control-label">Sort by</label> + <div class="input-group"> + <sorter ng-model="wordsIndexModels.sortkey"> + <option value="word">Word</option> + </sorter> + <span class="input-group-btn"> + <sort-dir ng-model="wordsIndexModels.sortdir" /> + </span> + </div> + </div> + <hr> + <div class="form-group"> + <label class="control-label">Filter</label> <div class="btn-group btn-group-justified"> <input type="text" class="form-control" ng-model="wordsIndexModels.contains" placeholder="Filter..." ng-model-options="{debounce:300}"> <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="wordsIndexModels.contains=''" analytics-on analytics-event="Entities Filter (clear)" analytics-category="Filter actions"></span> </div> </div> <div class="form-group"> - <label for="initial">Initial letter</label> + <label class="control-label" for="initial">Initial letter</label> <char-selector id="initial" ng-model="wordsIndexModels.startChar"/> </div> <div class="form-group"> - <label>Sort by</label> - <div class="input-group"> - <select class="form-control" ng-model="wordsIndexModels.sortkey"> - <option value="id">Word</option> - </select> - <span class="input-group-btn"> - <sort-dir ng-model="wordsIndexModels.sortdir" /> - </span> + <label class="control-label">Type</label> + <div class="radio"> + <input type="radio" name="typeFilter" value="1" id="typeAll" ng-model="wordsIndexModels.type" checked> + <label for="typeAll">All</label> + </div> + <div class="radio"> + <input type="radio" name="typeFilter" value="2" id="typeWords" ng-model="wordsIndexModels.type"> + <label for="typeWords"><span class="label label-default word-color">W</span></label> + </div> + <div class="radio"> + <input type="radio" name="typeFilter" value="3" id="typeWordsEntities" ng-model="wordsIndexModels.type"> + <label for="typeWordsEntities"><span class="label label-default word-color">W</span> <span class="label label-default entity-color">E</span></label> </div> </div> </div> diff --git a/vipra-ui/app/html/words/show.html b/vipra-ui/app/html/words/show.html index 413315ed7a5234ce5b93089e2b82445f47da99c1..2dce224827df2cd4409fbf42e21245555542fd5d 100644 --- a/vipra-ui/app/html/words/show.html +++ b/vipra-ui/app/html/words/show.html @@ -1,7 +1,8 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'words.show'"> <div class="page-header no-border"> - <span class="label label-default">Word</span> + <span class="label label-default word-color">Word</span> + <a class="label label-default entity-color" ng-if="word.isEntity" ui-sref="entities.show({id:word.word})">Entity</a> <h1 ng-bind="::word.word"></h1> </div> <div> @@ -29,6 +30,13 @@ <th class="infocol">Word</th> <td ng-bind="::word.word"></td> </tr> + <tr> + <th class="infocol">Entity</th> + <td> + <span ng-bind-template="{{ word.isEntity ? 'Yes' : 'No' }}"></span> + <entity-link class="inline-link" entity="::word.word" label="false" ng-if="word.isEntity" /> + </td> + </tr> </tbody> </table> </div> diff --git a/vipra-ui/app/html/words/topics.html b/vipra-ui/app/html/words/topics.html index 96c0fa297a47c8ac4ad01349681881345b5fb694..fdc80f88c2827ef69cdf6419fa859ff1c5a7f6bd 100644 --- a/vipra-ui/app/html/words/topics.html +++ b/vipra-ui/app/html/words/topics.html @@ -1,7 +1,7 @@ <div ng-cloak ui-view></div> <div class="container" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'words.show.topics'"> <div class="page-header no-border"> - <span class="label label-default">Word</span> + <span class="label label-default word-color">Word</span> <h1 ng-bind="::word"></h1> </div> <div> diff --git a/vipra-ui/app/img/dbpedia-logo.svg b/vipra-ui/app/img/dbpedia-logo.svg deleted file mode 100644 index 8d171f09becf65b836a7c46855dbb4483a1ad7b4..0000000000000000000000000000000000000000 --- a/vipra-ui/app/img/dbpedia-logo.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="svg3718" viewBox="0 0 130.413 96.786428"><defs id="defs3720"><radialGradient gradientUnits="userSpaceOnUse" r="55.666401" cy="59.631302" cx="131.353" id="XMLID_18_"><stop id="stop130" offset="0" stop-color="#FFD528"/><stop id="stop132" offset="0.222" stop-color="#FFD227"/><stop id="stop134" offset="0.4435" stop-color="#FFC925"/><stop id="stop136" offset="0.6647" stop-color="#FDBB21"/><stop id="stop138" offset="0.8846" stop-color="#FAA61D"/><stop id="stop140" offset="1" stop-color="#F8991D"/></radialGradient><radialGradient gradientUnits="userSpaceOnUse" r="63.037201" cy="61.586399" cx="130.28909" id="XMLID_17_"><stop id="stop101" offset="0" stop-color="#6D8896"/><stop id="stop103" offset="0.0435" stop-color="#4B7487"/><stop id="stop105" offset="0.0933" stop-color="#286379"/><stop id="stop107" offset="0.1494" stop-color="#00556C"/><stop id="stop109" offset="0.2114" stop-color="#004962"/><stop id="stop111" offset="0.2815" stop-color="#004059"/><stop id="stop113" offset="0.3633" stop-color="#003951"/><stop id="stop115" offset="0.4644" stop-color="#00344C"/><stop id="stop117" offset="0.6062" stop-color="#003149"/><stop id="stop119" offset="1" stop-color="#003048"/></radialGradient><radialGradient xlink:href="#XMLID_18_" id="radialGradient3700" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3702" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3704" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3706" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3708" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3710" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3712" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3714" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/><radialGradient xlink:href="#XMLID_18_" id="radialGradient3716" gradientUnits="userSpaceOnUse" cx="131.353" cy="59.631302" r="55.666401"/></defs><metadata id="metadata3723"/><g transform="translate(-2.661465,-3.636792)" id="layer1"><g id="g94" transform="translate(-63.989535,3.637222)"><path id="path96" d="m184.007 65.5c-1.928 0.029-4.055-0.01-6.305-0.049C163.736 65.202 143.662 64.867 131.859 80.32 120.055 64.867 99.982 65.203 86.014 65.451c-2.25 0.039-4.376 0.078-6.303 0.049-0.462-0.005-4.855 0.136-13.06 0.418 0 0 0.556 10.304 7.805 10.304 2.603 0 4.485-0.061 5.18-0.066 2.023 0.027 4.23-0.012 6.567-0.052 19.06-0.34 34.179 0.724 40.959 17.364l1.352 3.318 3.104 0 0.476 0 3.106 0 1.353-3.318c6.779-16.64 21.897-17.705 40.958-17.364 2.338 0.041 4.545 0.08 6.568 0.052 0.693 0.005 2.577 0.066 5.179 0.066 7.251 0 7.806-10.304 7.806-10.304-8.203-0.282-12.597-0.422-13.057-0.418z" fill="#004563"/></g><g id="g98" transform="translate(-63.989535,3.637222)"><radialGradient gradientUnits="userSpaceOnUse" r="63.037201" cy="61.586399" cx="130.28909" id="radialGradient3651"><stop id="stop3653" offset="0" stop-color="#6D8896"/><stop id="stop3655" offset="0.0435" stop-color="#4B7487"/><stop id="stop3657" offset="0.0933" stop-color="#286379"/><stop id="stop3659" offset="0.1494" stop-color="#00556C"/><stop id="stop3661" offset="0.2114" stop-color="#004962"/><stop id="stop3663" offset="0.2815" stop-color="#004059"/><stop id="stop3665" offset="0.3633" stop-color="#003951"/><stop id="stop3667" offset="0.4644" stop-color="#00344C"/><stop id="stop3669" offset="0.6062" stop-color="#003149"/><stop id="stop3671" offset="1" stop-color="#003048"/></radialGradient><path id="path121" d="m137.327 1.135 0 0c-2.923 1.367-5.142 3.79-6.243 6.822-0.487 1.347-0.73 2.741-0.73 4.132 0 1.746 0.382 3.487 1.146 5.117 1.781 3.813 5.409 6.26 9.504 6.761 0.106 1.142 0.227 2.284 0.227 3.441 0 0.553-0.041 1.108-0.064 1.663-0.494 0.127-1.016 0.134-1.482 0.352-2.007 0.936-3.525 2.597-4.28 4.677-0.335 0.922-0.501 1.878-0.501 2.831 0 1.198 0.264 2.391 0.785 3.508 0.48 1.023 1.215 1.864 2.054 2.605-1.188 2.629-2.685 5.213-4.495 7.717-0.17-0.039-0.337-0.076-0.51-0.104-0.546-3.015-1.326-5.929-2.355-8.693 0.611-1.083 1.019-2.25 1.019-3.462 0-1.022-0.22-2.049-0.671-3.015-1.11-2.374-3.376-3.848-5.931-4.045-2.954-4.181-6.559-7.778-10.724-10.754 0.114-0.599 0.311-1.194 0.311-1.79 0-3.917-2.425-7.612-6.304-9.027-4.965-1.802-10.471 0.773-12.274 5.736-0.873 2.406-0.758 5.007 0.325 7.325 1.083 2.318 3.005 4.074 5.411 4.947 2.871 1.041 5.989 0.458 8.492-1.206 3.171 2.25 5.937 4.973 8.266 8.116-0.728 1.152-1.239 2.411-1.239 3.753 0 1.019 0.221 2.047 0.672 3.017 1.162 2.48 3.579 3.991 6.215 4.089 0.704 2.128 1.263 4.369 1.655 6.709-0.221 0.171-0.45 0.333-0.653 0.524-3.313-2.269-6.775-4.13-10.358-5.501-0.126-0.428-0.254-0.866-0.254-0.866-0.814-1.739-2.254-3.056-4.058-3.709-1.8-0.651-3.746-0.562-5.479 0.25-0.769 0.357-1.421 0.894-2.017 1.508-3.976-0.389-7.964-0.2-11.908 0.452-2.589-3.858-7.619-5.437-11.945-3.411-4.791 2.242-6.865 7.961-4.625 12.749 2.243 4.789 7.962 6.861 12.749 4.625 2.829-1.323 4.69-3.887 5.262-6.873 2.897-0.482 5.836-0.668 8.795-0.445 0.093 0.301 0.097 0.634 0.23 0.92 1.675 3.583 5.949 5.137 9.529 3.465 0.778-0.366 1.44-0.89 2.031-1.491 3.123 1.308 6.182 3.037 9.123 5.205 0.017 1.311 0.299 2.604 0.859 3.788 1.04 2.234 2.896 3.934 5.222 4.778 2.328 0.846 4.844 0.734 7.086-0.314 2.479-1.159 4.206-3.33 4.926-5.916 5.223-0.753 10.094-2.186 14.519-4.296 2.022 1.218 4.49 1.486 6.673 0.465 2.572-1.205 4.115-3.771 4.115-6.487 0-0.326-0.113-0.656-0.159-0.986 2.217-1.971 4.24-4.171 6.056-6.563 2.378 0.585 4.858 0.482 7.111-0.574 2.606-1.22 4.579-3.381 5.557-6.081 2.025-5.579-0.866-11.765-6.449-13.798-5.58-2.019-11.771 0.872-13.802 6.45-0.432 1.193-0.642 2.428-0.642 3.655 0 2.296 0.765 4.537 2.149 6.408-1.337 1.731-2.826 3.35-4.466 4.834-1.793-0.684-3.767-0.68-5.541 0.152-2.42 1.128-3.926 3.518-4.061 6.118-3.604 1.65-7.58 2.787-11.853 3.415 2.273-3.198 4.152-6.516 5.563-9.915 0.61-0.128 1.243-0.186 1.809-0.45 2.007-0.937 3.527-2.601 4.282-4.683 0.335-0.922 0.501-1.876 0.501-2.829 0-1.198-0.263-2.389-0.785-3.506-0.542-1.159-1.403-2.093-2.397-2.885 0.07-1.032 0.141-2.066 0.141-3.104 0-1.579-0.154-3.155-0.316-4.729 2.639-1.406 4.666-3.668 5.691-6.499 0.489-1.345 0.731-2.738 0.731-4.126 0-1.747-0.383-3.486-1.145-5.113-2.824-6.036-10.035-8.654-16.076-5.833z" fill="url(#XMLID_17_)"/></g><g id="g123" transform="translate(-63.989535,3.637222)"><g id="g125"><g id="g127"><radialGradient gradientUnits="userSpaceOnUse" r="55.666401" cy="59.631302" cx="131.353" id="radialGradient3677"><stop id="stop3679" offset="0" stop-color="#FFD528"/><stop id="stop3681" offset="0.222" stop-color="#FFD227"/><stop id="stop3683" offset="0.4435" stop-color="#FFC925"/><stop id="stop3685" offset="0.6647" stop-color="#FDBB21"/><stop id="stop3687" offset="0.8846" stop-color="#FAA61D"/><stop id="stop3689" offset="1" stop-color="#F8991D"/></radialGradient><path id="path142" d="m128.544 38.833c0.172-2.384-1.622-4.455-4.006-4.626-2.385-0.171-4.454 1.623-4.625 4.007-0.172 2.384 1.623 4.455 4.011 4.624 2.379 0.173 4.45-1.621 4.62-4.005z" fill="url(#radialGradient3700)"/><circle id="circle144" r="6.6900001" cy="59.631001" cx="131.353" fill="url(#radialGradient3702)"/><circle id="circle146" r="6.493" cy="50.263" cx="82.981003" fill="url(#radialGradient3704)"/><path id="path148" d="m111.45 19.487c0.257-3.577-2.437-6.684-6.014-6.941-3.575-0.253-6.682 2.435-6.937 6.012-0.257 3.577 2.433 6.685 6.014 6.941 3.574 0.256 6.68-2.436 6.937-6.012z" fill="url(#radialGradient3706)"/><path id="path150" d="m108.147 45.254c-2.372-0.171-4.433 1.612-4.605 3.986-0.168 2.372 1.614 4.433 3.989 4.604 2.372 0.169 4.434-1.616 4.605-3.988 0.167-2.372-1.616-4.434-3.989-4.602z" fill="url(#radialGradient3708)"/><path id="path152" d="m174.369 26.85c-3.894-0.279-7.277 2.651-7.555 6.546-0.279 3.895 2.651 7.277 6.544 7.557 3.897 0.281 7.277-2.651 7.559-6.546 0.277-3.893-2.653-7.278-6.548-7.557z" fill="url(#radialGradient3710)"/><circle id="circle154" r="4.3270001" cy="51.766998" cx="158.276" fill="url(#radialGradient3712)"/><circle id="circle156" r="5.2259998" cy="36.931999" cx="143.19099" fill="url(#radialGradient3714)"/><path id="path158" d="m143.05 3.719c-4.624-0.333-8.638 3.146-8.971 7.768-0.328 4.625 3.147 8.64 7.77 8.971 4.626 0.33 8.638-3.149 8.97-7.771 0.328-4.623-3.146-8.638-7.769-8.968z" fill="url(#radialGradient3716)"/></g></g></g></g></svg> \ No newline at end of file diff --git a/vipra-ui/app/js/app.js b/vipra-ui/app/js/app.js index cadb228563fc63c3a7854eb35f6be0c3c484b5e5..22a7d6db21dff71f4923950f3f04358e1fff3fb2 100644 --- a/vipra-ui/app/js/app.js +++ b/vipra-ui/app/js/app.js @@ -31,7 +31,7 @@ // states $stateProvider.state('index', { - url: '/?q', + url: '/', templateUrl: 'html/index.html', controller: 'IndexController', reloadOnSearch: false @@ -58,7 +58,7 @@ // states: articles $stateProvider.state('articles', { - url: '/articles?p', + url: '/articles', templateUrl: 'html/articles/index.html', controller: 'ArticlesIndexController', reloadOnSearch: false @@ -85,7 +85,7 @@ // states: topics $stateProvider.state('topics', { - url: '/topics?p', + url: '/topics', templateUrl: 'html/topics/index.html', controller: 'TopicsIndexController', reloadOnSearch: false @@ -106,15 +106,17 @@ $stateProvider.state('topics.show.articles', { url: '/articles', templateUrl: 'html/topics/articles.html', - controller: 'TopicsArticlesController' + controller: 'TopicsArticlesController', + reloadOnSearch: false }); // states: words $stateProvider.state('words', { - url: '/words?p', + url: '/words', templateUrl: 'html/words/index.html', - controller: 'WordsIndexController' + controller: 'WordsIndexController', + reloadOnSearch: false }); $stateProvider.state('words.show', { @@ -138,9 +140,10 @@ // states: entities $stateProvider.state('entities', { - url: '/entities?p', + url: '/entities', templateUrl: 'html/entities/index.html', - controller: 'EntitiesIndexController' + controller: 'EntitiesIndexController', + reloadOnSearch: false }); $stateProvider.state('entities.show', { @@ -152,7 +155,8 @@ $stateProvider.state('entities.show.articles', { url: '/articles', templateUrl: 'html/entities/articles.html', - controller: 'EntitiesArticlesController' + controller: 'EntitiesArticlesController', + reloadOnSearch: false }); // states: slides diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js index 8b86823fe34add75ba9a8a784522eadafe1e9a92..f14631f66cf28b8c2462ee70eee00f7c01430f9b 100644 --- a/vipra-ui/app/js/controllers.js +++ b/vipra-ui/app/js/controllers.js @@ -1074,13 +1074,14 @@ }; $scope.clearSequence = function() { - if(!$scope.explorerModels.activeSequence) return; - delete $scope.explorerModels.activeSequence; delete $scope.articles; - var selectedPoints = $('#topicRelChart').highcharts().getSelectedPoints(); - for(var i = 0; i < selectedPoints.length; i++) { - selectedPoints[i].select(false); + var hc = $('#topicRelChart').highcharts(); + if(hc) { + var selectedPoints = hc.getSelectedPoints(); + for(var i = 0; i < selectedPoints.length; i++) { + selectedPoints[i].select(false); + } } }; @@ -1130,7 +1131,10 @@ }); $scope.$watch('explorerModels.activeTopic', function() { - if(!$scope.explorerModels.activeTopic) return; + if(!$scope.explorerModels.activeTopic) { + $scope.clearSequence(); + return; + } $('.topic').removeClass('active-topic'); $('[data-id="' + $scope.explorerModels.activeTopic.id + '"]').addClass('active-topic'); @@ -1165,7 +1169,7 @@ sortkey: 'date', sortdir: true, page: 1, - limit: 100 + limit: 50 }; $scope.reloadArticles = function() { @@ -1394,7 +1398,7 @@ sortkey: 'name', sortdir: true, page: 1, - limit: 100 + limit: 50 }; $scope.reloadTopics = function() { @@ -1620,7 +1624,7 @@ sortkey: 'title', sortdir: true, page: 1, - limit: 100 + limit: 50 }; $scope.$watchGroup(['topicsArticlesModels.page', 'topicsArticlesModels.sortkey', 'topicsArticlesModels.sortdir'], function() { @@ -1654,21 +1658,29 @@ $scope.checkTopicModel('entities', function() { $scope.entitiesIndexModels = { - sortkey: 'id', + sortkey: 'entity', sortdir: true, + type: 1, page: 1, - limit: 100 + limit: 50 }; $scope.reloadEntities = function() { $scope.loadingEntities = true; + + var words = null; + if(parseInt($scope.entitiesIndexModels.type, 10) !== 1) + words = parseInt($scope.entitiesIndexModels.type, 10) === 3; + EntityFactory.query({ topicModel: $scope.rootModels.topicModel.id, skip: ($scope.entitiesIndexModels.page - 1) * $scope.entitiesIndexModels.limit, limit: $scope.entitiesIndexModels.limit, sort: ($scope.entitiesIndexModels.sortdir ? '' : '-') + $scope.entitiesIndexModels.sortkey, char: $scope.entitiesIndexModels.startChar, - contains: $scope.entitiesIndexModels.contains + contains: $scope.entitiesIndexModels.contains, + word: words, + fields: 'id,entity,isWord' }, function(data, headers) { $scope.entities = data; $scope.entitiesTotal = headers("V-Total"); @@ -1679,7 +1691,7 @@ }); }; - $scope.$watchGroup(['entitiesIndexModels.page', 'entitiesIndexModels.sortkey', 'entitiesIndexModels.sortdir'], function() { + $scope.$watchGroup(['entitiesIndexModels.page', 'entitiesIndexModels.sortkey', 'entitiesIndexModels.sortdir', 'entitiesIndexModels.type'], function() { $scope.reloadEntities(); }); @@ -1731,7 +1743,7 @@ sortkey: 'date', sortdir: true, page: 1, - limit: 100 + limit: 50 }; $scope.$watchGroup(['entitiesArticlesModels.page', 'entitiesArticlesModels.sortkey', 'entitiesArticlesModels.sortdir'], function() { @@ -1768,21 +1780,29 @@ $scope.checkTopicModel('words', function() { $scope.wordsIndexModels = { - sortkey: 'id', + sortkey: 'word', sortdir: true, + type: 1, page: 1, - limit: 100 + limit: 50 }; $scope.reloadWords = function() { $scope.loadingWords = true; + + var entities = null; + if(parseInt($scope.wordsIndexModels.type, 10) !== 1) + entities = parseInt($scope.wordsIndexModels.type, 10) === 3; + WordFactory.query({ topicModel: $scope.rootModels.topicModel.id, skip: ($scope.wordsIndexModels.page - 1) * $scope.wordsIndexModels.limit, limit: $scope.wordsIndexModels.limit, sort: ($scope.wordsIndexModels.sortdir ? '' : '-') + $scope.wordsIndexModels.sortkey, char: $scope.wordsIndexModels.startChar, - contains: $scope.wordsIndexModels.contains + contains: $scope.wordsIndexModels.contains, + entity: entities, + fields: 'id,word,isEntity' }, function(data, headers) { $scope.words = data; $scope.wordsTotal = headers("V-Total"); @@ -1793,7 +1813,7 @@ }); }; - $scope.$watchGroup(['wordsIndexModels.page', 'wordsIndexModels.sortkey', 'wordsIndexModels.sortdir'], $scope.reloadWords); + $scope.$watchGroup(['wordsIndexModels.page', 'wordsIndexModels.sortkey', 'wordsIndexModels.sortdir', 'wordsIndexModels.type'], $scope.reloadWords); $scope.$watchGroup(['wordsIndexModels.startChar', 'wordsIndexModels.contains'], function() { if($scope.wordsIndexModels.page !== 1) @@ -1840,7 +1860,7 @@ sortkey: 'name', sortdir: true, page: 1, - limit: 100 + limit: 50 }; $scope.$watchGroup(['wordsTopicsModels.page', 'wordsTopicsModels.sortkey', 'wordsTopicsModels.sortdir'], function() { @@ -1874,7 +1894,7 @@ sortkey: 'date', sortdir: true, page: 1, - limit: 100 + limit: 50 }; $scope.$watchGroup(['wordsArticlesModels.page', 'wordsArticlesModels.sortkey', 'wordsArticlesModels.sortdir'], function() { @@ -1947,8 +1967,8 @@ /** * Pagination */ - app.controller('PaginationController', ['$scope', - function($scope) { + app.controller('PaginationController', ['$scope', '$location', + function($scope, $location) { $scope.calculatePages = function() { var pages = [], @@ -1972,18 +1992,80 @@ $scope.calculatePages(); $scope.changePage = function(page) { - if(page < 1 || page > $scope.maxPage) return; + if(!page || page < 1 || page > $scope.maxPage || page === $scope.page) return; $scope.page = page; + if($location.search().p !== page) + $location.search('p', page === 1 ? null : page); window.scrollTo(0,0); }; $scope.toPage = function() { var page = prompt("Enter a page number (between 1 and " + $scope.maxPage + ")"); - if (page > 0 && page <= $scope.maxPage) - $scope.changePage(page); + $scope.changePage(page); + }; + + /* + $scope.changePage($location.search().p); + + $scope.$watch('page', function() { + $location.search('p', $scope.page === 1 ? null : $scope.page); + }); + */ + } + ]); + + /* + app.controller('CharSelectorController', ['$scope', '$location', + function($scope, $location) { + + $scope.changeChar = function(char) { + if(!char || $scope.ngModel === char) return; + $scope.ngModel = char; + }; + + $scope.changeChar($location.search().c); + + $scope.$watch('ngModel', function() { + $location.search('c', $scope.ngModel ? $scope.ngModel : null); + }); + } + ]); + + app.controller('SorterController', ['$scope', '$location', + function($scope, $location) { + + $scope.changeSort = function(sort) { + if(!sort || sort === $scope.ngModel) return; + $scope.ngModel = sort; + }; + + $scope.changeSort($location.search().s); + + $scope.$watch('ngModel', function() { + $location.search('s', $scope.ngModel ? $scope.ngModel : null); + }); + } + ]); + + app.controller('SortDirController', ['$scope', '$location', + function($scope, $location) { + + $scope.changeSortDir = function(dir) { + if(!dir || dir === $scope.ngModel || (dir === 'asc') === $scope.ngModel) return; + $scope.ngModel = dir === 'asc'; }; + + $scope.changeSortDir($location.search().d); + + $scope.$watch('ngModel', function() { + if(typeof $scope.ngModel !== 'boolean') + $location.search('d', null); + else + $location.search('d', $scope.ngModel === true ? 'asc' : 'desc'); + }); } ]); + */ /** * Word Evolution diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js index 15781a9999aa527b05dba030a37bb00b096e5d5d..b917830c3116fd3257685be425abfaf31a33b90b 100644 --- a/vipra-ui/app/js/directives.js +++ b/vipra-ui/app/js/directives.js @@ -35,7 +35,8 @@ return { scope: { word: '=', - menu: '@' + menu: '@', + label: '@' }, restrict: 'E', replace: true, @@ -44,6 +45,7 @@ link: function($scope) { $scope.showBadge = $scope.badge !== 'false'; $scope.showMenu = $scope.menu !== 'false'; + $scope.showLabel = $scope.label !== 'false'; $scope.id = typeof $scope.word === 'string' ? $scope.word.toLowerCase() : $scope.word.word; } }; @@ -90,7 +92,8 @@ return { scope: { entity: '=', - menu: '@' + menu: '@', + label: '@' }, restrict: 'E', replace: true, @@ -98,6 +101,8 @@ templateUrl: 'html/directives/entity-link.html', link: function($scope) { $scope.showMenu = $scope.menu !== 'false'; + $scope.showLabel = $scope.label !== 'false'; + $scope.id = typeof $scope.entity === 'string' ? $scope.entity : $scope.entity.entity; } }; }]); @@ -144,7 +149,7 @@ }, controller: 'PaginationController', templateUrl: 'html/directives/sub-pagination.html' - } + }; }]); app.directive('highcharts', [function() { @@ -407,6 +412,7 @@ templateUrl: 'html/directives/entity-menu.html', link: function($scope) { $scope.dropdownRight = $scope.right === 'true'; + $scope.id = typeof $scope.entity === 'string' ? $scope.entity : $scope.entity.entity; } }; }]); @@ -595,4 +601,15 @@ }; }]); + app.directive('sorter', [function() { + return { + scope: { + ngModel: '=' + }, + replace: true, + transclude: true, + templateUrl: 'html/directives/sorter.html' + }; + }]); + })(); \ No newline at end of file diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less index 89e4e7076b42751e05b218512a8bb59a0aac96da..d4280b0b9850e4c0e88c849cb5a1471e307cf4cb 100644 --- a/vipra-ui/app/less/app.less +++ b/vipra-ui/app/less/app.less @@ -296,7 +296,6 @@ td { vertical-align: middle; margin-bottom: 10px; border-bottom: 1px solid #ddd; - height: 41px; &.tabs { padding: 5px 0 0 0; @@ -1101,6 +1100,43 @@ entity-menu { margin: 0; } +.inline-link { + display: inline-block; + margin-left: 5px; +} + +.article-color { + @color: rgb(152, 191, 114); + background-color: @color; + &:hover { + background-color: darken(@color, 10%); + } +} + +.topic-color { + @color: rgb(114, 157, 191); + background-color: @color; + &:hover { + background-color: darken(@color, 10%); + } +} + +.entity-color { + @color: rgb(114, 191, 182); + background-color: @color; + &:hover { + background-color: darken(@color, 10%); + } +} + +.word-color { + @color: rgb(169, 114, 191); + background-color: @color; + &:hover { + background-color: darken(@color, 10%); + } +} + [ng\:cloak], [ng-cloak], .ng-cloak { display: none !important; } diff --git a/vipra-util/src/main/java/de/vipra/util/Constants.java b/vipra-util/src/main/java/de/vipra/util/Constants.java index 53afc45d48e0e72b5e751bcd0fcf4554a5ee0f3f..952c785b8ac553c3b46a5a7289191519b679439c 100644 --- a/vipra-util/src/main/java/de/vipra/util/Constants.java +++ b/vipra-util/src/main/java/de/vipra/util/Constants.java @@ -221,7 +221,7 @@ public class Constants { "was", "way", "we", "welcome", "well", "went", "were", "what", "whatever", "when", "whence", "whenever", "where", "whereafter", "whereas", "whereby", "wherein", "whereupon", "wherever", "whether", "which", "while", "whither", "who", "whoever", "whole", "whom", "whose", "why", "will", "willing", "wish", "with", "within", "without", "wonder", "would", "would", "x", "y", "yes", "yet", "you", "your", "yours", - "yourself", "yourselves", "z", "zero"); + "yourself", "yourselves", "z", "zero", "'ll", "'re", "'s", "'ve", "'t", "'d"); /** * Disallowed chars for words in processed text segments. This regular diff --git a/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java b/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java index 4d2f669a71830ba1d7e29f2248683d9ae2b5717c..d244f27025521221be5e2589f3de78e809ba88d9 100644 --- a/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java +++ b/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java @@ -19,7 +19,7 @@ public class ArticleWord implements Comparable<ArticleWord>, Serializable { public ArticleWord() {} public ArticleWord(final String word, final int count) { - this.word = word; + this.word = word.toLowerCase().trim(); this.count = count; } diff --git a/vipra-util/src/main/java/de/vipra/util/model/WordFull.java b/vipra-util/src/main/java/de/vipra/util/model/WordFull.java index 85d4e91e961515a1417f518bc30798e8a625fff9..5a3b142cb0459d19f3a71ad5c27a23e48bd0ad0d 100644 --- a/vipra-util/src/main/java/de/vipra/util/model/WordFull.java +++ b/vipra-util/src/main/java/de/vipra/util/model/WordFull.java @@ -26,6 +26,9 @@ public class WordFull implements Model<String>, Comparable<WordFull>, Serializab private String word; + @QueryIgnore(multi = true) + private Boolean isEntity; + @Reference @QueryIgnore(multi = true) private TopicModel topicModel; @@ -39,9 +42,10 @@ public class WordFull implements Model<String>, Comparable<WordFull>, Serializab public WordFull() {} public WordFull(final String word, final TopicModel topicModel) { - this.word = word; + this.word = word.toLowerCase().trim(); this.topicModel = topicModel; - id = word + "-" + topicModel.getId(); + id = this.word + "-" + topicModel.getId(); + isEntity = false; } @Override @@ -62,6 +66,14 @@ public class WordFull implements Model<String>, Comparable<WordFull>, Serializab this.word = word; } + public Boolean getIsEntity() { + return isEntity; + } + + public void setIsEntity(Boolean isEntity) { + this.isEntity = isEntity; + } + public TopicModel getTopicModel() { return topicModel; } diff --git a/vipra-util/src/main/java/de/vipra/util/service/MongoService.java b/vipra-util/src/main/java/de/vipra/util/service/MongoService.java index 783ce4dd0556169a66e966864b952589871ff5df..5f5f627cc7370aec09b652dfb38d601298a60563 100644 --- a/vipra-util/src/main/java/de/vipra/util/service/MongoService.java +++ b/vipra-util/src/main/java/de/vipra/util/service/MongoService.java @@ -221,6 +221,28 @@ public class MongoService<Type extends Model<IdType>, IdType> { updateSingle(t, false, fields); } + public void updateMultiple(final Iterable<Type> ts, final String fieldName, final Object value) throws DatabaseException { + final List<IdType> ids = new ArrayList<>(); + for (final Type t : ts) + ids.add(t.getId()); + final Query<Type> query = datastore.createQuery(clazz).field("_id").in(ids); + final UpdateOperations<Type> ops = datastore.createUpdateOperations(clazz); + if (!this.updateFields.containsKey(fieldName)) + throw new DatabaseException("field unknown: " + fieldName); + final Field field = this.updateFields.get(fieldName); + if (field == null) + return; + try { + if (value == null) + ops.unset(fieldName); + else + ops.set(fieldName, value); + } catch (IllegalArgumentException e) { + throw new DatabaseException(e); + } + datastore.update(query, ops, false); + } + public void drop() { datastore.getCollection(clazz).drop(); }