diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/components/boards/boardColors.styl | 415 | ||||
-rw-r--r-- | client/components/boards/boardsList.jade | 4 | ||||
-rw-r--r-- | client/components/boards/boardsList.js | 6 | ||||
-rw-r--r-- | client/components/boards/boardsList.styl | 16 | ||||
-rw-r--r-- | client/components/lists/list.js | 24 | ||||
-rw-r--r-- | client/components/main/fonts.styl | 24 | ||||
-rw-r--r-- | client/components/main/layouts.styl | 2 | ||||
-rw-r--r-- | client/components/rules/actions/boardActions.js | 4 | ||||
-rw-r--r-- | client/components/sidebar/sidebar.jade | 16 | ||||
-rw-r--r-- | client/components/sidebar/sidebar.js | 7 | ||||
-rw-r--r-- | client/lib/exportHTML.js | 206 |
11 files changed, 704 insertions, 20 deletions
diff --git a/client/components/boards/boardColors.styl b/client/components/boards/boardColors.styl index 3be9c0c3..0081143f 100644 --- a/client/components/boards/boardColors.styl +++ b/client/components/boards/boardColors.styl @@ -293,3 +293,418 @@ setBoardColor(color) //.header-quick-access // backgroud-color: #568ba2 + + +/* + Alternate "Clear" Styling +*/ +setBoardClear(color1,color2) + //color1: The quick access color + //color2: The main bar color + + &.sk-spinner div, + .board-backgrounds-list &.background-box, + .board-list & a + background: linear-gradient(180deg, color1 0%, color2 100%) + //background: linear-gradient(180deg, rgb(73, 155, 234) 0%, rgb(0, 174, 204) 100%) + + .is-selected .minicard + border-left: 3px solid color1 + + &.pop-over .pop-over-list li a:not(.disabled):hover, + .sidebar .sidebar-content .sidebar-btn:hover, + .sidebar-list li a:hover + background-color: lighten(color1, 10%) + + &#header ul li.current, &#header-quick-access ul li.current + border-bottom: 4px solid lighten(color2, 10%) + + &#header-quick-access + background: darken(color1, 10%) + //background: rgba(66,137,204,1) + color: #FFF + + &#header-quick-access #header-new-board-icon, + &#header-quick-access #header-user-bar, + &#header-quick-access ul li + color: rgba(255,255,255,0.5) + + // The background-color value here is not seen, + // its covered by the background of #header-main-bar + // it's just to aid transitions between boards + &#header + background-color: color2 + border-bottom: 1px solid darken(color2, 20%) + border-top: 1px solid darken(color2, 40%) + + // Since the theme uses a gradient for the header + // and gradients break transitions, it has to be set here + &#header #header-main-bar + background: linear-gradient(180deg, color1 0%, color2 100%) + + &#header #header-main-bar p + margin-bottom: 6px + + &#header #header-main-bar .board-header-btn.emphasis + background: lighten(color2, 10%) + + &:hover, + .board-header-btn-close + background: rgba(0,0,0,0.2) + + &:hover .board-header-btn-close + background: rgba(0,0,0,0.2) + + .materialCheckBox.is-checked + border-bottom: 2px solid color1 + border-right: 2px solid color1 + + .is-multiselection-active .multi-selection-checkbox + &.is-checked + .minicard + background: lighten(color2, 90%) + + &:not(.is-checked) + .minicard:hover:not(.minicard-composer) + background: lighten(color2, 97%) + + .toggle-switch:checked ~ .toggle-label + background-color: lighten(color1, 20%) + + &:after + background-color: darken(color1, 20%) + + .board-canvas + background: linear-gradient(135deg, color1 0%, color2 100%) + + .swimlane + background: none + + .list:first-child + margin-left: 15px + + .list + background: rgba(255,255,255,0.35) + margin: 10px + border: 0 + border-radius: 14px + + .list.list-composer + background: rgba(255,255,255,0.1) + height: min-content + flex: unset + width: 270px + padding-bottom: 16px + + .list.list-composer .open-list-composer + border-radius: 7px + color: rgba(0,0,0,0.3) + padding: 7px 10px + display: block + + .list.list-composer .open-list-composer:hover + box-shadow: 0 1px 2px rgba(0,0,0,.2) + background: rgba(255,255,255,0.7) + color: rgba(0,0,0,0.6) + + .list-header + background-color: rgba(255,255,255,0.25) + border-radius: 14px 14px 0 0 + + .list-header:not([class*="list-header-"]) + border-bottom: 6px solid rgba(255,255,255,0) + + .list-header .list-header-name + color: rgba(0,0,0,0.6) + + .list-body + padding: 11px + + .minicard + border-radius: 7px + padding: 10px 10px 4px 10px + box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15) + color: #222 + + .card-details + border-radius: 0 0 14px 14px + box-shadow: 0 0 7px 0 rgba(0,0,0,0.5) + margin-left: -10px + + .list-body .open-minicard-composer + border-radius: 7px + color: rgba(0,0,0,.3) + margin-bottom: 11px + + .list-body .open-minicard-composer:hover + background: rgba(255,255,255,0.7) + color: rgba(0,0,0,0.6) + + button[type=submit].primary, input[type=submit].primary + box-shadow: none + background-color: rgba(255,255,255,0.5) + color: rgba(0,0,0,0.55) + border-radius: 7px + border: 0 + + button[type="submit"].primary:hover, input[type="submit"].primary:hover + background-color: rgba(255,255,255,0.7) + color: rgba(0,0,0,0.8) + box-shadow: 0 1px 2px rgba(0,0,0,.2) + + .quiet, .quiet a + color: rgba(0,0,0,0.4) + + .list-header .list-header-watch-icon + color: rgba(0,0,0,0.5) + position: absolute + margin-top: -34px + margin-let: -11px + + a.fa, a i.fa + color: rgba(0,0,0,0.3) + + a:not(.disabled).is-active.fa, a:not(.disabled).is-active i.fa, a:not(.disabled):hover.fa, a:not(.disabled):hover i.fa + color: rgba(0,0,0,0.6) + + input[type="email"], input[type="password"], input[type="text"] + border: 0 + border-radius: 7px + + .sidebar-shadow + box-shadow: none + border-left: 9px solid color2 + + .is-open .sidebar-shadow + box-shadow: -10px 0 8px rgba(0,0,0,0.3) + + .list.ui-sortable-helper + transform:rotate(0deg) + + .minicard-wrapper.placeholder + background: rgba(0,0,0,0.1) + + .minicard-wrapper.ui-sortable-helper + transform:rotate(0deg) + opacity: 0.8 + + .list-body .open-minicard-composer + color: rgba(0,0,0,.3) + + .swinlane.ui-sortable-helper + transform:rotate(0deg) + + .swimlane .swimlane-header-wrap + background: linear-gradient(0deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.25) 100%) + + .swimlane-header-wrap .inlined-form + width: 100% + + .swimlane-header-wrap .list-composer + text-align: center + margin: 5px + + .swimlane-header-wrap .list-name-input.full-line + margin: 0 + display: inline-block + width: 270px + + .swimlane-header-wrap .edit-controls + display: inline-block + vertical-align: middle + + .swimlane-header-wrap .primary.confirm + margin-right: 0 + + .swimlane-header-wrap .fa.fa-times-thin + margin-top: 2px + + // This is a general fix so that the little grabby hand appears when dragging the list via the title + .list.ui-sortable-helper, + .list.ui-sortable-helper .list-header.ui-sortable-handle, + .list.ui-sortable-helper .viewer + cursor:-webkit-grabbing; + cursor:grabbing + +.board-color-clearblue + setBoardClear(rgb(73, 155, 234),rgb(0, 174, 204)) + +/* + Alternate "Natural" Styling +*/ +.board-color-natural + setBoardColor(#596557) + + &#header-quick-access + background-color: #2d392b + + .ui-sortable + background-color:#dedede + + .list-header + background-color: #c9cfc3 + border-bottom: 6px solid #c9cfc3 + + .swimlane .swimlane-header-wrap + background-color: #c2c0ab + +/* + Alternate "Modern" Styling +*/ +.board-color-modern + setBoardColor(#2A80B8) + + /* General */ + body + background: #f5f5f5 + + &#header-quick-access + padding: 10px + font-size: 14px + background: #333 !important + + &#header-quick-access ul + overflow: visible + + &#header-quick-access ul li.current + border: 0 !important + font-weight: bold + + &#header-quick-access ul li.separator + display: none + + &#header-quick-access ul li:nth-child(3) + margin-right: 10px + + &#header-quick-access ul li a + padding: 5px 10px + border-radius: 2px + + &#header-quick-access ul li.current a + border-radius: 2px + background: rgba(255,255,255,.2) + + &#header #header-main-bar h1 + font-family: Poppins + font-weight: bold + &#header-quick-access #header-user-bar + position relative + + &#header-quick-access #header-user-bar .header-user-bar-name + margin: 5px 3px 0 0; + + section#notifications-drawer + top: 46px; + box-shadow: 0 4px 20px rgba(0,0,0,.1) + max-width: 100% + + section#notifications-drawer .header + top: 46px; + border-radius: 0 3px + height: 21px + background: #f7f7f7 + + /* Swimlane */ + .swimlane + background: #f5f5f5 + + .swimlane .swimlane-header-wrap .swimlane-header + font-family: Poppins + + /* All board views */ + .board-list .board-list-item + padding: 20px + + .board-list-item-name + font-family: Poppins + + /* Board */ + .list + background: transparent + border-left: 0 + margin: 10px 0 + padding: 0px + border-radius: 5px + min-width: 300px + + .list-body .open-minicard-composer:hover /*me*/ + background: none + box-shadow: none + + .list:first-child + margin-left: 5px + + .list.list-composer.js-list-composer + transition: all .3s ease + min-width: 80px + + .open-list-composer.js-open-inlined-form:hover + color: #222 + + .list-header + background: none + border-bottom-width: 0px + + .list-header .list-header-name + font-family: Poppins + color: #000 + font-weight: 500 + + /* Card changes */ + .minicard + background: #FFF + padding: 15px 15px 10px + box-shadow: 0 3px 8px rgba(0,0,0,.05) + + .minicard-plum:hover:not(.minicard-composer), .is-selected .minicard-plum, .draggable-hover-card .minicard-plum + background: none + + .minicard-title + line-height: 1.5em + + .minicard .minicard-cover + background-size: cover + margin: -15px -15px 10px + height: 100px + + .card-label-orange + color: #fff + + .card-date + font-size: 12px + padding: 3px 5px + + /* Pop over */ + .header-title + font-family: Poppins + font-size: 16px + color: #333 + + .pop-over + box-shadow: 0 4px 20px rgba(0,0,0,.1) + border: 0 + border-radius: 5px + + .pop-over .header + padding: 10px + border-bottom: 0 + border-radius: 5px 5px 0 0 + + .pop-over .content-container .content + padding: 5px 20px 20px + width: 260px + + .pop-over-list li > a + border-radius: 5px + + .pop-over-list li > a > i + margin-right: 5px + + .pop-over-list li>a .sub-name + margin-bottom: 8px + + /* Sidebar */ + .sidebar .sidebar-shadow + box-shadow: 0 0 60px rgba(0,0,0,.2) + + .sidebar .sidebar-content + padding: 30px + diff --git a/client/components/boards/boardsList.jade b/client/components/boards/boardsList.jade index bbce1d6f..7fd7c2ba 100644 --- a/client/components/boards/boardsList.jade +++ b/client/components/boards/boardsList.jade @@ -31,6 +31,10 @@ template(name="boardList") i.fa.js-has-spenttime-cards( class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}" title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}") + if isMiniScreen + i.fa.board-handle( + class="fa-arrows" + title="{{_ 'Drag board'}}") unless isMiniScreen if isSandstorm i.fa.js-clone-board( diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index b99c0c31..eee119ea 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -72,6 +72,12 @@ BlazeComponent.extendComponent({ // Disable drag-dropping if the current user is not a board member or is comment only this.autorun(() => { + if (Utils.isMiniScreen()) { + $boards.sortable({ + handle: '.board-handle', + }); + } + $boards.sortable('option', 'disabled', !userIsAllowedToMove()); }); }, diff --git a/client/components/boards/boardsList.styl b/client/components/boards/boardsList.styl index 97d4f195..0cadbf84 100644 --- a/client/components/boards/boardsList.styl +++ b/client/components/boards/boardsList.styl @@ -208,6 +208,22 @@ $spaceBetweenTiles = 16px top: -100px left: -100px + .board-handle + position: absolute + padding: 7px + top: 50% + transform: translateY(-50%) + right: 10px + font-size: 24px + @media screen and (max-width: 360px) li width: 100% + + .board-handle + position: absolute + padding: 7px + top: 50% + transform: translateY(-50%) + right: 10px + font-size: 24px diff --git a/client/components/lists/list.js b/client/components/lists/list.js index 839304f8..5c315588 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -74,18 +74,16 @@ BlazeComponent.extendComponent({ const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards); const listId = Blaze.getData(ui.item.parents('.list').get(0))._id; const currentBoard = Boards.findOne(Session.get('currentBoard')); - let swimlaneId = ''; + const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id; + let targetSwimlaneId = null; + + // only set a new swimelane ID if the swimlanes view is active if ( Utils.boardView() === 'board-view-swimlanes' || currentBoard.isTemplatesBoard() ) - swimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0))._id; - else if ( - Utils.boardView() === 'board-view-lists' || - Utils.boardView() === 'board-view-cal' || - !Utils.boardView - ) - swimlaneId = currentBoard.getDefaultSwimline()._id; + targetSwimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0)) + ._id; // Normally the jquery-ui sortable library moves the dragged DOM element // to its new position, which disrupts Blaze reactive updates mechanism @@ -98,9 +96,12 @@ BlazeComponent.extendComponent({ if (MultiSelection.isActive()) { Cards.find(MultiSelection.getMongoSelector()).forEach((card, i) => { + const newSwimlaneId = targetSwimlaneId + ? targetSwimlaneId + : card.swimlaneId || defaultSwimlaneId; card.move( currentBoard._id, - swimlaneId, + newSwimlaneId, listId, sortIndex.base + i * sortIndex.increment, ); @@ -108,7 +109,10 @@ BlazeComponent.extendComponent({ } else { const cardDomElement = ui.item.get(0); const card = Blaze.getData(cardDomElement); - card.move(currentBoard._id, swimlaneId, listId, sortIndex.base); + const newSwimlaneId = targetSwimlaneId + ? targetSwimlaneId + : card.swimlaneId || defaultSwimlaneId; + card.move(currentBoard._id, newSwimlaneId, listId, sortIndex.base); } boardComponent.setIsDragging(false); }, diff --git a/client/components/main/fonts.styl b/client/components/main/fonts.styl index fc8c8f00..5d6fb558 100644 --- a/client/components/main/fonts.styl +++ b/client/components/main/fonts.styl @@ -15,3 +15,27 @@ local('Roboto-Bold'), url('/fonts/roboto-bold.woff2') format('woff2'), url('/fonts/roboto-bold.woff') format('woff') + +@font-face + font-family: 'Poppins' + font-style: normal + font-weight: 400 + src: local('Poppins'), + local('Poppins-Regular'), + url('/fonts/poppins-regular.woff') format('woff') + +@font-face + font-family: 'Poppins' + font-style: normal + font-weight: 500 + src: local('Poppins Medium'), + local('Poppins-Medium'), + url('/fonts/poppins-medium.woff') format('woff') + +@font-face + font-family: 'Poppins' + font-style: normal + font-weight: 700 + src: local('Poppins Bold'), + local('Poppins-Bold'), + url('/fonts/poppins-bold.woff') format('woff') diff --git a/client/components/main/layouts.styl b/client/components/main/layouts.styl index 01ce2f16..85a5f1b2 100644 --- a/client/components/main/layouts.styl +++ b/client/components/main/layouts.styl @@ -32,7 +32,7 @@ a:hover,a:focus border-radius: unset html, body, input, select, textarea, button - font: 14px Roboto, "Helvetica Neue", Arial, Helvetica, sans-serif + font: 14px Roboto, Poppins, "Helvetica Neue", Arial, Helvetica, sans-serif line-height: 18px color: #4d4d4d diff --git a/client/components/rules/actions/boardActions.js b/client/components/rules/actions/boardActions.js index 02910cc1..5675873f 100644 --- a/client/components/rules/actions/boardActions.js +++ b/client/components/rules/actions/boardActions.js @@ -68,8 +68,8 @@ BlazeComponent.extendComponent({ const ruleName = this.data().ruleName.get(); const trigger = this.data().triggerVar.get(); const actionSelected = this.find('#move-spec-action').value; - const swimlaneName = this.find('#swimlaneName').value; - const listName = this.find('#listName').value; + const swimlaneName = this.find('#swimlaneName').value || '*'; + const listName = this.find('#listName').value || '*'; const boardId = Session.get('currentBoard'); const destBoardId = this.find('#board-id').value; const desc = Utils.getTriggerActionDesc(event, this); diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade index 280eaeaf..04f2a8c2 100644 --- a/client/components/sidebar/sidebar.jade +++ b/client/components/sidebar/sidebar.jade @@ -329,12 +329,10 @@ template(name="boardMenuPopup") if isSandstorm hr ul.pop-over-list - if withApi - li - a(href="{{exportUrl}}", download="{{exportFilename}}") - i.fa.fa-share-alt - i.fa.fa-sign-out - | {{_ 'export-board'}} + li + a.js-export-board + i.fa.fa-share-alt + | {{_ 'export-board'}} li a.js-import-board i.fa.fa-share-alt @@ -365,7 +363,7 @@ template(name="boardMenuPopup") template(name="exportBoard") ul.pop-over-list li - a(href="{{exportUrl}}", download="{{exportJsonFilename}}") + a.download-json-link(href="{{exportUrl}}", download="{{exportJsonFilename}}") i.fa.fa-share-alt | {{_ 'export-board-json'}} li @@ -376,6 +374,10 @@ template(name="exportBoard") a(href="{{exportTsvUrl}}", download="{{exportTsvFilename}}") i.fa.fa-share-alt | {{_ 'export-board-tsv'}} + li + a.html-export-board + i.fa.fa-archive + | {{_ 'export-board-html'}} template(name="labelsWidget") .board-widget.board-widget-labels diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index 2c1cfd75..0e535041 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -463,6 +463,13 @@ BlazeComponent.extendComponent({ }, }).register('exportBoardPopup'); +Template.exportBoard.events({ + 'click .html-export-board': async event => { + event.preventDefault(); + await ExportHtml(Popup)(); + } +}); + Template.labelsWidget.events({ 'click .js-label': Popup.open('editLabel'), 'click .js-add-label': Popup.open('createLabel'), diff --git a/client/lib/exportHTML.js b/client/lib/exportHTML.js new file mode 100644 index 00000000..fe15b6aa --- /dev/null +++ b/client/lib/exportHTML.js @@ -0,0 +1,206 @@ +const JSZip = require('jszip'); + +window.ExportHtml = (Popup) => { + const saveAs = function(blob, filename) { + let dl = document.createElement('a'); + dl.href = window.URL.createObjectURL(blob); + dl.onclick = event => document.body.removeChild(event.target); + dl.style.display = 'none'; + dl.target = '_blank'; + dl.download = filename; + document.body.appendChild(dl); + dl.click(); + }; + + const asyncForEach = async function (array, callback) { + for (let index = 0; index < array.length; index++) { + await callback(array[index], index, array); + } + }; + + const getPageHtmlString = () => { + return `<!doctype html>${ + window.document.querySelector('html').outerHTML + }`; + }; + + const removeAnchors = htmlString => { + const replaceOpenAnchor = htmlString.replace(new RegExp('<a ', 'gim'), '<span '); + return replaceOpenAnchor.replace(new RegExp('<\/a', 'gim'), '</span'); + }; + + const ensureSidebarRemoved = () => { + document.querySelector('.board-sidebar.sidebar').remove(); + }; + + const addJsonExportToZip = async (zip, boardSlug) => { + const downloadJSONLink = document.querySelector('.download-json-link'); + const downloadJSONURL = downloadJSONLink.href; + const response = await fetch(downloadJSONURL); + const responseBody = await response.text(); + zip.file(`data/${boardSlug}.json`, responseBody); + }; + + const closeSidebar = () => { + document.querySelector('.board-header-btn.js-toggle-sidebar').click(); + }; + + const cleanBoardHtml = () => { + Array.from(document.querySelectorAll('script')).forEach(elem => + elem.remove(), + ); + Array.from( + document.querySelectorAll('link:not([rel="stylesheet"])'), + ).forEach(elem => elem.remove()); + document.querySelector('#header-quick-access').remove(); + Array.from( + document.querySelectorAll('#header-main-bar .board-header-btns'), + ).forEach(elem => elem.remove()); + Array.from(document.querySelectorAll('.list-composer')).forEach(elem => + elem.remove(), + ); + Array.from( + document.querySelectorAll( + '.list-composer,.js-card-composer, .js-add-card', + ), + ).forEach(elem => elem.remove()); + Array.from( + document.querySelectorAll('.js-perfect-scrollbar > div:nth-of-type(n+2)'), + ).forEach(elem => elem.remove()); + Array.from(document.querySelectorAll('.js-perfect-scrollbar')).forEach( + elem => { + elem.style = 'overflow-y: auto !important;'; + elem.classList.remove('js-perfect-scrollbar'); + }, + ); + Array.from(document.querySelectorAll('[href]:not(link)')).forEach(elem => + elem.attributes.removeNamedItem('href'), + ); + Array.from(document.querySelectorAll('[href]')).forEach(elem => { + // eslint-disable-next-line no-self-assign + elem.href = elem.href; + // eslint-disable-next-line no-self-assign + elem.src = elem.src; + }); + Array.from(document.querySelectorAll('.is-editable')).forEach(elem => { + elem.classList.remove('is-editable') + }) + + }; + + const getBoardSlug = () => { + return window.location.href.split('/').pop(); + }; + + const getStylesheetList = () => { + return Array.from( + document.querySelectorAll('link[href][rel="stylesheet"]'), + ); + }; + + const downloadStylesheets = async (stylesheets, zip) => { + await asyncForEach(stylesheets, async elem => { + const response = await fetch(elem.href); + const responseBody = await response.text(); + + const finalResponse = responseBody.replace( + new RegExp('packages\/[^\/]+\/upstream\/', 'gim'), '../' + ); + + const filename = elem.href + .split('/') + .pop() + .split('?') + .shift(); + const fileFullPath = `style/${filename}`; + zip.file(fileFullPath, finalResponse); + elem.href = `../${fileFullPath}`; + }); + }; + + const getSrcAttached = () => { + return Array.from(document.querySelectorAll('[src]')); + }; + + const downloadSrcAttached = async (elements, zip, boardSlug) => { + await asyncForEach(elements, async elem => { + const response = await fetch(elem.src); + const responseBody = await response.blob(); + const filename = elem.src + .split('/') + .pop() + .split('?') + .shift(); + const fileFullPath = `${boardSlug}/${elem.tagName.toLowerCase()}/${filename}`; + zip.file(fileFullPath, responseBody); + elem.src = `./${elem.tagName.toLowerCase()}/${filename}`; + }); + }; + + const removeCssUrlSurround = url => { + const working = url || ""; + return working + .split("url(") + .join("") + .split("\")") + .join("") + .split("\"") + .join("") + .split("')") + .join("") + .split("'") + .join("") + .split(")") + .join(""); + }; + + const getCardCovers = () => { + return Array.from(document.querySelectorAll('.minicard-cover')) + .filter(elem => elem.style['background-image']) + } + + const downloadCardCovers = async (elements, zip, boardSlug) => { + await asyncForEach(elements, async elem => { + const response = await fetch(removeCssUrlSurround(elem.style['background-image'])); + const responseBody = await response.blob(); + const filename = removeCssUrlSurround(elem.style['background-image']) + .split('/') + .pop() + .split('?') + .shift() + .split('#') + .shift(); + const fileFullPath = `${boardSlug}/covers/${filename}`; + zip.file(fileFullPath, responseBody); + elem.style = "background-image: url('" + `covers/${filename}` + "')"; + }); + }; + + const addBoardHTMLToZip = (boardSlug, zip) => { + ensureSidebarRemoved(); + const htmlOutputPath = `${boardSlug}/index.html`; + zip.file(htmlOutputPath, new Blob([ + removeAnchors(getPageHtmlString()) + ], { type: 'application/html' })); + }; + + return async () => { + const zip = new JSZip(); + const boardSlug = getBoardSlug(); + + await addJsonExportToZip(zip, boardSlug); + Popup.close(); + closeSidebar(); + cleanBoardHtml(); + + await downloadStylesheets(getStylesheetList(), zip); + await downloadSrcAttached(getSrcAttached(), zip, boardSlug); + await downloadCardCovers(getCardCovers(), zip, boardSlug); + + addBoardHTMLToZip(boardSlug, zip); + + const content = await zip.generateAsync({ type: 'blob' }); + saveAs(content, `${boardSlug}.zip`); + window.location.reload(); + } +}; |