Commit 6e8fd62b authored by Administrator's avatar Administrator

Merge branch 'unstable' into testing

parents 6f574880 ecfd8c80
...@@ -166,6 +166,49 @@ def Root(request, format=None): ...@@ -166,6 +166,49 @@ def Root(request, format=None):
}) })
class NodesChildrenNgrams(APIView):
def get(self, request, node_id):
# query ngrams
ParentNode = aliased(Node)
ngrams_query = (Ngram
.query(Ngram.terms, func.count().label('count'))
# .query(Ngram.id, Ngram.terms, func.count().label('count'))
.join(Node_Ngram, Node_Ngram.ngram_id == Ngram.id)
.join(Node, Node.id == Node_Ngram.node_id)
.filter(Node.parent_id == node_id)
.group_by(Ngram.terms)
# .group_by(Ngram)
.order_by(func.count().desc(), Ngram.terms)
# .order_by(func.count().desc(), Ngram.id)
)
# filters
if 'startwith' in request.GET:
ngrams_query = ngrams_query.filter(Ngram.terms.startswith(request.GET['startwith']))
if 'contain' in request.GET:
ngrams_query = ngrams_query.filter(Ngram.terms.contains(request.GET['contain']))
# pagination
offset = int(request.GET.get('offset', 0))
limit = int(request.GET.get('limit', 20))
total = ngrams_query.count()
# return formatted result
return JsonHttpResponse({
'pagination': {
'offset': offset,
'limit': limit,
'total': total,
},
'data': [
{
# 'id': ngram.id,
'terms': ngram.terms,
'count': ngram.count,
}
for ngram in ngrams_query[offset : offset+limit]
],
})
class NodesChildrenDuplicates(APIView): class NodesChildrenDuplicates(APIView):
def _fetch_duplicates(self, request, node_id, extra_columns=[], min_count=1): def _fetch_duplicates(self, request, node_id, extra_columns=[], min_count=1):
...@@ -234,20 +277,23 @@ class NodesChildrenDuplicates(APIView): ...@@ -234,20 +277,23 @@ class NodesChildrenDuplicates(APIView):
# get the minimum ID for each of the nodes sharing the same metadata # get the minimum ID for each of the nodes sharing the same metadata
kept_node_ids_query = self._fetch_duplicates(request, node_id, [func.min(Node.id).label('id')], 0) kept_node_ids_query = self._fetch_duplicates(request, node_id, [func.min(Node.id).label('id')], 0)
kept_node_ids = [kept_node.id for kept_node in kept_node_ids_query] kept_node_ids = [kept_node.id for kept_node in kept_node_ids_query]
# delete the stuff duplicate_nodes = models.Node.objects.filter( parent_id=node_id ).exclude(id__in=kept_node_ids)
delete_query = (session # # delete the stuff
.query(Node) # delete_query = (session
.filter(Node.parent_id == node_id) # .query(Node)
.filter(~Node.id.in_(kept_node_ids)) # .filter(Node.parent_id == node_id)
) # .filter(~Node.id.in_(kept_node_ids))
count = delete_query.count() # )
delete_query.delete(synchronize_session=False) count = len(duplicate_nodes)
session.flush() for node in duplicate_nodes:
# return the result print("deleting node ",node.id)
node.delete()
# print(delete_query)
# # delete_query.delete(synchronize_session=True)
# session.flush()
return JsonHttpResponse({ return JsonHttpResponse({
'deleted': count, 'deleted': count
}) })
# return duplicates_query
...@@ -291,10 +337,10 @@ class NodesChildrenMetatadata(APIView): ...@@ -291,10 +337,10 @@ class NodesChildrenMetatadata(APIView):
# if there is less than 32 values, retrieve them # if there is less than 32 values, retrieve them
values = None values = None
if isinstance(values_count, int) and values_count <= 48: if isinstance(values_count, int) and values_count <= 48:
values = [row[0] for row in node_metadata_query.all()]
if metadata.type == 'datetime': if metadata.type == 'datetime':
values = [] values = [row[0].isoformat() for row in node_metadata_query.all()]
values = map(lambda x: x.isoformat(), values) else:
values = [row[0] for row in node_metadata_query.all()]
# adding this metadata to the collection # adding this metadata to the collection
collection.append({ collection.append({
...@@ -621,6 +667,7 @@ class Nodes(APIView): ...@@ -621,6 +667,7 @@ class Nodes(APIView):
}) })
# deleting node by id # deleting node by id
# currently, very dangerous
def delete(self, request, node_id): def delete(self, request, node_id):
session = get_session() session = get_session()
node = models.Node.objects.filter(id = node_id) node = models.Node.objects.filter(id = node_id)
......
...@@ -21,7 +21,7 @@ def get_team(): ...@@ -21,7 +21,7 @@ def get_team():
{ 'first_name' : 'David', 'last_name' : 'Chavalarias', 'mail' : '', 'website' : 'http://chavalarias.com', 'picture' : 'david.jpg'}, { 'first_name' : 'David', 'last_name' : 'Chavalarias', 'mail' : '', 'website' : 'http://chavalarias.com', 'picture' : 'david.jpg'},
{ 'first_name' : 'Mathieu', 'last_name' : 'Rodic', 'mail' : '', 'website' : 'http://rodic.fr', 'picture' : 'mathieu.jpg'}, { 'first_name' : 'Mathieu', 'last_name' : 'Rodic', 'mail' : '', 'website' : 'http://rodic.fr', 'picture' : 'mathieu.jpg'},
{ 'first_name' : 'Samuel', 'last_name' : 'Castillo J.', 'mail' : 'kaisleanATgmail.com', 'website' : 'http://www.pksm3.droppages.com', 'picture' : 'samuel.jpg'}, { 'first_name' : 'Samuel', 'last_name' : 'Castillo J.', 'mail' : 'kaisleanATgmail.com', 'website' : 'http://www.pksm3.droppages.com', 'picture' : 'samuel.jpg'},
{ 'first_name' : 'Elias', 'last_name' : 'Showk', 'mail' : '', 'website' : 'https://github.com/elishowk', 'picture' : 'logo.svg'}, { 'first_name' : 'Elias', 'last_name' : 'Showk', 'mail' : '', 'website' : 'https://github.com/elishowk', 'picture' : ''},
#{ 'first_name' : '', 'name' : '', 'mail' : '', 'website' : '', 'picture' : ''}, #{ 'first_name' : '', 'name' : '', 'mail' : '', 'website' : '', 'picture' : ''},
# copy paste the line above and write your informations please # copy paste the line above and write your informations please
] ]
......
...@@ -50,9 +50,11 @@ urlpatterns = patterns('', ...@@ -50,9 +50,11 @@ urlpatterns = patterns('',
# Data management # Data management
url(r'^api$', gargantext_web.api.Root), url(r'^api$', gargantext_web.api.Root),
url(r'^api/nodes/(\d+)/children/ngrams$', gargantext_web.api.NodesChildrenNgrams.as_view()),
url(r'^api/nodes/(\d+)/children/metadata$', gargantext_web.api.NodesChildrenMetatadata.as_view()), url(r'^api/nodes/(\d+)/children/metadata$', gargantext_web.api.NodesChildrenMetatadata.as_view()),
url(r'^api/nodes/(\d+)/children/queries$', gargantext_web.api.NodesChildrenQueries.as_view()), url(r'^api/nodes/(\d+)/children/queries$', gargantext_web.api.NodesChildrenQueries.as_view()),
url(r'^api/nodes/(\d+)/children/duplicates$', gargantext_web.api.NodesChildrenDuplicates.as_view()), url(r'^api/nodes/(\d+)/children/duplicates$', gargantext_web.api.NodesChildrenDuplicates.as_view()),
# url(r'^api/nodes/(\d+)/children/duplicates/delete$', gargantext_web.api.NodesChildrenDuplicates.delete ),
url(r'^api/nodes/(\d+)$', gargantext_web.api.Nodes.as_view()), url(r'^api/nodes/(\d+)$', gargantext_web.api.Nodes.as_view()),
url(r'^api/nodes$', gargantext_web.api.NodesList.as_view()), url(r'^api/nodes$', gargantext_web.api.NodesList.as_view()),
......
...@@ -124,10 +124,10 @@ class CustomForm(forms.Form): ...@@ -124,10 +124,10 @@ class CustomForm(forms.Form):
if len(file_.name)>30: if len(file_.name)>30:
from datetime import datetime from datetime import datetime
file_.name = str(datetime.now().microsecond) file_.name = str(datetime.now().microsecond)
raise forms.ValidationError(_('Come on dude, name too long. Now is:'+file_.name)) # raise forms.ValidationError(_('Come on dude, name too long. Now is:'+file_.name))
#File size #File size
if len(file_)>104857600: if len(file_)>104857600:
raise forms.ValidationError(_('File to heavy! (<100MB svp mec).')) raise forms.ValidationError(_('File to heavy! (<100MB).'))
## File type: ## File type:
# if file_.content_type == "application/zip": # if file_.content_type == "application/zip":
# raise forms.ValidationError(_('We need a zip pls.')) # raise forms.ValidationError(_('We need a zip pls.'))
......
:after,:before,tags-input *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}tags-input .host{position:relative;margin-top:5px;margin-bottom:5px}tags-input .host:active{outline:0}tags-input .tags{-moz-appearance:textfield;-webkit-appearance:textfield;padding:1px;overflow:hidden;word-wrap:break-word;cursor:text;background-color:#fff;border:1px solid #a9a9a9;box-shadow:1px 1px 1px 0 #d3d3d3 inset}tags-input .tags.focused{outline:0;-webkit-box-shadow:0 0 3px 1px rgba(5,139,242,.6);-moz-box-shadow:0 0 3px 1px rgba(5,139,242,.6);box-shadow:0 0 3px 1px rgba(5,139,242,.6)}tags-input .tags .tag-list{margin:0;padding:0;list-style-type:none}tags-input .tags .tag-item{margin:2px;padding:0 5px;display:inline-block;float:left;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif;height:26px;line-height:25px;border:1px solid #acacac;border-radius:3px;background:-webkit-linear-gradient(top,#f0f9ff 0,#cbebff 47%,#a1dbff 100%);background:linear-gradient(to bottom,#f0f9ff 0,#cbebff 47%,#a1dbff 100%)}tags-input .tags .tag-item.selected{background:-webkit-linear-gradient(top,#febbbb 0,#fe9090 45%,#ff5c5c 100%);background:linear-gradient(to bottom,#febbbb 0,#fe9090 45%,#ff5c5c 100%)}tags-input .tags .tag-item .remove-button{margin:0 0 0 5px;padding:0;border:none;background:0 0;cursor:pointer;vertical-align:middle;font:700 16px Arial,sans-serif;color:#585858}tags-input .tags .tag-item .remove-button:active{color:red}tags-input .tags .input{border:0;outline:0;margin:2px;padding:0;padding-left:5px;float:left;height:26px;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}tags-input .tags .input.invalid-tag{color:red}tags-input .tags .input::-ms-clear{display:none}tags-input.ng-invalid .tags{-webkit-box-shadow:0 0 3px 1px rgba(255,0,0,.6);-moz-box-shadow:0 0 3px 1px rgba(255,0,0,.6);box-shadow:0 0 3px 1px rgba(255,0,0,.6)}tags-input .autocomplete{margin-top:5px;position:absolute;padding:5px 0;z-index:999;width:100%;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}tags-input .autocomplete .suggestion-list{margin:0;padding:0;list-style-type:none}tags-input .autocomplete .suggestion-item{padding:5px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font:16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}tags-input .autocomplete .suggestion-item.selected,tags-input .autocomplete .suggestion-item.selected em{color:#fff;background-color:#0097cf}tags-input .autocomplete .suggestion-item em{font:normal bold 16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}
\ No newline at end of file
...@@ -108,7 +108,7 @@ var groupings = { ...@@ -108,7 +108,7 @@ var groupings = {
// Define the application // Define the application
var gargantext = angular.module('Gargantext', ['n3-charts.linechart', 'ngCookies']); var gargantext = angular.module('Gargantext', ['n3-charts.linechart', 'ngCookies', 'ngTagsInput']);
// Customize the application's scope // Customize the application's scope
...@@ -272,16 +272,36 @@ gargantext.controller("DatasetController", function($scope, $http) { ...@@ -272,16 +272,36 @@ gargantext.controller("DatasetController", function($scope, $http) {
$scope.entities = undefined; $scope.entities = undefined;
$scope.filters = []; $scope.filters = [];
$http.get(url, {cache: true}).success(function(response){ $http.get(url, {cache: true}).success(function(response){
$scope.entities = { $scope.entities = [
metadata: response.data, {
ngrams: [ key: 'metadata',
columns: response.data
},
{
key: 'ngrams',
columns: [
{key:'terms', type:'string'}, {key:'terms', type:'string'},
{key:'terms count', type:'integer'} {key:'terms count', type:'integer'}
] ],
}; }
];
}); });
$scope.updateQuery(); $scope.updateQuery();
}; };
// query ngrams
$scope.getNgrams = function(query) {
var url = '/api/nodes/' + $scope.corpusId + '/children/ngrams?limit=10&contain=' + encodeURI(query);
var appendTransform = function(defaults, transform) {
defaults = angular.isArray(defaults) ? defaults : [defaults];
return defaults.concat(transform);
}
return $http.get(url, {
transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
console.log(value.data)
return value.data;
})
});
};
// filtering informations retrieval // filtering informations retrieval
$scope.operators = operators; $scope.operators = operators;
// add a filter // add a filter
...@@ -308,12 +328,26 @@ gargantext.controller("DatasetController", function($scope, $http) { ...@@ -308,12 +328,26 @@ gargantext.controller("DatasetController", function($scope, $http) {
continue; continue;
} }
} }
if (filter.entity.key == 'ngrams') {
var termsList = [];
angular.forEach(filter.value, function(ngram) {
termsList.push(ngram.terms);
});
if (termsList.length) {
filters.push({ filters.push({
field: filter.entity + '.' + filter.column, field: 'ngrams.terms',
operator: 'in',
value: termsList
});
}
} else {
filters.push({
field: filter.entity.key + '.' + filter.column.key,
operator: filter.operator, operator: filter.operator,
value: filter.value value: filter.value
}); });
} }
}
// event firing to parent(s) // event firing to parent(s)
$scope.$emit('updateDataset', { $scope.$emit('updateDataset', {
datasetIndex: $scope.$index, datasetIndex: $scope.$index,
......
/*! ngTagsInput v2.0.1 License: MIT */!function(){"use strict";function a(){var a={};return{on:function(b,c){return b.split(" ").forEach(function(b){a[b]||(a[b]=[]),a[b].push(c)}),this},trigger:function(b,c){return angular.forEach(a[b],function(a){a.call(null,c)}),this}}}function b(a,b){return a=a||[],a.length>0&&!angular.isObject(a[0])&&a.forEach(function(c,d){a[d]={},a[d][b]=c}),a}function c(a,b,c){for(var d=null,e=0;e<a.length;e++)if(a[e][c].toLowerCase()===b[c].toLowerCase()){d=a[e];break}return d}function d(a,b,c){var d=b.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return a.replace(new RegExp(d,"gi"),c)}var e={backspace:8,tab:9,enter:13,escape:27,space:32,up:38,down:40,comma:188},f=angular.module("ngTagsInput",[]);f.directive("tagsInput",["$timeout","$document","tagsInputConfig",function(d,f,g){function h(a,b){var d,e,f,g={};return d=function(b){return b[a.displayProperty]},e=function(b,c){b[a.displayProperty]=c},f=function(b){var e=d(b);return e.length>=a.minLength&&e.length<=(a.maxLength||e.length)&&a.allowedTagsPattern.test(e)&&!c(g.items,b,a.displayProperty)},g.items=[],g.addText=function(a){var b={};return e(b,a),g.add(b)},g.add=function(c){var h=d(c).trim();return a.replaceSpacesWithDashes&&(h=h.replace(/\s/g,"-")),e(c,h),f(c)?(g.items.push(c),b.trigger("tag-added",{$tag:c})):b.trigger("invalid-tag",{$tag:c}),c},g.remove=function(a){var c=g.items.splice(a,1)[0];return b.trigger("tag-removed",{$tag:c}),c},g.removeLast=function(){var b,c=g.items.length-1;return a.enableEditingLastTag||g.selected?(g.selected=null,b=g.remove(c)):g.selected||(g.selected=g.items[c]),b},g}return{restrict:"E",require:"ngModel",scope:{tags:"=ngModel",onTagAdded:"&",onTagRemoved:"&"},replace:!1,transclude:!0,templateUrl:"ngTagsInput/tags-input.html",controller:["$scope","$attrs","$element",function(b,c,d){g.load("tagsInput",b,c,{placeholder:[String,"Add a tag"],tabindex:[Number],removeTagSymbol:[String,String.fromCharCode(215)],replaceSpacesWithDashes:[Boolean,!0],minLength:[Number,3],maxLength:[Number],addOnEnter:[Boolean,!0],addOnSpace:[Boolean,!1],addOnComma:[Boolean,!0],addOnBlur:[Boolean,!0],allowedTagsPattern:[RegExp,/.+/],enableEditingLastTag:[Boolean,!1],minTags:[Number],maxTags:[Number],displayProperty:[String,"text"],allowLeftoverText:[Boolean,!1],addFromAutocompleteOnly:[Boolean,!1]}),b.events=new a,b.tagList=new h(b.options,b.events),this.registerAutocomplete=function(){var a=d.find("input");return a.on("keydown",function(a){b.events.trigger("input-keydown",a)}),{addTag:function(a){return b.tagList.add(a)},focusInput:function(){a[0].focus()},getTags:function(){return b.tags},getOptions:function(){return b.options},on:function(a,c){return b.events.on(a,c),this}}}}],link:function(a,c,g,h){var i=[e.enter,e.comma,e.space,e.backspace],j=a.tagList,k=a.events,l=a.options,m=c.find("input");k.on("tag-added",a.onTagAdded).on("tag-removed",a.onTagRemoved).on("tag-added",function(){a.newTag.text=""}).on("tag-added tag-removed",function(){h.$setViewValue(a.tags)}).on("invalid-tag",function(){a.newTag.invalid=!0}).on("input-change",function(){j.selected=null,a.newTag.invalid=null}).on("input-focus",function(){h.$setValidity("leftoverText",!0)}).on("input-blur",function(){l.addFromAutocompleteOnly||(l.addOnBlur&&j.addText(a.newTag.text),h.$setValidity("leftoverText",l.allowLeftoverText?!0:!a.newTag.text))}),a.newTag={text:"",invalid:null},a.getDisplayText=function(a){return a[l.displayProperty].trim()},a.track=function(a){return a[l.displayProperty]},a.newTagChange=function(){k.trigger("input-change",a.newTag.text)},a.$watch("tags",function(c){a.tags=b(c,l.displayProperty),j.items=a.tags}),a.$watch("tags.length",function(a){h.$setValidity("maxTags",angular.isUndefined(l.maxTags)||a<=l.maxTags),h.$setValidity("minTags",angular.isUndefined(l.minTags)||a>=l.minTags)}),m.on("keydown",function(b){if(!b.isImmediatePropagationStopped||!b.isImmediatePropagationStopped()){var c,d,f=b.keyCode,g=b.shiftKey||b.altKey||b.ctrlKey||b.metaKey,h={};if(!g&&-1!==i.indexOf(f))if(h[e.enter]=l.addOnEnter,h[e.comma]=l.addOnComma,h[e.space]=l.addOnSpace,c=!l.addFromAutocompleteOnly&&h[f],d=!c&&f===e.backspace&&0===a.newTag.text.length,c)j.addText(a.newTag.text),a.$apply(),b.preventDefault();else if(d){var k=j.removeLast();k&&l.enableEditingLastTag&&(a.newTag.text=k[l.displayProperty]),a.$apply(),b.preventDefault()}}}).on("focus",function(){a.hasFocus||(a.hasFocus=!0,k.trigger("input-focus"),a.$apply())}).on("blur",function(){d(function(){var b=f.prop("activeElement"),d=b===m[0],e=c[0].contains(b);(d||!e)&&(a.hasFocus=!1,k.trigger("input-blur"))})}),c.find("div").on("click",function(){m[0].focus()})}}}]),f.directive("autoComplete",["$document","$timeout","$sce","tagsInputConfig",function(a,f,g,h){function i(a,d){var e,g,h,i={};return g=function(a,b){return a.filter(function(a){return!c(b,a,d.tagsInput.displayProperty)})},i.reset=function(){h=null,i.items=[],i.visible=!1,i.index=-1,i.selected=null,i.query=null,f.cancel(e)},i.show=function(){i.selected=null,i.visible=!0},i.load=function(c,j){return c.length<d.minLength?void i.reset():(f.cancel(e),void(e=f(function(){i.query=c;var e=a({$query:c});h=e,e.then(function(a){e===h&&(a=b(a.data||a,d.tagsInput.displayProperty),a=g(a,j),i.items=a.slice(0,d.maxResultsToShow),i.items.length>0?i.show():i.reset())})},d.debounceDelay,!1)))},i.selectNext=function(){i.select(++i.index)},i.selectPrior=function(){i.select(--i.index)},i.select=function(a){0>a?a=i.items.length-1:a>=i.items.length&&(a=0),i.index=a,i.selected=i.items[a]},i.reset(),i}function j(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}return{restrict:"E",require:"^tagsInput",scope:{source:"&"},templateUrl:"ngTagsInput/auto-complete.html",link:function(b,c,f,k){var l,m,n,o,p,q=[e.enter,e.tab,e.escape,e.up,e.down];h.load("autoComplete",b,f,{debounceDelay:[Number,100],minLength:[Number,3],highlightMatchedText:[Boolean,!0],maxResultsToShow:[Number,10]}),n=b.options,m=k.registerAutocomplete(),n.tagsInput=m.getOptions(),l=new i(b.source,n),o=function(a){return a[n.tagsInput.displayProperty]},b.suggestionList=l,b.addSuggestion=function(){var a=!1;return l.selected&&(m.addTag(l.selected),l.reset(),m.focusInput(),a=!0),a},b.highlight=function(a){var b=o(a);return b=j(b),n.highlightMatchedText&&(b=d(b,j(l.query),"<em>$&</em>")),g.trustAsHtml(b)},b.track=function(a){return o(a)},m.on("tag-added invalid-tag",function(){l.reset()}).on("input-change",function(a){a?l.load(a,m.getTags()):l.reset()}).on("input-keydown",function(a){var c,d;if(-1!==q.indexOf(a.keyCode)){var f=!1;a.stopImmediatePropagation=function(){f=!0,a.stopPropagation()},a.isImmediatePropagationStopped=function(){return f},l.visible&&(c=a.keyCode,d=!1,c===e.down?(l.selectNext(),d=!0):c===e.up?(l.selectPrior(),d=!0):c===e.escape?(l.reset(),d=!0):(c===e.enter||c===e.tab)&&(d=b.addSuggestion()),d&&(a.preventDefault(),a.stopImmediatePropagation(),b.$apply()))}}).on("input-blur",function(){l.reset()}),p=function(){l.visible&&(l.reset(),b.$apply())},a.on("click",p),b.$on("$destroy",function(){a.off("click",p)})}}}]),f.directive("tiTranscludeAppend",function(){return function(a,b,c,d,e){e(function(a){b.append(a)})}}),f.directive("tiAutosize",function(){return{restrict:"A",require:"ngModel",link:function(a,b,c,d){var e,f,g=3;e=angular.element('<span class="input"></span>'),e.css("display","none").css("visibility","hidden").css("width","auto").css("white-space","pre"),b.parent().append(e),f=function(a){var d,f=a;return angular.isString(f)&&0===f.length&&(f=c.placeholder),f&&(e.text(f),e.css("display",""),d=e.prop("offsetWidth"),e.css("display","none")),b.css("width",d?d+g+"px":""),a},d.$parsers.unshift(f),d.$formatters.unshift(f),c.$observe("placeholder",function(a){d.$modelValue||f(a)})}}}),f.provider("tagsInputConfig",function(){var a={},b={};this.setDefaults=function(b,c){return a[b]=c,this},this.setActiveInterpolation=function(a,c){return b[a]=c,this},this.$get=["$interpolate",function(c){var d={};return d[String]=function(a){return a},d[Number]=function(a){return parseInt(a,10)},d[Boolean]=function(a){return"true"===a.toLowerCase()},d[RegExp]=function(a){return new RegExp(a)},{load:function(e,f,g,h){f.options={},angular.forEach(h,function(h,i){var j,k,l,m,n;j=h[0],k=h[1],l=d[j],m=function(){var b=a[e]&&a[e][i];return angular.isDefined(b)?b:k},n=function(a){f.options[i]=a?l(a):m()},b[e]&&b[e][i]?g.$observe(i,function(a){n(a)}):n(g[i]&&c(g[i])(f.$parent))})}}}]}),f.run(["$templateCache",function(a){a.put("ngTagsInput/tags-input.html",'<div class="host" tabindex="-1" ti-transclude-append=""><div class="tags" ng-class="{focused: hasFocus}"><ul class="tag-list"><li class="tag-item" ng-repeat="tag in tagList.items track by track(tag)" ng-class="{ selected: tag == tagList.selected }"><span>{{getDisplayText(tag)}}</span> <a class="remove-button" ng-click="tagList.remove($index)">{{options.removeTagSymbol}}</a></li></ul><input class="input" placeholder="{{options.placeholder}}" tabindex="{{options.tabindex}}" ng-model="newTag.text" ng-change="newTagChange()" ng-trim="false" ng-class="{\'invalid-tag\': newTag.invalid}" ti-autosize=""></div></div>'),a.put("ngTagsInput/auto-complete.html",'<div class="autocomplete" ng-show="suggestionList.visible"><ul class="suggestion-list"><li class="suggestion-item" ng-repeat="item in suggestionList.items track by track(item)" ng-class="{selected: item == suggestionList.selected}" ng-click="addSuggestion()" ng-mouseenter="suggestionList.select($index)" ng-bind-html="highlight(item)"></li></ul></div>')}])}();
\ No newline at end of file
...@@ -20,17 +20,85 @@ ...@@ -20,17 +20,85 @@
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseVersions">
<h2>Versions</h2>
</a>
</h2>
</div>
<div id="collapseVersions" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div class="container">
<ul>
<li>Version 1.0</li>
<ul>
<li>Beta Version </li>
<li>Licence of Gargantext is GPL v3+ </li>
</ul>
<li>Version 1.0.5</li>
<ul>
<li>Bug resolution: xml zipped from Mac</li>
<li>Bug resolution: french accents in filenames</li>
<li>New features: [Advanced chart] ngrams completion</li>
<li>New features: button to delete all duplicates</li>
</ul>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseCommunity">
<h2>Community</h2>
</a>
</h2>
</div>
<div id="collapseCommunity" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div class="container">
<ul>
<li>Mailing-lists</li>
<ul>
<li>User mailing-list: soon</li>
<li>Devel mailing-list: soon</li>
</ul>
<li>Code and repository access</li>
<ul>
<li>You are free to participate. Present yourself on mailing-lists or irc.</li>
</ul>
<li>IRC</li>
<ul>
<li>#gargantext on OFTC:</li>
<li>
<p><iframe src="http://webchat.oftc.net/?channels=#gargantext" width="500" height="350"></iframe></p>
<p>If the window is too small, just click <a href="http://webchat.oftc.net/?channels=#gargantext">here</a></p>
</li>
</ul>
</ul>
</div>
</div>
</div>
</div>
{% if team %} {% if team %}
<div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title"> <h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseTeam">
<h2>The Team</h2> <h2>Core team</h2>
</a> </a>
</h2> </h2>
</div> </div>
<div id="collapseOne" class="panel-collapse show" role="tabpanel"> <div id="collapseTeam" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body"> <div class="panel-body">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
...@@ -40,6 +108,8 @@ ...@@ -40,6 +108,8 @@
<div class="thumbnail"> <div class="thumbnail">
{% if member.picture %} {% if member.picture %}
<img src="{% static "img/team/"%}{{ member.picture }}" style="100px; height:150px"> <img src="{% static "img/team/"%}{{ member.picture }}" style="100px; height:150px">
{% else %}
<img src="{% static "img/logo.png" %}" style="100px; height:150px">
{% endif %} {% endif %}
<div class="caption"> <div class="caption">
<h3>{{ member.first_name }} {{member.last_name }}</h3> <h3>{{ member.first_name }} {{member.last_name }}</h3>
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
<div class="container theme-showcase" role="main"> <div class="container theme-showcase" role="main">
<div class="jumbotron"> <div class="jumbotron">
<h1>Advanced charts</h1> <h1>Advanced chart</h1>
<p>Custom, test, interpret</p>
</div> </div>
</div> </div>
...@@ -217,8 +218,11 @@ ...@@ -217,8 +218,11 @@
</div> </div>
--> -->
<div ng-app="Gargantext" ng-controller="GraphController"> <div ng-app="Gargantext" ng-controller="GraphController">
<ul class="datasets"> <ul class="datasets">
<button class="add" ng-click="addDataset()">Add a dataset...</button> <button class="add" ng-click="addDataset()">Add a dataset...</button>
<li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets"> <li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets">
...@@ -236,21 +240,17 @@ ...@@ -236,21 +240,17 @@
<li ng-repeat="filter in filters"> <li ng-repeat="filter in filters">
<button ng-click="removeFilter($index)" title="remove this filter">x</button> <button ng-click="removeFilter($index)" title="remove this filter">x</button>
<span>...where the </span> <span>...where the </span>
<select ng-model="filter.entity"> <select ng-model="filter.entity" ng-options="entity as entity.key for entity in entities"></select>
<option ng-repeat="(entityName, entityColumns) in entities" value="{{entityName}}">{{entityName}}</option> <span ng-if="filter.entity.key != 'ngrams'">
</select> <select ng-if="filter.entity" ng-model="filter.column" ng-options="column as column.key for column in filter.entity.columns | orderBy:'key'"></select>
<span ng-if="filter.entity"> <select ng-if="filter.column" ng-model="filter.operator" ng-options="operator.key as operator.label for operator in operators[filter.column.type]"></select>
<select ng-model="filter.column"> <input ng-if="filter.operator" type="text" ng-model="filter.value" ng-change="updateQuery()">
<option ng-repeat="column in entities[filter.entity] | orderBy:'key'" value="{{column.key}}">{{column.key}}</option>
</select>
<span ng-if="filter.column" ng-repeat="column in entities[filter.entity]">
<span ng-if="column.key == filter.column">
<select ng-model="filter.operator">
<option ng-repeat="operator in operators[column.type]" value="{{operator.key}}">{{operator.label}}</option>
</select>
<input type="text" ng-model="filter.value" ng-change="updateQuery()">
</span>
</span> </span>
<span ng-if="filter.entity.key == 'ngrams'">
are in this list:
<tags-input ng-model="filter.value" display-property="terms" placeholder="Add an ngram" on-tag-added="updateQuery()" on-tag-removed="updateQuery()" add-from-autocomplete-only="true">
<auto-complete source="getNgrams($query)"></auto-complete>
</tags-input ng-model="tags">
</span> </span>
</li> </li>
</ul> </ul>
...@@ -333,7 +333,9 @@ ...@@ -333,7 +333,9 @@
<script type="text/javascript" src="{% static "js/angular-cookies.min.js" %}"></script> <script type="text/javascript" src="{% static "js/angular-cookies.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "js/d3/angular-charts.js" %}"></script> -->
<script type="text/javascript" src="{% static "js/ng-tags-input.min.js" %}"></script>
<link rel="stylesheet" href="{% static "css/ng-tags-input.min.css" %}">
<script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script> <script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script>
...@@ -358,3 +360,4 @@ ...@@ -358,3 +360,4 @@
...@@ -239,6 +239,7 @@ $.ajax({ ...@@ -239,6 +239,7 @@ $.ajax({
BIS_dict[untitlebis[0]] = [bisarray[i].count , 0];// [ total amount , removed ] BIS_dict[untitlebis[0]] = [bisarray[i].count , 0];// [ total amount , removed ]
} }
pr(BIS_dict) pr(BIS_dict)
if(Object.keys(BIS_dict).length>0) $("#delAll").css("visibility", "visible"); $("#delAll").show();
} }
}); });
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
<!-- Why not French ? --> <!-- Why not French ? -->
<!-- find Cambridge source which inspired this --!> <!-- find Cambridge source which inspired this --!>
Il praaît que l'odrre des ltteers dnas un mto n'a pas Il praaît que l'odrre des ltetres dnas un mot n'a pas
d'iprnorotncae. La pmeirère et la drenèire letrte diovent d'iprnorotncae. La pmeirère et la drenèire letrte diovent
êrte à la bnnoe pclae. Le rsete peut êrte dnas un dsérorde êrte à la bnnoe pclae. Le rsete peut êrte dnas un dsérorde
ttoal et on puet tujoruos lrie snas poribême. On ne lit ttoal et on puet tujoruos lrie snas poribême. On ne lit
......
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<hr> <hr>
<footer> <footer>
<p>Gargantext v.1.0 (Copyrights CNRS {{ date.year }})</p> <p>Gargantext, version 1.0.5, Copyrights CNRS {{ date.year }}.</p>
</footer> </footer>
......
...@@ -90,8 +90,8 @@ ...@@ -90,8 +90,8 @@
<button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom" <button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content=' data-content='
<ul> <ul>
<li> Add documents </li>
<li> Rename </li> <li> Rename </li>
<li> Add new documents </li>
<li><a href="/project/{{ project.id }}/corpus/{{ corpus.id}}/delete">Delete</a></li> <li><a href="/project/{{ project.id }}/corpus/{{ corpus.id}}/delete">Delete</a></li>
</ul> </ul>
'>Manage</button> '>Manage</button>
......
...@@ -38,7 +38,16 @@ ...@@ -38,7 +38,16 @@
<!--<div class="col-md-offset-7 col-md-4 content" style="background-color:grey">!--> <!--<div class="col-md-offset-7 col-md-4 content" style="background-color:grey">!-->
<div class="col-md-3 content"> <div class="col-md-3 content">
<h3><a href="/project/{{ project.id }}">{{ project.name }}</a> <h3><a href="/project/{{ project.id }}">{{ project.name }}</a>
<button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom" data-content='<a href="/project/{{ project.id }}/delete">Yes, I am sure!</a>'>Delete</button>
<button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content='
<ul>
<li> Rename </li>
<li> Add new corpus </li>
<li><a href="/project/{{ project.id }}/delete">Delete</a></li>
</ul>
'>Manage</button>
</h3> </h3>
<h4>{{ project.subtitle }}<h4> <h4>{{ project.subtitle }}<h4>
......
...@@ -19,6 +19,12 @@ ...@@ -19,6 +19,12 @@
{% if documents %} {% if documents %}
<div id="delAll" style="visibility: hidden;">
<button onclick="deleteDuplicates(theurl);">Delete Duplicates</button>
</div>
<ul> <ul>
{% for doc in documents %} {% for doc in documents %}
{% if doc.date %} {% if doc.date %}
...@@ -45,6 +51,26 @@ function getCookie(name) { ...@@ -45,6 +51,26 @@ function getCookie(name) {
return cookieValue; return cookieValue;
} }
function deleteDuplicates(url) {
console.log("hello world")
console.log(url)
$.ajax({
url: url,
type: 'DELETE',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("in DeleteDuplicates")
console.log(data)
$("#delAll").remove();
},
error: function(result) {
console.log("Data not found");
console.log(result)
}
});
}
function deleteNode(node_id) { function deleteNode(node_id) {
$.ajax({ $.ajax({
...@@ -111,6 +137,11 @@ function deleteNode(node_id) { ...@@ -111,6 +137,11 @@ function deleteNode(node_id) {
//'+"{{doc.id}}"+',\"'+title+'\" //'+"{{doc.id}}"+',\"'+title+'\"
current_docs = {} current_docs = {}
if(Object.keys(BIS_dict).length>0) {
$("#delAll").css("visibility", "visible");
$("#delAll").show();
} else $("#delAll").remove()
{% for doc in documents %} {% for doc in documents %}
id = "doc_{{doc.id}}" id = "doc_{{doc.id}}"
title = $("<div/>").html("{{doc.name}}").text() title = $("<div/>").html("{{doc.name}}").text()
......
...@@ -218,8 +218,11 @@ ...@@ -218,8 +218,11 @@
</div> </div>
--> -->
<div ng-app="Gargantext" ng-controller="GraphController"> <div ng-app="Gargantext" ng-controller="GraphController">
<ul class="datasets"> <ul class="datasets">
<button class="add" ng-click="addDataset()">Add a dataset...</button> <button class="add" ng-click="addDataset()">Add a dataset...</button>
<li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets"> <li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets">
...@@ -237,21 +240,17 @@ ...@@ -237,21 +240,17 @@
<li ng-repeat="filter in filters"> <li ng-repeat="filter in filters">
<button ng-click="removeFilter($index)" title="remove this filter">x</button> <button ng-click="removeFilter($index)" title="remove this filter">x</button>
<span>...where the </span> <span>...where the </span>
<select ng-model="filter.entity"> <select ng-model="filter.entity" ng-options="entity as entity.key for entity in entities"></select>
<option ng-repeat="(entityName, entityColumns) in entities" value="{{entityName}}">{{entityName}}</option> <span ng-if="filter.entity.key != 'ngrams'">
</select> <select ng-if="filter.entity" ng-model="filter.column" ng-options="column as column.key for column in filter.entity.columns | orderBy:'key'"></select>
<span ng-if="filter.entity"> <select ng-if="filter.column" ng-model="filter.operator" ng-options="operator.key as operator.label for operator in operators[filter.column.type]"></select>
<select ng-model="filter.column"> <input ng-if="filter.operator" type="text" ng-model="filter.value" ng-change="updateQuery()">
<option ng-repeat="column in entities[filter.entity] | orderBy:'key'" value="{{column.key}}">{{column.key}}</option>
</select>
<span ng-if="filter.column" ng-repeat="column in entities[filter.entity]">
<span ng-if="column.key == filter.column">
<select ng-model="filter.operator">
<option ng-repeat="operator in operators[column.type]" value="{{operator.key}}">{{operator.label}}</option>
</select>
<input type="text" ng-model="filter.value" ng-change="updateQuery()">
</span>
</span> </span>
<span ng-if="filter.entity.key == 'ngrams'">
are in this list:
<tags-input ng-model="filter.value" display-property="terms" placeholder="Add an ngram" on-tag-added="updateQuery()" on-tag-removed="updateQuery()" add-from-autocomplete-only="true">
<auto-complete source="getNgrams($query)"></auto-complete>
</tags-input ng-model="tags">
</span> </span>
</li> </li>
</ul> </ul>
...@@ -334,7 +333,9 @@ ...@@ -334,7 +333,9 @@
<script type="text/javascript" src="{% static "js/angular-cookies.min.js" %}"></script> <script type="text/javascript" src="{% static "js/angular-cookies.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "js/d3/angular-charts.js" %}"></script> -->
<script type="text/javascript" src="{% static "js/ng-tags-input.min.js" %}"></script>
<link rel="stylesheet" href="{% static "css/ng-tags-input.min.css" %}">
<script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script> <script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment