From 26b1abc309e0545c98c1468e7d7d2c3ca2749b38 Mon Sep 17 00:00:00 2001
From: jaden <noreply@example.com>
Date: Mon, 12 Jun 2017 14:52:19 +0200
Subject: [PATCH] mv lastEdited timer to css animation, closes #45

---
 .../reports/app/directives/lastEdited.js      | 141 ------------------
 .../static/reports/app/directives/save.js     |   7 +-
 .../reports/app/services/reportService.js     |   1 -
 beat/web/reports/static/reports/css/style.css |  18 +++
 .../web/reports/templates/reports/report.html |   7 +-
 5 files changed, 27 insertions(+), 147 deletions(-)
 delete mode 100644 beat/web/reports/static/reports/app/directives/lastEdited.js

diff --git a/beat/web/reports/static/reports/app/directives/lastEdited.js b/beat/web/reports/static/reports/app/directives/lastEdited.js
deleted file mode 100644
index c824d170f..000000000
--- a/beat/web/reports/static/reports/app/directives/lastEdited.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
- * Contact: beat.support@idiap.ch
- *
- * This file is part of the beat.web module of the BEAT platform.
- *
- * Commercial License Usage
- * Licensees holding valid commercial BEAT licenses may use this file in
- * accordance with the terms contained in a written agreement between you
- * and Idiap. For further information contact tto@idiap.ch
- *
- * Alternatively, this file may be used under the terms of the GNU Affero
- * Public License version 3 as published by the Free Software and appearing
- * in the file LICENSE.AGPL included in the packaging of this file.
- * The BEAT platform is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero Public License along
- * with the BEAT platform. If not, see http://www.gnu.org/licenses/.
- */
-
-/*
- * lastEdited
- * Desc:
- * 	shows a live & humanized last-edited timestamp
- */
-angular.module('reportApp')
-.directive("lastEdited", ['ReportService', '$interval', '$timeout', function(ReportService, $interval, $timeout){
-	return {
-		scope: {
-			initStr: '@'
-		},
-		link: function(scope){
-			scope.ReportService = ReportService;
-
-			// humanize some amount of time
-			const nowFunc = () => 'Just now';
-			const secondFunc = (s) => `${s} second${s === 1 ? '' : 's'} ago`;
-			const minuteFunc = (m) => `${m} minute${m === 1 ? '' : 's'} ago`;
-			const hourFunc = (h) => `${h} hour${h === 1 ? '' : 's'} ago`;
-
-			// convert from/to ms to/from a different time seg
-			const intoSeconds = (t) => Math.floor(t / 1000);
-			const intoMinutes = (t) => Math.floor(intoSeconds(t) / 60);
-			const intoHours = (t) => Math.floor(intoMinutes(t) / 60);
-			const fromSeconds = (s) => s * 1000;
-			const fromMinutes = (m) => fromSeconds(m * 60);
-			const fromHours = (h) => fromMinutes(h * 60);
-
-			// cutoffs & corresponding update freq
-			const before1m = fromSeconds(5);
-			const before10m = fromMinutes(1);
-			const before1h = fromMinutes(10);
-			const after1h = fromHours(1);
-
-			// different update funcs for diff time intervals
-			const beginning = () => nowFunc();
-			const every5s = (t) => secondFunc(intoSeconds(t));
-			const every1m = (t) => minuteFunc(intoMinutes(t));
-			const every10m = (t) => minuteFunc(intoMinutes(t));
-			const every1h = (t) => hourFunc(intoHours(t));
-
-			// current string to be shown
-			scope.currStr = {
-				val: scope.initStr
-			};
-
-			const updateCurrStr = (t, strFunc) => {
-				const str = strFunc(Date.now() - t);
-				scope.currStr.val = str;
-				return str;
-			};
-
-			// curr interval ids
-			let currIntervalIds = [];
-
-			// interval funcs
-			const secondsInterval = (t) => {
-				const id = $interval(updateCurrStr, before1m, 0, true, t, every5s);
-				const tid = $timeout(() => $interval.cancel(id), fromSeconds(59));
-
-				return [id, tid];
-			};
-			const singleMinutesInterval = (t) => {
-				const id = $interval(updateCurrStr, before10m, 0, true, t, every1m);
-				const tid = $timeout(() => $interval.cancel(id), fromMinutes(9.9));
-
-				return [id, tid];
-			};
-			const tenMinutesInterval = (t) => {
-				const id = $interval(updateCurrStr, before1h, 0, true, t, every10m);
-				const tid = $timeout(() => $interval.cancel(id), fromMinutes(59));
-
-				return [id, tid];
-			};
-			const hourInterval = (t) => {
-				const id = $interval(updateCurrStr, after1h, 0, true, t, every1h);
-				const tid = $timeout(() => $interval.cancel(id), fromMinutes(61));
-
-				return [id, tid];
-			};
-
-			const setupIntervals = (t) => {
-				const intervalIds = [
-					...secondsInterval(t),
-					...singleMinutesInterval(t),
-					...tenMinutesInterval(t),
-					...hourInterval(t)
-				];
-
-				return intervalIds;
-			};
-
-			const cancelIntervals = () => currIntervalIds.forEach(id => $interval.cancel(id));
-
-			const reset = () => {
-				cancelIntervals();
-				updateCurrStr(0, beginning);
-				currIntervalIds = setupIntervals(ReportService.lastEditedTime);
-			};
-
-			// watch lastEditedTime for a change and start/restart the timers
-			scope.$watch('ReportService.lastEditedTime', (newTime, oldTime) => {
-				if(newTime > oldTime && newTime !== 0 && Date.now() > newTime){
-					reset();
-				}
-			});
-
-			// need to clear timers/intervals when this el is destroyed
-			scope.$on('$destroy', cancelIntervals);
-
-			if(ReportService.lastEditedTime > 0){
-				reset();
-			}
-		},
-		template: `
-Last Edited: <strong>{{ currStr.val }}</strong>
-`
-	};
-}]);
diff --git a/beat/web/reports/static/reports/app/directives/save.js b/beat/web/reports/static/reports/app/directives/save.js
index 5fefdd874..77c48e8bb 100644
--- a/beat/web/reports/static/reports/app/directives/save.js
+++ b/beat/web/reports/static/reports/app/directives/save.js
@@ -32,6 +32,7 @@ angular.module('reportApp')
 		},
 		restrict: 'A',
 		link: function(scope, el){
+
 			const saveReport = () => {
 				// save the serialized group data...
 				// the rest of the state is reconstructed from it and the URL
@@ -44,8 +45,10 @@ angular.module('reportApp')
 				return reportFactory.removeExperiments(ExperimentsService.cachedDeletedExperiments)
 				.then(() => reportFactory.updateReport(ReportService.author, ReportService.name, saveData, ''))
 				.then(() => {
-					ReportService.lastEditedTime = Date.now();
-					scope.$apply();
+					const lastEditedEl = document.querySelector('.lastEdited');
+					lastEditedEl.classList.remove('lastEditedAnimating');
+					void lastEditedEl.offsetWidth;
+					lastEditedEl.classList.add('lastEditedAnimating');
 				})
 				.catch(e => {
 					ErrorService.logError(e, `Could not save the report.`);
diff --git a/beat/web/reports/static/reports/app/services/reportService.js b/beat/web/reports/static/reports/app/services/reportService.js
index 1dd40c919..67c8802d7 100644
--- a/beat/web/reports/static/reports/app/services/reportService.js
+++ b/beat/web/reports/static/reports/app/services/reportService.js
@@ -35,7 +35,6 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF
 	rs.number = undefined;
 	rs.author = undefined;
 	rs.name = undefined;
-	rs.lastEditedTime = 0;
 
 	rs.plotters = [];
 	rs.defaultPlotters = [];
diff --git a/beat/web/reports/static/reports/css/style.css b/beat/web/reports/static/reports/css/style.css
index 8bbdc3678..8ced0afd2 100644
--- a/beat/web/reports/static/reports/css/style.css
+++ b/beat/web/reports/static/reports/css/style.css
@@ -215,3 +215,21 @@ div.report_commands div.report_buttons_bloc .publish_report:hover
     margin-left: 20px;
     margin-bottom: 0;
 }
+
+.lastEdited {
+}
+
+.lastEditedAnimating {
+	animation-duration: 3s;
+	animation-name: reportSaved;
+}
+
+@keyframes reportSaved {
+	from {
+		background-color: #dff0d8;
+	}
+
+	to {
+		background-color: white;
+	}
+}
diff --git a/beat/web/reports/templates/reports/report.html b/beat/web/reports/templates/reports/report.html
index bdaebcf58..a5ec574f2 100644
--- a/beat/web/reports/templates/reports/report.html
+++ b/beat/web/reports/templates/reports/report.html
@@ -42,6 +42,7 @@
     <link rel="stylesheet" href="{% fingerprint "chosen-bootstrap/chosen.bootstrap.min.css" %}" type="text/css" media="screen" />
     <link rel="stylesheet" href="{% fingerprint "datatables/media/css/dataTables.bootstrap.min.css" %}" type="text/css" media="screen" />
     <link rel="stylesheet" href="{% fingerprint "jquery-ui/themes/base/minified/jquery-ui.min.css" %}" type="text/css" media="screen" />
+    <link rel="stylesheet" href="{% fingerprint "reports/css/style.css" %}" type="text/css" media="screen" />
     {% code_editor_css %}
 {% endblock %}
 
@@ -102,7 +103,6 @@
     <script src="{% fingerprint "reports/app/directives/save.js" %}" type="text/javascript" charset="utf-8"></script>
     <script src="{% fingerprint "reports/app/directives/error.js" %}" type="text/javascript" charset="utf-8"></script>
     <script src="{% fingerprint "reports/app/directives/experimentsTable.js" %}" type="text/javascript" charset="utf-8"></script>
-    <script src="{% fingerprint "reports/app/directives/lastEdited.js" %}" type="text/javascript" charset="utf-8"></script>
     <script src="{% fingerprint "reports/app/directives/editableLabel.js" %}" type="text/javascript" charset="utf-8"></script>
     <script src="{% fingerprint "reports/app/directives/panelExperiments.js" %}" type="text/javascript" charset="utf-8"></script>
     <script src="{% fingerprint "reports/app/directives/panelContainer.js" %}" type="text/javascript" charset="utf-8"></script>
@@ -151,7 +151,7 @@
 	<div class="row">
 		<div class="col-sm-12">
 
-			<p class="bs-callout bs-callout-{% if status == 'Editable' %}danger{% elif status == 'Locked' %}warning{% else %}info{% endif %}">
+			<p class="bs-callout bs-callout-{% if status == 'Editable' %}danger{% elif status == 'Locked' %}warning{% else %}info{% endif %} lastEdited">
 
 				{% if report.short_description %}
 				<i class="fa fa-file-text"></i> {{ report.short_description }}<br/>
@@ -167,7 +167,8 @@
 				<i class="fa fa-calendar-o"></i> Created: <strong>{{ report.creation_date|naturaltime }}</strong><br/>
 				{% endif %}
 				{% if report.last_edited_date != None and not report.publication_date %}
-				<i class="fa fa-calendar-o"></i> <last-edited init-str='{{ report.last_edited_date|naturaltime }}'></last-edited><br/>
+
+				<i class="fa fa-calendar-o"></i> Last Edited: <strong>{{ report.last_edited_date|naturaltime }}</strong><br/>
 				{% endif %}
 
 				{% if status == 'Editable' %}
-- 
GitLab