diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 06f3ad58a..6ec3c615b 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -153,39 +153,46 @@ margin-bottom: @alertify_padding-base; margin: 0; overflow: auto; - .alertify-tabs { - .alertify-tabs-titles { + } + .alertify-tabs { + max-height: 100%; + display: flex; + flex-flow: column; + .alertify-tabs-titles { + height: 30px; + display: flex; + border-bottom: 1px solid @alertify-fore; + margin-bottom: 20px; + box-sizing: content-box; + span { + font-size: 20px; height: 30px; - display: flex; - border-bottom: 1px solid @alertify-fore; - margin-bottom: 20px; - box-sizing: content-box; - span { - font-size: 20px; - height: 30px; - line-height: 30px; - box-sizing: border-box; - padding: 0 15px; - border-left: 1px solid lighten(@alertify-base, 10%); - border-right: 1px solid lighten(@alertify-base, 10%); - cursor: pointer; - } - span.alertify-tabs-active { - background-color: @alertify-fore; - border-left: 1px solid @alertify-fore; - border-right: 1px solid @alertify-fore; - color: @alertify-base; - font-weight: bold; - cursor: default; - } + line-height: 30px; + box-sizing: border-box; + padding: 0 15px; + border-left: 1px solid lighten(@alertify-base, 10%); + border-right: 1px solid lighten(@alertify-base, 10%); + cursor: pointer; } - .alertify-tabs-contents { - & > div { - display: none; - } - & > div.alertify-tabs-content-active { - display: block; - } + span.alertify-tabs-active { + background-color: @alertify-fore; + border-left: 1px solid @alertify-fore; + border-right: 1px solid @alertify-fore; + color: @alertify-base; + font-weight: bold; + cursor: default; + } + } + .alertify-tabs-contents { + flex: 1; + min-height: 0; + & > div { + max-height: 100%; + display: none; + overflow: auto; + } + & > div.alertify-tabs-content-active { + display: block; } } } @@ -201,10 +208,17 @@ padding: @alertify_padding-base; } - input[type="checkbox"] { + input[type="checkbox"], input[type="radio"] { + width: auto; padding: 0; - margin: 0; margin-right: 0.5em; + margin-top: 1px; + margin-bottom: 5px; + vertical-align: middle; + & + label { + margin-bottom: 0; + margin-right: 2em; + } } nav { diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 178a922fb..5bdc47f43 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -789,9 +789,8 @@ width: 125px; text-align: center; } - .cp-toolbar-share-button button { + .cp-toolbar-share-button { width: 50px; - text-align: center; } } .cp-toolbar-rightside { diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 28c281c46..6a28b43ae 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -812,5 +812,18 @@ define(function () { out.creation_newPadModalDescription = "Cliquez sur un type de pad pour le créer. Vous pouvez cocher la case pour afficher l'écran de création de pads"; out.creation_newPadModalAdvanced = "Afficher l'écran de création de pads"; + // New share modal + out.share_linkCategory = "Partage"; + out.share_linkAccess = "Droits d'accès"; + out.share_linkEdit = "Édition"; + out.share_linkView = "Lecture-seule"; + out.share_linkOptions = "Options du lien"; + out.share_linkEmbed = "Mode intégration (barre d'outils cachée)"; + out.share_linkPresent = "Mode présentation (sections d'édition cachées)"; + out.share_linkOpen = "Ouvrir le lien"; + out.share_linkCopy = "Copier le lien"; + out.share_embedCategory = "Intégration"; + out.share_mediatagCopy = "Copier le mediatag"; + return out; }); diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index abece3af6..f554de85b 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -845,5 +845,19 @@ define(function () { out.creation_newPadModalDescription = "Click on a pad type to create it. You can check the box if you want to display the pad creation screen (for owned pad, expiration pad, etc.)."; out.creation_newPadModalAdvanced = "Display the pad creation screen"; + // New share modal + out.share_linkCategory = "Share link"; + out.share_linkAccess = "Access rights"; + out.share_linkEdit = "Edit"; + out.share_linkView = "View"; + out.share_linkOptions = "Link options"; + out.share_linkEmbed = "Embed mode (toolbar and userlist hidden)"; + out.share_linkPresent = "Present mode (editable sections hidden)"; + out.share_linkOpen = "Open in new tab"; + out.share_linkCopy = "Copy to clipboard"; + out.share_embedCategory = "Embed"; + out.share_mediatagCopy = "Copy mediatag to clipboard"; + + return out; }); diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 14cb3e53a..2ae963a71 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -55,6 +55,15 @@ define([ $(el || window).keydown(handler); return handler; }; + var customListenForKeys = function (keys, cb, el) { + if (!keys || typeof cb !== "function") { return; } + var handler = function (e) { + e.stopPropagation(); + if (keys.indexOf(e.which) !== -1) { cb(); } + }; + $(el || window).keydown(handler); + return handler; + }; var stopListening = UI.stopListening = function (handler) { if (!handler) { return; } // we don't want to stop all the 'keyup' listeners @@ -139,7 +148,7 @@ define([ var titles = []; tabs.forEach(function (tab) { if (!tab.content || !tab.title) { return; } - var content = tab.content; + var content = h('div.alertify-tabs-content', tab.content); var title = h('span.alertify-tabs-title', tab.title); $(title).click(function () { titles.forEach(function (t) { $(t).removeClass('alertify-tabs-active'); }); @@ -274,6 +283,70 @@ define([ return tagger; }; + dialog.customModal = function (msg, opt) { + var force = false; + if (typeof(opt) === 'object') { + force = opt.force || false; + } else if (typeof(opt) === 'boolean') { + force = opt; + } + if (typeof(opt) !== 'object') { + opt = {}; + } + + var message; + if (typeof(msg) === 'string') { + // sanitize + if (!force) { msg = Util.fixHTML(msg); } + message = dialog.message(); + message.innerHTML = msg; + } else { + message = dialog.message(msg); + } + + var close = Util.once(function (el) { + var $el = $(el).fadeOut(150, function () { + $el.remove(); + }); + }); + + var navs = []; + opt.buttons.forEach(function (b) { + if (!b.name || !b.onClick) { return; } + var button = h('button', { tabindex: '1' }, b.name); + $(button).click(function () { + b.onClick(); + close($(this).parents('.alertify').first()); + }); + if (b.keys && b.keys.length) { $(button).attr('data-keys', b.keys.join(',')); } + navs.push(button); + }); + var frame = h('div', [ + message, + dialog.nav(navs), + ]); + + if (opt.forefront) { $(frame).addClass('forefront'); } + return frame; + }; + UI.openCustomModal = function (content) { + var frame = dialog.frame([ + content + ]); + $(frame).find('button[data-keys]').each(function (i, el) { + var keys = $(el).attr('data-keys'); + customListenForKeys(keys, function () { + if (!$(el).is(':visible')) { return; } + $(el).click(); + }, frame); + }); + document.body.appendChild(frame); + $(frame).focus(); + setTimeout(function () { + Notifier.notify(); + }); + }; + UI.alert = function (msg, cb, opt) { var force = false; if (typeof(opt) === 'object') { diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index aad840259..2d999558e 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -9,13 +9,14 @@ define([ '/common/common-feedback.js', '/common/hyperscript.js', '/common/media-tag.js', + '/common/clipboard.js', '/customize/messages.js', '/customize/application_config.js', '/bower_components/nthen/index.js', 'css!/common/tippy.css', -], function ($, Config, Util, Hash, Language, UI, Constants, Feedback, h, MediaTag, Messages, - AppConfig, NThen) { +], function ($, Config, Util, Hash, Language, UI, Constants, Feedback, h, MediaTag, Clipboard, + Messages, AppConfig, NThen) { var UIElements = {}; // Configure MediaTags to use our local viewer @@ -226,6 +227,223 @@ define([ }); }; + UIElements.createShareModal = function (config) { + var origin = config.origin; + var pathname = config.pathname; + var hashes = config.hashes; + var common = config.common; + + // Share link tab + var link = h('div.cp-share-modal', [ + h('label', Messages.share_linkAccess), + h('br'), + h('input#cp-share-editable-true.cp-share-editable-value', { + type: 'radio', + name: 'cp-share-editable', + value: 1, + checked: 'checked' + }), + h('label', { 'for': 'cp-share-editable-true' }, Messages.share_linkEdit), + h('input#cp-share-editable-false.cp-share-editable-value', { + type: 'radio', + name: 'cp-share-editable', + value: 0 + }), + h('label', { 'for': 'cp-share-editable-false' }, Messages.share_linkView), + h('br'), + h('br'), + h('label', Messages.share_linkOptions), + h('br'), + h('input#cp-share-embed', { + type: 'checkbox', + name: 'cp-share-embed' + }), + h('label', { 'for': 'cp-share-embed' }, Messages.share_linkEmbed), + h('br'), + h('input#cp-share-present', { + type: 'checkbox', + name: 'cp-share-present' + }), + h('label', { 'for': 'cp-share-present' }, Messages.share_linkPresent), + h('br'), + h('br'), + UI.dialog.selectable('', { id: 'cp-share-link-preview' }) + ]); + if (!hashes.editHash) { + $(link).find('#cp-share-editable-false').attr('checked', true); + $(link).find('#cp-share-editable-true').attr('disabled', true); + } + var saveValue = function () { + var edit = $(link).find('#cp-share-editable-true').is(':checked'); + var embed = $(link).find('#cp-share-embed').is(':checked'); + var present = $(link).find('#cp-share-present').is(':checked'); + common.setAttribute(['general', 'share'], { + edit: edit, + embed: embed, + present: present + }); + }; + var getLinkValue = function () { + var edit = $(link).find('#cp-share-editable-true').is(':checked'); + var embed = $(link).find('#cp-share-embed').is(':checked'); + var present = $(link).find('#cp-share-present').is(':checked'); + + var hash = (edit && hashes.editHash) ? hashes.editHash : hashes.viewHash; + var href = origin + pathname + '#' + hash; + var parsed = Hash.parsePadUrl(href); + return origin + parsed.getUrl({embed: embed, present: present}); + }; + $(link).find('#cp-share-link-preview').val(getLinkValue()); + $(link).find('input[type="radio"], input[type="checkbox"]').on('change', function () { + $(link).find('#cp-share-link-preview').val(getLinkValue()); + }); + var linkButtons = [{ + name: Messages.share_linkCopy, + onClick: function () { + saveValue(); + var v = getLinkValue(); + var success = Clipboard.copy(v); + if (success) { UI.log(Messages.shareSuccess); } + } + }, { + name: Messages.share_linkOpen, + onClick: function () { + saveValue(); + var v = getLinkValue(); + window.open(v); + } + }, { + name: Messages.cancel, + onClick: function () {}, + keys: [27] + }]; + var frameLink = UI.dialog.customModal(link, {buttons: linkButtons}); + + // Embed tab + var getEmbedValue = function () { + var hash = hashes.viewHash || hashes.editHash; + var href = origin + pathname + '#' + hash; + var parsed = Hash.parsePadUrl(href); + var url = origin + parsed.getUrl({embed: true, present: true}); + return ''; + }; + var embed = h('div.cp-share-modal', [ + h('h3', Messages.viewEmbedTitle), + h('p', Messages.viewEmbedTag), + h('br'), + UI.dialog.selectable(getEmbedValue()) + ]); + var embedButtons = [{ + name: Messages.share_linkCopy, + onClick: function () { + var v = getEmbedValue(); + var success = Clipboard.copy(v); + if (success) { UI.log(Messages.shareSuccess); } + } + }, { + name: Messages.cancel, + onClick: function () {}, + keys: [27] + }]; + var frameEmbed = UI.dialog.customModal(embed, { buttons: embedButtons}); + + // Create modal + var tabs = UI.dialog.tabs([{ + title: Messages.share_linkCategory, + content: frameLink + }, { + title: Messages.share_embedCategory, + content: frameEmbed + }]); + if (typeof(AppConfig.customizeShareOptions) === 'function') { + Config.customizeShareOptions(hashes, tabs, { + type: 'DEFAULT', + origin: origin, + pathname: pathname + }); + } + common.getAttribute(['general', 'share'], function (err, val) { + val = val || {}; + if (val.edit === false) { + $(link).find('#cp-share-editable-false').attr('checked', true); + } + if (val.embed) { $(link).find('#cp-share-embed').attr('checked', true); } + if (val.present) { $(link).find('#cp-share-present').attr('checked', true); } + UI.openCustomModal(tabs); + }); + }; + UIElements.createFileShareModal = function (config) { + var origin = config.origin; + var pathname = config.pathname; + var hashes = config.hashes; + var common = config.common; + + if (!hashes.fileHash) { throw new Error("You must provide a file hash"); } + var url = origin + pathname + '#' + hashes.fileHash; + + + // Share link tab + var link = h('div.cp-share-modal', [ + UI.dialog.selectable('', { id: 'cp-share-link-preview' }) + ]); + var getLinkValue = function () { return url; }; + $(link).find('#cp-share-link-preview').val(getLinkValue()); + var linkButtons = [{ + name: Messages.share_linkCopy, + onClick: function () { + var v = getLinkValue(); + var success = Clipboard.copy(v); + if (success) { UI.log(Messages.shareSuccess); } + } + }, { + name: Messages.cancel, + onClick: function () {}, + keys: [27] + }]; + var frameLink = UI.dialog.customModal(link, {buttons: linkButtons}); + + // Embed tab + var embed = h('div.cp-share-modal', [ + h('h3', Messages.fileEmbedTitle), + h('p', Messages.fileEmbedScript), + h('br'), + UI.dialog.selectable(common.getMediatagScript()), + h('p', Messages.fileEmbedTag), + h('br'), + UI.dialog.selectable(common.getMediatagFromHref(url)), + ]); + var embedButtons = [{ + name: Messages.share_mediatagCopy, + onClick: function () { + var v = common.getMediatagFromHref(url); + var success = Clipboard.copy(v); + if (success) { UI.log(Messages.shareSuccess); } + } + }, { + name: Messages.cancel, + onClick: function () {}, + keys: [27] + }]; + var frameEmbed = UI.dialog.customModal(embed, { buttons: embedButtons}); + + // Create modal + var tabs = UI.dialog.tabs([{ + title: Messages.share_linkCategory, + content: frameLink + }, { + title: Messages.share_embedCategory, + content: frameEmbed + }]); + if (typeof(AppConfig.customizeShareOptions) === 'function') { + Config.customizeShareOptions(hashes, tabs, { + type: 'FILE', + origin: origin, + pathname: pathname + }); + } + UI.openCustomModal(tabs); + }; + UIElements.createButton = function (common, type, rightside, data, callback) { var AppConfig = common.getAppConfig(); var button; diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js index c8aa2f901..03cb9d7c1 100644 --- a/www/common/toolbar3.js +++ b/www/common/toolbar3.js @@ -7,8 +7,7 @@ define([ '/common/common-hash.js', '/common/common-feedback.js', '/customize/messages.js', - '/common/clipboard.js', -], function ($, Config, ApiConfig, UIElements, UI, Hash, Feedback, Messages, Clipboard) { +], function ($, Config, ApiConfig, UIElements, UI, Hash, Feedback, Messages) { var Common; var Bar = { @@ -27,9 +26,6 @@ define([ // Userlist var USERLIST_CLS = Bar.constants.userlist = "cp-toolbar-users"; - var EDITSHARE_CLS = Bar.constants.editShare = "cp-toolbar-share-edit"; - var VIEWSHARE_CLS = Bar.constants.viewShare = "cp-toolbar-share-view"; - var SHARE_CLS = Bar.constants.viewShare = "cp-toolbar-share"; // Top parts var USER_CLS = Bar.constants.userAdmin = "cp-toolbar-user"; @@ -441,124 +437,19 @@ define([ var origin = config.metadataMgr.getPrivateData().origin; var pathname = config.metadataMgr.getPrivateData().pathname; var hashes = metadataMgr.getPrivateData().availableHashes; - var readOnly = metadataMgr.getPrivateData().readOnly; - var $shareIcon = $('', {'class': 'fa fa-share-alt'}); - var options = []; - - if (hashes.editHash) { - options.push({ - tag: 'a', - attributes: {title: Messages.editShareTitle, 'class': 'cp-toolbar-share-edit-copy'}, - content: ' ' + Messages.editShare - }); - if (readOnly) { - // We're in view mode, display the "open editing link" button - options.push({ - tag: 'a', - attributes: { - title: Messages.editOpenTitle, - 'class': 'cp-toolbar-share-edit-open', - href: origin + pathname + '#' + hashes.editHash, - target: '_blank' - }, - content: ' ' + Messages.editOpen - }); - } - options.push({tag: 'hr'}); - } - if (hashes.viewHash) { - options.push({ - tag: 'a', - attributes: {title: Messages.viewShareTitle, 'class': 'cp-toolbar-share-view-copy'}, - content: ' ' + Messages.viewShare - }); - if (!readOnly) { - // We're in edit mode, display the "open readonly" button - options.push({ - tag: 'a', - attributes: { - title: Messages.viewOpenTitle, - 'class': 'cp-toolbar-share-view-open', - href: origin + pathname + '#' + hashes.viewHash, - target: '_blank' - }, - content: ' ' + Messages.viewOpen - }); - } - options.push({tag: 'hr'}); - options.push({ - tag: 'a', - attributes: { - title: Messages.viewEmbedTitle, - 'class': 'cp-toolbar-share-view-embed', - }, - content: ' ' + Messages.getEmbedCode - }); - } - if (typeof(Config.customizeShareOptions) === 'function') { - Config.customizeShareOptions(hashes, options, { - type: 'DEFAULT', + var $shareBlock = $('