diff --git a/controllers/preview-pane.js b/controllers/preview-pane.js new file mode 100644 index 000000000..b8d4115f5 --- /dev/null +++ b/controllers/preview-pane.js @@ -0,0 +1,56 @@ +const dom = require('@nymag/dom'), + _ = require('lodash'), + previewSizes = { + small: { w: 375, h: 660 }, + medium: { w: 768, h: 1024 }, + large: { w: 1024, h: 768 } + }; + +module.exports = function () { + function Constructor(el) { + // share elements + this.link = dom.find(el, '.share-input'); + this.button = dom.find(el, '.share-copy'); + } + + Constructor.prototype = { + events: { + '.preview-link click': 'onPreview', + '.share-copy click': 'onCopy', + }, + + onPreview: function (e) { + var link = e.currentTarget, + url = link.getAttribute('href'), + size = _.find(Object.keys(previewSizes), (s) => link.classList.contains(s)); + + e.preventDefault(); + window.open(url, `Preview${size}`, `resizable=yes,scrollbars=yes,width=${previewSizes[size].w},height=${previewSizes[size].h}`); + }, + + onCopy: function () { + var link = this.link, + button = this.button, + success; + + try { + link.select(); + success = document.execCommand('copy'); + + if (success) { + button.classList.remove('error'); + button.classList.add('success'); + } else { + button.classList.remove('success'); + button.classList.add('error'); + } + } catch (e) { + // some browsers can't do this. + button.classList.remove('success'); + button.classList.add('error'); + console.error(e.message, e.stack); + } + } + }; + return Constructor; +}; diff --git a/media/copy.svg b/media/copy.svg new file mode 100644 index 000000000..ae23b1f32 --- /dev/null +++ b/media/copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/media/preview-large.svg b/media/preview-large.svg new file mode 100644 index 000000000..1f1c3d47e --- /dev/null +++ b/media/preview-large.svg @@ -0,0 +1,3 @@ + + + diff --git a/media/preview-medium.svg b/media/preview-medium.svg new file mode 100644 index 000000000..52d45d588 --- /dev/null +++ b/media/preview-medium.svg @@ -0,0 +1,3 @@ + + + diff --git a/media/preview-small.svg b/media/preview-small.svg new file mode 100644 index 000000000..ac54be792 --- /dev/null +++ b/media/preview-small.svg @@ -0,0 +1,3 @@ + + + diff --git a/services/pane.js b/services/pane.js index e2fbb25c9..01edbfc10 100644 --- a/services/pane.js +++ b/services/pane.js @@ -13,6 +13,7 @@ var _ = require('lodash'), paneController = require('../controllers/pane'), filterableList = require('./filterable-list'), publishPaneController = require('../controllers/publish-pane'), + previewController = require('../controllers/preview-pane'), references = require('./references'), addComponent = require('./components/add-component'), select = require('./components/select'), @@ -468,27 +469,31 @@ function addPreview(preview) { } /** - * open preview dialog pane + * open preview + share pane + * @returns {Element} */ function openPreview() { - var header = 'Preview Link', - innerEl = document.createDocumentFragment(), - previewUrl = edit.getPageUrl(), - pageActionsSubTemplate = tpl.get('.preview-actions-template'), - previewInput; - - if (pageActionsSubTemplate) { - previewInput = dom.find(pageActionsSubTemplate, '.preview-input'); - } + var pageUrl = edit.getPageUrl(), + previewHeader = 'Preview', + previewContent = tpl.get('.preview-actions-template'), + shareHeader = 'Shareable Link', + shareContent = tpl.get('.share-actions-template'), + el; + + // set the page url into the responsive preview items + _.each(dom.findAll(previewContent, 'a'), function (link) { + link.setAttribute('href', pageUrl); + }); - if (previewInput) { - previewInput.setAttribute('value', previewUrl); - } + // set the page url into the share tab + dom.find(shareContent, '.share-input').setAttribute('value', pageUrl); - // append actions to the doc fragment - innerEl.appendChild(pageActionsSubTemplate); - // create the root pane element - open([{header: header, content: innerEl}]); + el = open([{ header: previewHeader, content: previewContent }, { header: shareHeader, content: shareContent }]); + + // init controller + ds.controller('preview-pane', previewController); + ds.get('preview-pane', el); + return el; } /** diff --git a/services/pane.test.js b/services/pane.test.js index d92804923..aa5c34bf8 100644 --- a/services/pane.test.js +++ b/services/pane.test.js @@ -56,10 +56,36 @@ function stubCustomUrlTemplate() { } function stubPreviewActionsTemplate() { - return dom.create(`
- + return dom.create(``); +} + +function stubShareActionsTemplate() { + return dom.create(`
Share the link below to preview the latest version of this page.
+
+ +
`); } @@ -105,6 +131,7 @@ describe(dirname, function () { getTemplate.withArgs('.publish-messages-template').returns(stubMessageTemplate()); getTemplate.withArgs('.publish-actions-template').returns(stubPublishTemplate()); getTemplate.withArgs('.preview-actions-template').returns(stubPreviewActionsTemplate()); + getTemplate.withArgs('.share-actions-template').returns(stubShareActionsTemplate()); getTemplate.withArgs('.publish-error-message-template').returns(dom.create('
ERROR MESSAGE
')); getTemplate.withArgs('.publish-warning-message-template').returns(dom.create('
WARNING MESSAGE
')); getTemplate.withArgs('.publish-errors-template').returns(stubErrorsTemplate()); @@ -362,7 +389,8 @@ describe(dirname, function () { it('opens a preview pane', function () { lib.close(); fn(); - expect(document.querySelector('#pane-tab-1').innerHTML).to.equal('Preview Link'); + expect(document.querySelector('#pane-tab-1').innerHTML).to.equal('Preview'); + expect(document.querySelector('#pane-tab-2').innerHTML).to.equal('Shareable Link'); expect(document.querySelectorAll('.pane-inner input').length).to.equal(1); }); }); diff --git a/styleguide/pane.scss b/styleguide/pane.scss index a98a3e85a..ee1fe9bbe 100644 --- a/styleguide/pane.scss +++ b/styleguide/pane.scss @@ -452,7 +452,63 @@ $schedule-item-width: calc(50% - 8px); padding-top: 20px; } -/* preview pane */ +/* preview / share pane */ + +.kiln-toolbar-pane .preview-actions { + list-style: none; + margin: -20px -20px 0; + padding: 0; + position: relative; + width: calc(100% + 40px); +} + +.kiln-toolbar-pane .preview-item { + border-bottom: 1px solid $grey; + margin: 0; + padding: 0 20px; + width: 100%; +} + +.kiln-toolbar-pane .preview-link { + align-items: center; + cursor: pointer; + display: flex; + justify-content: flex-start; + line-height: 16px; + list-style: none; + margin: 0; + text-decoration: none; + width: 100%; + + &:hover, + &:active, + &:visited { + text-decoration: none; + } +} + +.kiln-toolbar-pane .preview-link-size { + @include icon-button($black-75, 22px); + + flex: 0 0 auto; + margin-right: 10px; + padding: 0; +} + +.kiln-toolbar-pane .preview-link-text { + @include primary-text(); + + flex: 1 0 auto; + padding: 15px 0; +} + +.kiln-toolbar-pane .preview-link-icon { + @include icon-button($black-50, 18px); + + flex: 0 0 auto; + margin-left: 5px; + padding: 0; +} .kiln-toolbar-pane .info-message { @include primary-text(); @@ -461,18 +517,67 @@ $schedule-item-width: calc(50% - 8px); padding: 0 0 20px; } -.kiln-toolbar-pane .preview-actions { +.kiln-toolbar-pane .share-actions { + display: flex; width: 100%; } -.kiln-toolbar-pane .preview-input { +.kiln-toolbar-pane .share-input { @include input(); cursor: initial; + flex: 0 1 auto; margin: 0; padding: 8px 10px 7px; } +.kiln-toolbar-pane .share-copy { + @include button-outlined($black-25); + + border-radius: 0; + flex: 0 0 auto; + height: 36px; // bump up the height to match input + margin: 0 0 0 -1px; // cover the input border + position: relative; + + &:before, + &:after { + @include secondary-text(); + + opacity: 0; + position: absolute; + right: 0; + top: calc(100% + 8px); + transition: opacity 300ms ease-out; + white-space: nowrap; + } + + // :before is the success message, :after is the error + // this allows us to fade them in (setting the content with the class messes up the animation) + &:before { + color: $blue; + content: 'Copied to clipboard!'; + } + + &:after { + color: $red; + content: 'Cannot copy link'; + } + + &.success:before { + opacity: 1; + } + + &.error:after { + opacity: 1; + } + + svg { + height: 20px; + width: 18px; + } +} + /* new page pane */ .add-page-form { diff --git a/template.nunjucks b/template.nunjucks index 0828fca4a..0bf0d3b80 100644 --- a/template.nunjucks +++ b/template.nunjucks @@ -138,13 +138,39 @@
- {# preview link #} + {# preview items #} + + {# share link #} +