From ff4a49d59b3423856f2ccd8ef9461e3368d69707 Mon Sep 17 00:00:00 2001 From: "Ryan P.C. McQuen" Date: Thu, 18 Jan 2018 08:32:37 -0800 Subject: [PATCH 1/9] Fix Org mode regex. More details here: https://github.com/mickael-kerjean/nuage/pull/16 --- www/code/orgmode.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/www/code/orgmode.js b/www/code/orgmode.js index 09e19966b..3377ebb15 100644 --- a/www/code/orgmode.js +++ b/www/code/orgmode.js @@ -7,12 +7,12 @@ define([ CodeMirror.defineSimpleMode("orgmode", { start: [ {regex: /^(^\*{1,6}\s)(TODO|DOING|WAITING|NEXT){0,1}(CANCELLED|CANCEL|DEFERRED|DONE|REJECTED|STOP|STOPPED){0,1}(.*)$/, token: ["header org-level-star", "header org-todo", "header org-done", "header"]}, - {regex: /(^\+[^\/]*\+)/, token: ["strikethrough"]}, - {regex: /(^\*[^\/]*\*)/, token: ["strong"]}, - {regex: /(^\/[^\/]*\/)/, token: ["em"]}, - {regex: /(^\_[^\/]*\_)/, token: ["link"]}, - {regex: /(^\~[^\/]*\~)/, token: ["comment"]}, - {regex: /(^\=[^\/]*\=)/, token: ["comment"]}, + {regex: /(\+[^\+]+\+)/, token: ["strikethrough"]}, + {regex: /(\*[^\*]+\*)/, token: ["strong"]}, + {regex: /(\/[^\/]+\/)/, token: ["em"]}, + {regex: /(\_[^\_]+\_)/, token: ["link"]}, + {regex: /(\~[^\~]+\~)/, token: ["comment"]}, + {regex: /(\=[^\=]+\=)/, token: ["comment"]}, {regex: /\[\[[^\[\]]*\]\[[^\[\]]*\]\]/, token: "url"}, // links {regex: /\[[xX\s]?\]/, token: 'qualifier'}, // checkbox {regex: /\#\+BEGIN_[A-Z]*/, token: "comment", next: "env"}, // comments From 2e436f16c94aa5cfb7ba69239d7acd194866eb02 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 19 Jan 2018 17:03:58 +0100 Subject: [PATCH 2/9] Refactor context menu in drive --- www/common/userObject.js | 1 - www/drive/inner.html | 44 --- www/drive/inner.js | 658 +++++++++++++++++++-------------------- 3 files changed, 323 insertions(+), 380 deletions(-) diff --git a/www/common/userObject.js b/www/common/userObject.js index 300098412..ecead9f2b 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -571,7 +571,6 @@ define([ // RENAME exp.rename = function (path, newName, cb) { if (sframeChan) { - console.log(path, newName); return void sframeChan.query("Q_DRIVE_USEROBJECT", { cmd: "rename", data: { diff --git a/www/drive/inner.html b/www/drive/inner.html index 93d4688ef..463619753 100644 --- a/www/drive/inner.html +++ b/www/drive/inner.html @@ -18,50 +18,6 @@
- - - - - diff --git a/www/drive/inner.js b/www/drive/inner.js index aaf26245c..b2a1a774b 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -11,6 +11,7 @@ define([ '/bower_components/nthen/index.js', '/common/sframe-common.js', '/common/common-realtime.js', + '/common/hyperscript.js', '/common/userObject.js', '/customize/application_config.js', '/bower_components/chainpad-listmap/chainpad-listmap.js', @@ -32,6 +33,7 @@ define([ nThen, SFCommon, CommonRealtime, + h, FO, AppConfig, Listmap, @@ -155,19 +157,30 @@ define([ }; // Icons + var faFolder = 'fa-folder'; + var faFolderOpen = 'fa-folder-open'; + var faReadOnly = 'fa-eye'; + var faRename = 'fa-pencil'; + var faTrash = 'fa-trash'; + var faDelete = 'fa-eraser'; + var faProperties = 'fa-database'; + var faTags = 'fa-hashtag'; + var faEmpty = 'fa-trash-o'; + var faRestore = 'fa-repeat'; + var faShowParent = 'fa-location-arrow'; var $folderIcon = $('', { - "class": "fa fa-folder cp-app-drive-icon-folder cp-app-drive-content-icon" + "class": faFolder + " fa cp-app-drive-icon-folder cp-app-drive-content-icon" }); //var $folderIcon = $('', {src: "/customize/images/icons/folder.svg", "class": "folder icon"}); var $folderEmptyIcon = $folderIcon.clone(); - var $folderOpenedIcon = $('', {"class": "fa fa-folder-open cp-app-drive-icon-folder"}); + var $folderOpenedIcon = $('', {"class": faFolderOpen + " fa cp-app-drive-icon-folder"}); //var $folderOpenedIcon = $('', {src: "/customize/images/icons/folderOpen.svg", "class": "folder icon"}); var $folderOpenedEmptyIcon = $folderOpenedIcon.clone(); //var $upIcon = $('', {"class": "fa fa-arrow-circle-up"}); var $unsortedIcon = $('', {"class": "fa fa-files-o"}); var $templateIcon = $('', {"class": "fa fa-cubes"}); var $recentIcon = $('', {"class": "fa fa-clock-o"}); - var $trashIcon = $('', {"class": "fa fa-trash"}); + var $trashIcon = $('', {"class": "fa " + faTrash}); var $trashEmptyIcon = $('', {"class": "fa fa-trash-o"}); //var $collapseIcon = $('', {"class": "fa fa-minus-square-o cp-app-drive-icon-expcol"}); var $expandIcon = $('', {"class": "fa fa-plus-square-o cp-app-drive-icon-expcol"}); @@ -181,7 +194,7 @@ define([ var $searchIcon = $('', {"class": "fa fa-search cp-app-drive-tree-search-con"}); var $addIcon = $('', {"class": "fa fa-plus"}); var $renamedIcon = $('', {"class": "fa fa-flag"}); - var $readonlyIcon = $('', {"class": "fa fa-eye"}); + var $readonlyIcon = $('', {"class": "fa " + faReadOnly}); var $ownedIcon = $('', {"class": "fa fa-id-card-o"}); var $ownerIcon = $('', {"class": "fa fa-id-card"}); @@ -200,6 +213,91 @@ define([ }); }; + var createContextMenu = function () { + var menu = h('div.cp-app-drive-context.dropdown.cp-unselectable', [ + h('ul.dropdown-menu', { + 'role': 'menu', + 'aria-labelledby': 'dropdownMenu', + 'style': 'display:block;position:static;margin-bottom:5px;' + }, [ + h('li', h('a.cp-app-drive-context-open.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faFolderOpen, + }, Messages.fc_open)), + h('li', h('a.cp-app-drive-context-openro.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faReadOnly, + }, Messages.fc_open_ro)), + h('li', h('a.cp-app-drive-context-openparent.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faShowParent, + }, Messages.fm_openParent)), + h('li', h('a.cp-app-drive-context-newfolder.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faFolder, + }, Messages.fc_newfolder)), + h('li', h('a.cp-app-drive-context-hashtag.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faTags, + }, Messages.fc_hashtag)), + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + 'tabindex': '-1', + 'data-icon': AppConfig.applicationsIcon.pad, + 'data-type': 'pad' + }, Messages.button_newpad)), + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + 'tabindex': '-1', + 'data-icon': AppConfig.applicationsIcon.code, + 'data-type': 'code' + }, Messages.button_newcode)), + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + 'tabindex': '-1', + 'data-icon': AppConfig.applicationsIcon.slide, + 'data-type': 'slide' + }, Messages.button_newslide)), + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + 'tabindex': '-1', + 'data-icon': AppConfig.applicationsIcon.poll, + 'data-type': 'poll' + }, Messages.button_newpoll)), + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + 'tabindex': '-1', + 'data-icon': AppConfig.applicationsIcon.whiteboard, + 'data-type': 'whiteboard' + }, Messages.button_newwhiteboard)), + h('li', h('a.cp-app-drive-context-empty.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faEmpty, + }, Messages.fc_empty)), + h('li', h('a.cp-app-drive-context-restore.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faRestore, + }, Messages.fc_restore)), + h('li', h('a.cp-app-drive-context-rename.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faRename, + }, Messages.fc_rename)), + h('li', h('a.cp-app-drive-context-delete.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faTrash, + }, Messages.fc_delete)), + h('li', h('a.cp-app-drive-context-deleteowned.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faDelete, + }, Messages.fc_delete_owned)), + h('li', h('a.cp-app-drive-context-remove.dropdown-item.cp-app-drive-context-editable', { + 'tabindex': '-1', + 'data-icon': faDelete, + }, Messages.fc_remove)), + h('li', h('a.cp-app-drive-context-properties.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faProperties, + }, Messages.fc_prop)), + ]) + ]); + return $(menu); + }; + var andThen = function (common, proxy) { var files = proxy.drive; var metadataMgr = common.getMetadataMgr(); @@ -227,7 +325,8 @@ define([ var $content = APP.$content = $("#cp-app-drive-content"); var $appContainer = $(".cp-app-drive-container"); var $driveToolbar = $("#cp-app-drive-toolbar"); - var $contextMenu = $("#cp-app-drive-context-tree"); + var $contextMenu = createContextMenu().appendTo($appContainer); + var $contentContextMenu = $("#cp-app-drive-context-content"); var $defaultContextMenu = $("#cp-app-drive-context-default"); var $trashTreeContextMenu = $("#cp-app-drive-context-trashtree"); @@ -638,68 +737,112 @@ define([ },0); }; - var filterContextMenu = function ($menu, paths) { - //var path = $element.data('path'); + var filterContextMenu = function (type, paths) { if (!paths || paths.length === 0) { logError('no paths'); } - var hide = []; - var hasFolder = false; - paths.forEach(function (p) { - var path = p.path; - var $element = p.element; - if (path.length === 1) { - // Can't rename or delete root elements - hide.push($menu.find('a.cp-app-drive-context-rename')); - hide.push($menu.find('a.cp-app-drive-context-delete')); - } - if (!APP.editable) { - hide.push($menu.find('a.cp-app-drive-context-editable')); - } - if (!isOwnDrive()) { - hide.push($menu.find('a.cp-app-drive-context-own')); - } - if (!$element.is('.cp-app-drive-element-owned')) { - hide.push($menu.find('a.cp-app-drive-context-deleteowned')); - } - if ($element.is('.cp-app-drive-element-notrash')) { - hide.push($menu.find('a.cp-app-drive-context-delete')); - } - if ($element.is('.cp-app-drive-element-file')) { - // No folder in files - hide.push($menu.find('a.cp-app-drive-context-newfolder')); - if ($element.is('.cp-app-drive-element-readonly')) { - // Keep only open readonly - hide.push($menu.find('a.cp-app-drive-context-open')); - } else if ($element.is('.cp-app-drive-element-noreadonly')) { - // Keep only open readonly - hide.push($menu.find('a.cp-app-drive-context-openro')); + $contextMenu.find('li').hide(); + + var show = []; + var filter; + + if (type === "content") { + filter = function ($el, className) { + if (className === 'newfolder') { return; } + return AppConfig.availablePadTypes.indexOf($el.attr('data-type')) === -1; + }; + } else { + // In case of multiple selection, we must hide the option if at least one element + // is not compatible + var containsFolder = false; + var hide = []; + paths.forEach(function (p) { + var path = p.path; + var $element = p.element; + if (path.length === 1) { + // Can't rename or delete root elements + hide.push('delete'); + hide.push('rename'); } - } else { - if (hasFolder) { - // More than 1 folder selected: cannot create a new subfolder - hide.push($menu.find('a.cp-app-drive-context-newfolder')); + if (!$element.is('.cp-app-drive-element-owned')) { + hide.push('deleteowned'); + } + if ($element.is('.cp-app-drive-element-notrash')) { + // We can't delete elements in virtual categories + hide.push('delete'); + } else { + // We can only open parent in virtual categories + hide.push('openparent'); + } + if ($element.is('.cp-app-drive-element-file')) { + // No folder in files + hide.push('newfolder'); + if ($element.is('.cp-app-drive-element-readonly')) { + hide.push('open'); // Remove open 'edit' mode + } else if ($element.is('.cp-app-drive-element-noreadonly')) { + hide.push('openro'); // Remove open 'view' mode + } + } else { // it's a folder + if (containsFolder) { + // More than 1 folder selected: cannot create a new subfolder + hide.push('newfolder'); + } + containsFolder = true; + hide.push('openro'); + hide.push('properties'); + hide.push('hashtag'); + } + // If we're in the trash, hide restore and properties for non-root elements + if (type === "trash" && path && path.length > 4) { + hide.push('restore'); + hide.push('properties'); } - hasFolder = true; - hide.push($menu.find('a.cp-app-drive-context-openro')); - hide.push($menu.find('a.cp-app-drive-context-properties')); - hide.push($menu.find('a.cp-app-drive-context-hashtag')); + }); + if (paths.length > 1) { + hide.push('restore'); + hide.push('properties'); + hide.push('rename'); + hide.push('openparent'); } - // If we're in the trash, hide restore and properties for non-root elements - if ($menu.find('a.cp-app-drive-context-restore').length && path && path.length > 4) { - hide.push($menu.find('a.cp-app-drive-context-restore')); - hide.push($menu.find('a.cp-app-drive-context-properties')); + if (containsFolder && paths.length > 1) { + // Cannot open multiple folders + hide.push('open'); } - }); - if (paths.length > 1) { - hide.push($menu.find('a.cp-app-drive-context-restore')); - hide.push($menu.find('a.cp-app-drive-context-properties')); - hide.push($menu.find('a.cp-app-drive-context-rename')); + + filter = function ($el, className) { + if (hide.indexOf(className) !== -1) { return true; } + }; } - if (hasFolder && paths.length > 1) { - // Cannot open multiple folders - hide.push($menu.find('a.cp-app-drive-context-open')); + + switch(type) { + case 'content': + show = ['newfolder', 'newdoc']; + break; + case 'tree': + show = ['open', 'openro', 'rename', 'delete', 'deleteowned', 'newfolder', + 'properties', 'hashtag']; + break; + case 'default': + show = ['open', 'openro', 'openparent', 'delete', 'deleteowned', 'properties', 'hashtag']; + break; + case 'trashtree': { + show = ['empty']; + break; + } + case 'trash': { + show = ['remove', 'restore', 'properties']; + } } - return hide; + + var filtered = []; + show.forEach(function (className) { + var $el = $contextMenu.find('.cp-app-drive-context-' + className); + if (!APP.editable && $el.is('.cp-app-drive-context-editable')) { return; } + if (!isOwnDrive && $el.is('.cp-app-drive-context-own')) { return; } + if (filter($el, className)) { return; } + $el.parent('li').show(); + filtered.push('.cp-app-drive-context-' + className); + }); + return filtered; }; var getSelectedPaths = function ($element) { @@ -763,16 +906,13 @@ define([ $container.html(''); var $element = $li.length === 1 ? $li : $($li[0]); var paths = getSelectedPaths($element); - var $menu = $element.data('context'); - if (!$menu) { return; } + var menuType = $element.data('context'); + if (!menuType) { return; } //var actions = []; - var $actions = $menu.find('a'); - var toHide = filterContextMenu($menu, paths); + var toShow = filterContextMenu(menuType, paths); + var $actions = $contextMenu.find('a'); $actions = $actions.filter(function (i, el) { - for (var j = 0; j < toHide.length; j++) { - if ($(el).is(toHide[j])) { return false; } - } - return true; + return toShow.some(function (className) { return $(el).is(className); }); }); $actions.each(function (i, el) { var $a = $('