diff --git a/capsule-prototype/index.html b/capsule-prototype/index.html index 8caea838f292055c6eb52b4b1c8e6fc9cab53aad..4d5a2759effb4d67c6e9bed8cada2cd46cb4cdb8 100644 --- a/capsule-prototype/index.html +++ b/capsule-prototype/index.html @@ -25,6 +25,8 @@ <script language="javascript" type='text/javascript' src='../shared/js/libs/sha1.js'></script> <script language="javascript" type='text/javascript' src='../shared/js/libs/fastdom.js'></script> <script language="javascript" type='text/javascript' src='../shared/js/libs/moment-with-langs.min.js'></script> + <script language="javascript" type="text/javascript" src='../shared/js/shared.js'></script> + <script language="javascript" type="text/javascript" src='../shared/js/MosaicPanelWidget.js'></script> <script language="javascript" type='text/javascript' src="../shared/php/rekallApp.js.php"></script> diff --git a/capsule-prototype/js/MosaicPanelWidget.js b/capsule-prototype/js/MosaicPanelWidget.js new file mode 100644 index 0000000000000000000000000000000000000000..e4382afd524d587f274c1c0ded421f6500035709 --- /dev/null +++ b/capsule-prototype/js/MosaicPanelWidget.js @@ -0,0 +1,164 @@ +function MosaicPanelWidget(opts){ + + const defaultOptions = { + htmlElement: $('#mosaic_tab'), + rekall: window.app.rekall.Rekall('rekall'), + getTagGradientColor: function(tag) { + var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera) + var isFirefox = typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ + var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; // At least Safari 3+: "[object HTMLElementConstructor]" + var isChrome = !!window.chrome && !isOpera; // Chrome 1+ + var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6 + + if(isOpera) { + return "-o-linear-gradient(right bottom, rgba(20,46,51,1) 0%, "+tag.color+" 100%)"; + } + if(isFirefox) { + return "-moz-linear-gradient(right bottom, rgba(20,46,51,1) 0%, "+tag.color+" 100%)"; + } + if((isSafari)||(isChrome)){ + return "-webkit-linear-gradient(right bottom, rgba(20,46,51,1) 0%, "+tag.color+" 100%)"; + } + }, + getPreviewPath: function (tagOrDoc){ + Utils.getPreviewPath(tagOrDoc); + }, + isOpen: false + }; + + const localOptions = $.extend({}, defaultOptions, opts); + + const getUrl = function(tagOrDoc, path){ + if ('undefined' === typeof path) { + let [reg, type] = tagOrDoc.getMetadata("Rekall->Type").split('/'); + if (reg === 'rekall') { + if (type === 'marker') type = 'note'; + } + return "../shared/css/images/img-"+type+".png"; + } else { + return path; + } + } + + const createHtmlElementForTagOrDoc = function (tagOrDoc) { + let path = localOptions.getPreviewPath(tagOrDoc); + let name = tagOrDoc.getMetadata("Rekall->Name"); + let url = getUrl(tagOrDoc, path); + + let div=$('<div/>').addClass('mosaic_item').on('click', function() {tagOrDoc.openPopupEdit();}); + div.append($('<img/>').attr('src', url).attr('onerror', "this.src='../shared/css/images/img-document.png';")); + div.append($('<span/>').addClass('caption').text(name)); + div.attr('data-rekall-labels', ''); + div.attr('data-rekall-labels', tagOrDoc.getMetadata('Rekall->Labels')); + return div; + } + + const getFilterElement = function (text, color, callback, css_class) { + return $('<div/>') + .addClass('mosaic_filter_item') + .addClass(css_class) + .on('click', callback) + .css('background-color', color) + .append($('<h2/>').text(text)); + } + + const emptyPanel = function(){ + localOptions.htmlElement.html(''); + } + + const fillPanel = function(){ + let filterdiv = $('<div/>').addClass('mosaic_filter'); + filterdiv.append(getFilterElement( + 'Reset filters', + 'rgb(100,100,100)', + function () { + $('.mosaic_filter_item').removeClass('mosaic_filter_disabled'); + $('.mosaic_category').show(); + }, + 'mosaic_filter_item_all' + )); + localOptions.htmlElement.append(filterdiv); + let labels = new Set(); + // TODO is there a better way to iterate over tags or documents ? + for ( let [k, v] of Object.entries(localOptions.rekall.sortings.colors.categories)) { + let categoryName = localOptions.rekall.sortings.colors.getCategoryName(k) + let category = $('<div/>').addClass('mosaic_category').css('background', localOptions.getTagGradientColor(v)); + + let grid = $('<div/>').addClass('mosaic_category_grid'); + + category.append($('<h2/>').text(categoryName)); + category.append(grid); + + filterdiv.append(getFilterElement( + categoryName, + v.color,function() { + category.toggle(); + $(this).toggleClass('mosaic_filter_disabled'); + }, + '' + )); + + for (let i in v.tags){ + grid.append(createHtmlElementForTagOrDoc(v.tags[i])); + let current_labels = v.tags[i].getMetadata('Rekall->Labels'); + if (current_labels && current_labels != '') { + current_labels.split(';').forEach(l => {if (l != '') labels.add(l)}); + } + } + localOptions.htmlElement.append(category); + } + + labels.forEach(l => { + let button = $('<p/>').html(l); + button.my_state = undefined; + button.addClass('mosaic_label_filter'); + button.click(ev => { + if (typeof(ev.target.my_state) === 'undefined') ev.target.my_state = true; + else ev.target.my_state = !ev.target.my_state; + if (ev.target.my_state) $(ev.target).addClass('mosaic_label_filter_enabled'); + else $(ev.target).removeClass('mosaic_label_filter_enabled'); + let labels = new Set(); + $('.mosaic_label_filter').toArray().forEach(f => { + if (f.my_state == true) + labels.add(f.innerHTML); + }); + if (!labels.size) { + $('.mosaic_label_filter').toArray().forEach(f => { + f.my_state = undefined; + $(f).removeClass('mosaic_label_filter_enabled'); + }); + } + console.debug('filters: ', labels); + $('.mosaic_item').toArray().forEach(t => { + if (!labels.size || Array.from(labels).map(l => t.dataset.rekallLabels.indexOf(l) != -1).includes(true)) + $(t).show(); + else + $(t).hide(); + }); + }) + filterdiv.append(button); + }); + } + + return { + show: function(){ + if (localOptions.isOpen) + return; + + localOptions.rekall.timeline.pause(); + fillPanel(); + localOptions.htmlElement.show(); + localOptions.updateObserver = window.app.rekall.Rekall('pubSub').subscribe('popupEdit.updated', this.refresh) + }, + hide: function (){ + window.app.rekall.Rekall('pubSub').unsubscribe(localOptions.updateObserver); + localOptions.updateObserver = undefined; + localOptions.htmlElement.hide(); + emptyPanel(); + }, + refresh: function (){ + emptyPanel(); + fillPanel(); + } + }; +} \ No newline at end of file diff --git a/capsule-prototype/js/online-rekall/RekallApplication.js b/capsule-prototype/js/online-rekall/RekallApplication.js index c214d4e070efd711ed12dd41534e6798ff399253..24b763baff26059b8d84014aeb7e3be198ab3c86 100644 --- a/capsule-prototype/js/online-rekall/RekallApplication.js +++ b/capsule-prototype/js/online-rekall/RekallApplication.js @@ -8,7 +8,8 @@ 'videoPlayer', 'rekall', 'getUrl', - 'projectName' + 'projectName', + 'mosaicWidget' ]; let localOptions = {}; @@ -25,6 +26,14 @@ $.extend(localOptions, opts); } }, + mosaicWidget : function (){ + if (!arguments.length){ + return localOptions.MosaicWidget; + } + if ('object' === typeof arguments[0] && null !== arguments[0]) { + localOptions.MosaicWidget = arguments[0]; + } + }, openUrl: function () { if (!arguments) return; diff --git a/capsule-prototype/js/online-script.js b/capsule-prototype/js/online-script.js index 34d52382b1b0832faf8d114b7c12f38e1b0054b5..cd11dd403f800636188b851a8eab32e690761677 100644 --- a/capsule-prototype/js/online-script.js +++ b/capsule-prototype/js/online-script.js @@ -11,7 +11,8 @@ window.onload = function() { pubSub.subscribe('video', openVideo); pubSub.subscribe('open_paste_modal', openPasteModal); pubSub.subscribe('close_paste_modal', closePasteModal); - pubSub.subscribe('updated.project.name', onUpdatedProjectName) + pubSub.subscribe('updated.project.name', onUpdatedProjectName); + window.app.rekall.Rekall('mosaicWidget', new MosaicPanelWidget()) }; $(document).ready(function() { @@ -828,140 +829,19 @@ function closeEdit() { if(isPaused=="false") rekall.timeline.play(); $("#popupSpace").hide(); $("#popupEdit").hide(); + window.app.rekall.Rekall('pubSub').publish('popupEdit.updated', {}); } function openVideo() { - $('#mosaic_tab').hide(); - $('#video_tab').show(); - $('#left_menu_controls').show(); + window.app.rekall.Rekall('mosaicWidget').hide(); + $('#video_tab').show(); + $('#left_menu_controls').show(); } function openMosaic() { - function getMosaicItem(tagOrDoc) { - let path = Utils.getPreviewPath(tagOrDoc); - let name = tagOrDoc.getMetadata("Rekall->Name"); - let url =''; - if ('undefined' === typeof path) { - let [reg, type] = tagOrDoc.getMetadata("Rekall->Type").split('/'); - if (reg === 'rekall') { - if (type === 'marker') type = 'note'; - } - url = "../shared/css/images/img-"+type+".png"; - } else { - url = path; - } - let div=$('<div/>').addClass('mosaic_item').on('click', function() {tagOrDoc.openPopupEdit();}); - div.append($('<img/>').attr('src', url).attr('onerror', "this.src='../shared/css/images/img-document.png';")); - div.append($('<span/>').addClass('caption').text(name)); - div.attr('data-rekall-labels', ''); - div.attr('data-rekall-labels', tagOrDoc.getMetadata('Rekall->Labels')); - return div; - } - function getFilterElement(text, color, callback, css_class) { - return $('<div/>') - .addClass('mosaic_filter_item') - .addClass(css_class) - .on('click', callback) - .css('background-color', color) - .append($('<h2/>').text(text)); - } - - - rekall.timeline.pause(); - $('#mosaic_tab').show(); - $('#video_tab').hide(); - $('#left_menu_controls').hide(); - - let container = $('#mosaic_tab'); - container.html(''); - let filterdiv = $('<div/>').addClass('mosaic_filter'); - filterdiv.append(getFilterElement( - 'Reset filters', - 'rgb(100,100,100)', - function () { - $('.mosaic_filter_item').removeClass('mosaic_filter_disabled'); - $('.mosaic_category').show(); - }, - 'mosaic_filter_item_all' - )); - container.append(filterdiv); - var labels = new Set(); - // TODO is there a better way to iterate over tags or documents ? - for ( let [k, v] of Object.entries(rekall.sortings.colors.categories)) { - let categoryName = rekall.sortings.colors.getCategoryName(k) - let category = $('<div/>').addClass('mosaic_category').css('background', getTagGradientColor(v)); - - let grid = $('<div/>').addClass('mosaic_category_grid'); - - category.append($('<h2/>').text(categoryName)); - category.append(grid); - - filterdiv.append(getFilterElement( - categoryName, - v.color,function() { - category.toggle(); - $(this).toggleClass('mosaic_filter_disabled'); - }, - '' - )); - - for (let i in v.tags){ - grid.append(getMosaicItem(v.tags[i])); - var current_labels = v.tags[i].getMetadata('Rekall->Labels'); - if (current_labels && current_labels != '') { - current_labels.split(';').forEach(l => {if (l != '') labels.add(l)}); - } - } - container.append(category); - } - labels.forEach(l => { - var button = $('<p/>').html(l); - button.my_state = undefined; - button.addClass('mosaic_label_filter'); - button.click(ev => { - if (typeof(ev.target.my_state) === 'undefined') ev.target.my_state = true; - else ev.target.my_state = !ev.target.my_state; - if (ev.target.my_state) $(ev.target).addClass('mosaic_label_filter_enabled'); - else $(ev.target).removeClass('mosaic_label_filter_enabled'); - var labels = new Set(); - $('.mosaic_label_filter').toArray().forEach(f => { - if (f.my_state == true) - labels.add(f.innerHTML); - }); - if (!labels.size) { - $('.mosaic_label_filter').toArray().forEach(f => { - f.my_state = undefined; - $(f).removeClass('mosaic_label_filter_enabled'); - }); - } - console.debug('filters: ', labels); - $('.mosaic_item').toArray().forEach(t => { - if (!labels.size || Array.from(labels).map(l => t.dataset.rekallLabels.indexOf(l) != -1).includes(true)) - $(t).show(); - else - $(t).hide(); - }); - }) - filterdiv.append(button); - }); -} - -function getTagGradientColor(tag) { - var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera) - var isFirefox = typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ - var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; // At least Safari 3+: "[object HTMLElementConstructor]" - var isChrome = !!window.chrome && !isOpera; // Chrome 1+ - var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6 - - if(isOpera) { - return "-o-linear-gradient(right bottom, rgba(20,46,51,1) 0%, "+tag.color+" 100%)"; - } - if(isFirefox) { - return "-moz-linear-gradient(right bottom, rgba(20,46,51,1) 0%, "+tag.color+" 100%)"; - } - if((isSafari)||(isChrome)){ - return "-webkit-linear-gradient(right bottom, rgba(20,46,51,1) 0%, "+tag.color+" 100%)"; - } + $('#video_tab').hide(); + $('#left_menu_controls').hide(); + window.app.rekall.Rekall('mosaicWidget').show(); } function fillPopupEdit(tag) { @@ -1251,7 +1131,7 @@ function uploadFiles(files, additionnal_post_data={}) { formData.append("author", rekall_common.owner.author); formData.append("locationGps", rekall_common.owner.locationGps); formData.append("locationName", rekall_common.owner.locationName); - Object.keys(additionnal_post_data).forEach(k => formData.append(k, additionnal_post_data[k])); + Object.keys(additionnal_post_data).forEach(k => formData.append(k, additionnal_post_data[k])); if(formData != undefined) { filesToUpload.push({ diff --git a/capsule-prototype/js/shared.js b/capsule-prototype/js/shared.js new file mode 100644 index 0000000000000000000000000000000000000000..bb434ceb51e5245850616d856cc33b81429d2a50 --- /dev/null +++ b/capsule-prototype/js/shared.js @@ -0,0 +1,17 @@ +function getTagGradientColor(tag) { + var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera) + var isFirefox = typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ + var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; // At least Safari 3+: "[object HTMLElementConstructor]" + var isChrome = !!window.chrome && !isOpera; // Chrome 1+ + var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6 + + if (isOpera) { + return "-o-linear-gradient(right bottom, rgba(20,46,51,1) 0%, " + tag.color + " 100%)"; + } + if (isFirefox) { + return "-moz-linear-gradient(right bottom, rgba(20,46,51,1) 0%, " + tag.color + " 100%)"; + } + if ((isSafari) || (isChrome)) { + return "-webkit-linear-gradient(right bottom, rgba(20,46,51,1) 0%, " + tag.color + " 100%)"; + } +} \ No newline at end of file