Export button

main
Elbert Alias 3 years ago
parent 2d0ada890a
commit 3e8869ac47

@ -72,7 +72,7 @@ p {
text-align: right;
}
.button__link:hover:before {
.button__link:before {
background: var(--color-primary);
border-radius: 4px;
content: '';
@ -81,6 +81,10 @@ p {
left: 0;
right: 0;
bottom: 0;
opacity: 0;
}
.button__link:hover:before {
opacity: .1;
}
@ -223,16 +227,22 @@ small {
overflow: hidden;
}
.tab-item:nth-child(2) {
min-width: 500px;
}
.tab-item--hidden {
display: none;
}
.credits {
background: var(--color-secondary);
color: var(--color-text-lighten);
display: block;
font-size: .8rem;
text-align: right;
flex: 1;
padding: 0 1.5rem;
padding: 1rem 1.5rem 0 1.5rem;
margin-bottom: -3px;
line-height: 1rem;
}
@ -393,13 +403,22 @@ small {
}
.plus-download {
background: var(--color-secondary);
padding: 1rem 1.5rem 0 1.5rem;
flex: 1 0;
text-align: right;
padding: 0 1.5rem;
white-space: nowrap;
}
.plus-download .button__link:before {
opacity: .1;
}
.plus-download .button__link:hover:before {
opacity: .2;
}
.plus-download--hidden {
display: none;
visibility: hidden;
}
.plus-error {
@ -849,7 +868,7 @@ body.dynamic-icon .category__heading:hover .category__pin {
color: var(--color-text-dark);
}
.dark .button__link:hover:before {
.dark .button__link:before {
background: white;
}
@ -953,6 +972,11 @@ body.dynamic-icon .category__heading:hover .category__pin {
border-color: var(--color-primary);
}
.dark .credits {
background: var(--color-primary-darken);
}
.dark .footer {
background: var(--color-primary-darken);
border-top: 1px solid var(--color-primary);

@ -49,13 +49,22 @@
<div class="tab tab--technologies tab--active" data-i18n="tabTechnologies">&nbsp;</div>
<div class="tab tab--plus"><span data-i18n="tabPlus">&nbsp;</span></div>
<div class="credits credits--hidden">
<span data-i18n="creditBalance">&nbsp;</span>
<div class="plus-download plus-download--hidden">
<div class="plus-download__button button">
<span class="button__link">
<svg class="button__icon button__icon--left" viewBox="0 0 24 24">
<path fill="currentColor" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
</svg>
<span class="credits__remaining">&nbsp;</span>
<span class="button__text">
Export
</span>
</span>
</div>
</div>
</div>
<div class="tab-items">
<div class="tab-item">
<div class="empty empty--hidden">
<div class="empty__text" data-i18n="noAppsDetected">&nbsp;</div>
@ -154,18 +163,10 @@
</div>
<div class="tab-item tab-item--hidden">
<div class="plus-download plus-download--hidden">
<div class="plus-download__button button">
<span class="button__link">
<svg class="button__icon button__icon--left" viewBox="0 0 24 24">
<path fill="currentColor" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
</svg>
<div class="credits credits--hidden">
<span data-i18n="creditBalance">&nbsp;</span>
<span class="button__text">
Download CSV
</span>
</span>
</div>
<span class="credits__remaining">&nbsp;</span>
</div>
<div class="plus-error plus-error--hidden">
@ -231,6 +232,7 @@
<div class="plus-empty plus-empty--hidden" data-i18n="plusEmpty"></div>
<div class="plus-crawl plus-crawl--hidden" data-i18n="plusCrawl"></div>
</div>
</div>
<div class="footer">
<div class="footer__heading">

@ -8,9 +8,6 @@ const { agent, open, i18n, getOption, setOption, promisify, sendMessage } =
const baseUrl = 'https://www.wappalyzer.com'
const utm = '?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer'
let csv = ''
let csvFilename = ''
const footers = [
{
heading: 'Generate sales leads',
@ -107,6 +104,71 @@ function setDisabledDomain(enabled) {
}
}
function getCsv() {
let hostname = ''
let www = false
let https = false
try {
let protocol = ''
;({ hostname, protocol } = new URL(Popup.cache.url))
www = hostname.startsWith('www')
https = protocol === 'https:'
hostname = hostname.replace(/^www\./, '')
} catch (error) {
// Continue
}
const columns = [
'URL',
...Popup.cache.categories.map(({ id }) =>
chrome.i18n.getMessage(`categoryName${id}`)
),
...attributeKeys.map((key) =>
chrome.i18n.getMessage(
`attribute${
key.charAt(0).toUpperCase() + key.slice(1).replace('.', '_')
}`
)
),
]
const csv = [`"${columns.join('","')}"`]
const filename = `wappalyzer${
hostname ? `_${hostname.replace('.', '-')}` : ''
}.csv`
const row = [`http${https ? 's' : ''}://${www ? 'www.' : ''}${hostname}`]
row.push(
...Popup.cache.categories.reduce((categories, { id }) => {
categories.push(
Popup.cache.detections
.filter(({ categories }) =>
categories.some(({ id: _id }) => _id === id)
)
.map(({ name }) => name)
.join(' ; ')
)
return categories
}, [])
)
row.push(
...attributeKeys.map((key) => csvEscape(Popup.cache.attributeValues[key]))
)
csv.push(`"${row.join('","')}"`)
return { csv, filename }
}
function csvEscape(value = '') {
if (Array.isArray(value)) {
value = value
@ -136,6 +198,13 @@ const Popup = {
* Initialise popup
*/
async init() {
Popup.cache = {
url: '',
categories: [],
detections: [],
attributeValues: {},
}
const el = {
body: document.body,
terms: document.querySelector('.terms'),
@ -150,6 +219,7 @@ const Popup = {
headerSwitchDisabled: document.querySelector('.header__switch--disabled'),
plusConfigureApiKey: document.querySelector('.plus-configure__apikey'),
plusConfigureSave: document.querySelector('.plus-configure__save'),
plusDownload: document.querySelector('.plus-download'),
plusDownloadLink: document.querySelector(
'.plus-download__button .button__link'
),
@ -246,6 +316,8 @@ const Popup = {
;[{ url }] = tabs
if (url.startsWith('http')) {
Popup.cache.url = url
const { hostname } = new URL(url)
setDisabledDomain(disabledDomains.includes(hostname))
@ -322,6 +394,7 @@ const Popup = {
el.tabItems[index].classList.remove('tab-item--hidden')
el.credits.classList.add('credits--hidden')
el.plusDownload.classList.remove('plus-download--hidden')
el.footer.classList.remove('footer--hidden')
if (tab.classList.contains('tab--plus')) {
@ -331,7 +404,7 @@ const Popup = {
})
// Download
el.plusDownloadLink.addEventListener('click', (event) => Popup.downloadCsv)
el.plusDownloadLink.addEventListener('click', Popup.downloadCsv)
// Footer
const item =
@ -381,6 +454,8 @@ const Popup = {
// Apply internationalization
i18n()
Popup.cache.categories = await Popup.driver('getCategories')
},
driver(func, args) {
@ -423,9 +498,12 @@ const Popup = {
* @param {Array} detections
*/
async onGetDetections(detections = []) {
Popup.cache.detections = detections
const el = {
empty: document.querySelector('.empty'),
detections: document.querySelector('.detections'),
plusDownload: document.querySelector('.plus-download'),
}
detections = (detections || [])
@ -435,12 +513,14 @@ const Popup = {
if (!detections || !detections.length) {
el.empty.classList.remove('empty--hidden')
el.detections.classList.add('detections--hidden')
el.plusDownload.classList.add('plus-download--hidden')
return
}
el.empty.classList.add('empty--hidden')
el.detections.classList.remove('detections--hidden')
el.plusDownload.classList.remove('plus-download--hidden')
while (el.detections.firstChild) {
el.detections.removeChild(detections.firstChild)
@ -554,9 +634,6 @@ const Popup = {
crawl: document.querySelector('.plus-crawl'),
error: document.querySelector('.plus-error'),
download: document.querySelector('.plus-download'),
downloadLink: document.querySelector(
'.plus-download__button .button__link'
),
errorMessage: document.querySelector('.plus-error__message'),
configure: document.querySelector('.plus-configure'),
credits: document.querySelector('.credits'),
@ -565,6 +642,7 @@ const Popup = {
}
el.error.classList.add('plus-error--hidden')
el.download.classList.add('plus-download--hidden')
if (apiKey) {
el.loading.classList.remove('loading--hidden')
@ -579,7 +657,6 @@ const Popup = {
}
el.panels.classList.add('panels--hidden')
el.download.classList.add('plus-download--hidden')
el.empty.classList.add('plus-empty--hidden')
el.crawl.classList.add('plus-crawl--hidden')
el.error.classList.add('plus-error--hidden')
@ -588,24 +665,6 @@ const Popup = {
el.panels.removeChild(el.panels.lastElementChild)
}
let hostname = ''
let www = false
let https = false
try {
let protocol = ''
;({ hostname, protocol } = new URL(url))
www = hostname.startsWith('www')
https = protocol === 'https:'
hostname = hostname.replace(/^www\./, '')
} catch (error) {
// Continue
}
try {
const response = await fetch(
`https://api.wappalyzer.com/v2/plus/${encodeURIComponent(url)}`,
@ -635,9 +694,8 @@ const Popup = {
10
).toLocaleString()
el.credits.classList.remove('credits--hidden')
el.loading.classList.add('loading--hidden')
el.credits.classList.remove('credits--hidden')
if (crawl) {
document
@ -649,50 +707,11 @@ const Popup = {
if (!Object.keys(attributes).length) {
el.empty.classList.remove('plus-empty--hidden')
el.download.classList.remove('plus-download--hidden')
return
}
const categories = await Popup.driver('getCategories')
const columns = [
'URL',
...categories.map(({ id }) =>
chrome.i18n.getMessage(`categoryName${id}`)
),
...attributeKeys.map((key) =>
chrome.i18n.getMessage(
`attribute${
key.charAt(0).toUpperCase() + key.slice(1).replace('.', '_')
}`
)
),
]
csv = [`"${columns.join('","')}"`]
csvFilename = `wappalyzer${
hostname ? `_${hostname.replace('.', '-')}` : ''
}.csv`
const row = [`http${https ? 's' : ''}://${www ? 'www.' : ''}${hostname}`]
const detections = await Popup.driver('getDetections')
row.push(
...categories.reduce((categories, { id }) => {
categories.push(
detections
.filter(({ categories }) =>
categories.some(({ id: _id }) => _id === id)
)
.map(({ name }) => name)
.join(' ; ')
)
return categories
}, [])
)
const attributeValues = {}
Object.keys(attributes).forEach((set) => {
@ -800,26 +819,7 @@ const Popup = {
el.panels.appendChild(panel)
})
row.push(...attributeKeys.map((key) => csvEscape(attributeValues[key])))
csv.push(`"${row.join('","')}"`)
el.downloadLink.addEventListener('click', (event) => {
event.preventDefault()
const file = URL.createObjectURL(
new Blob([csv.join('\n')], { type: 'text/csv;charset=utf-8' })
)
chrome.downloads.download({
url: file,
filename: `wappalyzer${
hostname ? `_${hostname.replace('.', '-')}` : ''
}.csv`,
})
return false
})
Popup.cache.attributeValues = attributeValues
el.panels.classList.remove('panels--hidden')
el.download.classList.remove('plus-download--hidden')
@ -869,14 +869,20 @@ const Popup = {
i18n()
},
downloadCsv() {
downloadCsv(event) {
console.log('x')
event.preventDefault()
chrome.downloads.download({
url: URL.createObjectURL(
const { csv, filename } = getCsv()
const file = URL.createObjectURL(
new Blob([csv.join('\n')], { type: 'text/csv;charset=utf-8' })
),
filename: csvFilename,
)
chrome.downloads.download({
url: file,
filename,
})
return false