diff --git a/beat/web/reports/static/reports/app/directives/lastEdited.js b/beat/web/reports/static/reports/app/directives/lastEdited.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f2c83b864450ca0c59465364c19bbb97dbfdc14
--- /dev/null
+++ b/beat/web/reports/static/reports/app/directives/lastEdited.js
@@ -0,0 +1,141 @@
+/*
+ * 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);
+				$timeout(() => $interval.cancel(id), fromSeconds(59));
+
+				return id;
+			};
+			const singleMinutesInterval = (t) => {
+				const id = $interval(updateCurrStr, before10m, 0, true, t, every1m);
+				$timeout(() => $interval.cancel(id), fromMinutes(9.9));
+
+				return id;
+			};
+			const tenMinutesInterval = (t) => {
+				const id = $interval(updateCurrStr, before1h, 0, true, t, every10m);
+				$timeout(() => $interval.cancel(id), fromMinutes(59));
+
+				return id;
+			};
+			const hourInterval = (t) => {
+				const id = $interval(updateCurrStr, after1h, 0, true, t, every1h);
+				$timeout(() => $interval.cancel(id), fromMinutes(61));
+
+				return id;
+			};
+
+			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 1ee131a3ed17ac8b7be8f96f25ccdd2464175c55..186e720b9dfce7c58e3d9e290e1d1a643a01fe89 100644
--- a/beat/web/reports/static/reports/app/directives/save.js
+++ b/beat/web/reports/static/reports/app/directives/save.js
@@ -44,8 +44,7 @@ angular.module('reportApp')
 				return reportFactory.removeExperiments(ExperimentsService.cachedDeletedExperiments)
 				.then(() => reportFactory.updateReport(ReportService.author, ReportService.name, saveData, ''))
 				.then(() => {
-					const lastUpdatedEl = document.querySelector('#last-edited-text');
-					lastUpdatedEl.innerHTML = 'Just now';
+					ReportService.lastEditedTime = Date.now();
 				})
 				.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 8490735909bde59b908d5518df70298d30727419..1dd40c91964468a18278f0554f180daf3c2629f5 100644
--- a/beat/web/reports/static/reports/app/services/reportService.js
+++ b/beat/web/reports/static/reports/app/services/reportService.js
@@ -35,6 +35,7 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF
 	rs.number = undefined;
 	rs.author = undefined;
 	rs.name = undefined;
+	rs.lastEditedTime = 0;
 
 	rs.plotters = [];
 	rs.defaultPlotters = [];
@@ -118,7 +119,6 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF
 			openSourceAlgs.length && openSourceAlgs.length > 0 ? data : undefined
 		)
 		.catch(error => {
-			console.error(`Failed to publish report: ${error}`);
 			throw error;
 		});
 		;
@@ -132,7 +132,6 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF
 			''
 		)
 		.catch(error => {
-			console.error(`Failed to lock report: ${error}`);
 			throw error;
 		});
 		;
diff --git a/beat/web/reports/templates/reports/report.html b/beat/web/reports/templates/reports/report.html
index 5a45d4284cbbe01c00c7474e8147b0fe7c46f4e2..8fad84ee4fe76f691400d5904dc2a9a6adb1a884 100644
--- a/beat/web/reports/templates/reports/report.html
+++ b/beat/web/reports/templates/reports/report.html
@@ -103,6 +103,7 @@
     <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>
 
     <!-- edit view -->
     {% if not report_number and report.get_status_display == 'Editable' and owner %}
@@ -175,7 +176,7 @@
 				<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: <strong id='last-edited-text'>{{ report.last_edited_date|naturaltime }}</strong><br/>
+				<i class="fa fa-calendar-o"></i> <last-edited init-str='{{ report.last_edited_date|naturaltime }}'></last-edited><br/>
 				{% endif %}
 
 				{% if status == 'Editable' %}