diff --git a/helpers/trendings_helper.py b/helpers/trendings_helper.py index b85caca..06951bb 100644 --- a/helpers/trendings_helper.py +++ b/helpers/trendings_helper.py @@ -158,3 +158,43 @@ class Trendings_helper: tagSet.add(tag['name']) to_ret[self.keyTag] = list(tagSet) return to_ret + + # In contrary of getGenericTrending, it regroups items in the format: {item, start: timestamp1, end: timestamp2} + # so that it can be displayed easily on the timeline. + def getGenericTrendingOvertime(self, dateS, dateE, trendingType=None, topNum=0): + trendingType = self.keyEvent + dico_items = {} + to_format = [] + prev_days = (dateE - dateS).days + # get data + for curDate in util.getXPrevDaysSpan(dateE, prev_days): + keyname = "{}:{}".format(trendingType, util.getDateStrFormat(curDate)) + data = self.serv_redis_db.zrange(keyname, 0, topNum-1, desc=True, withscores=True) + data = [ [record[0].decode('utf8'), record[1]] for record in data ] + data = data if data is not None else [] + to_format.append([util.getTimestamp(curDate), data]) + + for timestamp, array in to_format: + for item, _ in array: + if item not in dico_items: + dico_items[item] = [] + dico_items[item].append(timestamp) + + # sort timestamps in correct order + for item in dico_items.keys(): + dico_items[item].sort() + # dico_items have the form: {item: [t1,t2,t4], ...} + to_ret = [] + ONEDAY = 60*60*24 + for item, timestamps in dico_items.items(): + obj = {'name': item, 'start': timestamps[0]-ONEDAY, 'end': timestamps[0]} + for t in timestamps: + if t-obj['end'] > ONEDAY: #new entry + to_ret.append(obj) + obj['start'] = t-ONEDAY + obj['end'] = t + else: # contrinue entry + obj['end'] = t + to_ret.append(obj) + + return to_ret diff --git a/install_dependencies.sh b/install_dependencies.sh index 420fade..7c98f8b 100755 --- a/install_dependencies.sh +++ b/install_dependencies.sh @@ -108,4 +108,9 @@ mv temp/jquery-punchcard/src/punchcard.js ./static/js mv temp/jquery-punchcard/src/punchcard.css ./static/css wget https://momentjs.com/downloads/moment.js -O ./static/js/moment.js +# timeline +VISJS_VERSION="4.21.0" +https://cdnjs.cloudflare.com/ajax/libs/vis/${VISJS_VERSION}/vis.min.js +https://cdnjs.cloudflare.com/ajax/libs/vis/${VISJS_VERSION}/vis.min.css + rm -rf ./temp diff --git a/server.py b/server.py index ee57001..a23e40d 100755 --- a/server.py +++ b/server.py @@ -536,5 +536,17 @@ def getTypeaheadData(): data = trendings_helper.getTypeaheadData(dateS, dateE) return jsonify(data) +@app.route("/_getGenericTrendingOvertime") +def getGenericTrendingOvertime(): + try: + dateS = datetime.datetime.fromtimestamp(float(request.args.get('dateS'))) + dateE = datetime.datetime.fromtimestamp(float(request.args.get('dateE'))) + except: + dateS = datetime.datetime.now() - datetime.timedelta(days=7) + dateE = datetime.datetime.now() + + data = trendings_helper.getGenericTrendingOvertime(dateS, dateE) + return jsonify(data) + if __name__ == '__main__': app.run(host='localhost', port=8001, threaded=True) diff --git a/static/js/trendings.js b/static/js/trendings.js index 79741e9..7d38216 100644 --- a/static/js/trendings.js +++ b/static/js/trendings.js @@ -9,6 +9,7 @@ var tagPie = ["#tagPie"]; var tagLine = ["#tagLine"]; var sightingLineWidget; var discLine = ["#discussionLine"]; +var timeline; var allData; var globalColorMapping = {}; @@ -103,6 +104,8 @@ var typeaheadOption_tag = { updateLineForLabel(tagLine, tag, undefined, url_getTrendingTag); } } +var timeline_option = {}; + /* FUNCTIONS */ function getColor(label) { @@ -396,6 +399,29 @@ function updateDisc() { }); } +function updateTimeline() { + $.getJSON( url_getGenericTrendingOvertime+"?dateS="+parseInt(dateStart.getTime()/1000)+"&dateE="+parseInt(dateEnd.getTime()/1000), function( data ) { + var items = []; + var i = 1; + for (var obj of data) { + if (obj.end == obj.start) { console.log(obj);} + items.push({ + id: i, + content: obj.name, + start: obj.start*1000, + end: obj.end*1000 + }); + i++; + } + items = new vis.DataSet(items); + if (timeline === undefined) { // create timeline + timeline = new vis.Timeline(document.getElementById('timeline'), items, timeline_option); + } else { // update + timeline.setItems(items); + } + }); +} + function dateChanged() { dateStart = datePickerWidgetStart.datepicker( "getDate" ); dateEnd = datePickerWidgetEnd.datepicker( "getDate" ); @@ -404,6 +430,7 @@ function dateChanged() { updatePieLine(tagPie, tagLine, url_getTrendingTag); updateSignthingsChart(); updateDisc(); + updateTimeline(); } $(document).ready(function () { @@ -426,6 +453,7 @@ $(document).ready(function () { updatePieLine(tagPie, tagLine, url_getTrendingTag) updateSignthingsChart(); updateDisc(); + updateTimeline(); $( "#num_selector" ).change(function() { var sel = parseInt($( this ).val()); @@ -437,5 +465,4 @@ $(document).ready(function () { position: "absolute", display: "none", }).appendTo("body"); - }); diff --git a/templates/trendings.html b/templates/trendings.html index 924e316..2a71b7e 100644 --- a/templates/trendings.html +++ b/templates/trendings.html @@ -36,6 +36,9 @@ + + +