Skip to content

Commit

Permalink
feat: basic implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
test123456789012345 committed Jun 6, 2020
1 parent c1b180c commit a5775f8
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 47 deletions.
12 changes: 12 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "GitHub Saved Filters",
"matches": [
"https://github.com/*"
],
"permissions": ["storage"],
"browser_specific_settings": {
"gecko": {
"id": "{071e944b-8d1c-4b48-8bba-4c2519deee01}"
}
}
}
21 changes: 21 additions & 0 deletions content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { property } from '@dword-design/functions'
import buildHeaderNav from './model/build-header-nav'
import buildActionButton from './model/build-action-button'

const run = async () => {
if (!['/issues', '/pulls'].includes(window.location.pathname)) {
return undefined
}

const savedFilters =
(browser.storage.sync.get('githubSavedFilters')
|> await
|> property('githubSavedFilters')) || []

return Promise.all([
buildHeaderNav({ savedFilters }),
buildActionButton({ savedFilters }),
])
}

run()
33 changes: 33 additions & 0 deletions model/build-action-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { find } from '@dword-design/functions'
import openSaveDialog from './open-save-dialog'
import openDeleteDialog from './open-delete-dialog'
import { SLUG } from './variables.config'

export default async options => {
const $subnav = document.querySelector('.subnav')
const $query = document.querySelector('.subnav-search-input')
const filter = options.savedFilters |> find({ query: $query.value })
let $actionButton = document.querySelector(`.${SLUG}-button`)
if ($actionButton) {
$actionButton.remove()
}
$actionButton = document.createElement('button')
$actionButton.innerText = filter ? 'Delete' : 'Save'
$actionButton.classList.add(
`${SLUG}-button`,
'btn',
...(filter ? ['btn-danger'] : []),
'ml-md-2',
'mt-2',
'mt-md-0',
'flex-self-start'
)
$subnav.append($actionButton)
$actionButton.onclick = () => {
if (filter) {
openDeleteDialog(filter, options)
} else {
openSaveDialog(options)
}
}
}
38 changes: 38 additions & 0 deletions model/build-header-nav.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { endent, map, join } from '@dword-design/functions'
import { SLUG } from './variables.config'

export default async options => {
if (options.savedFilters.length === 0) {
return
}
const $headerNav = document.querySelector('.Header nav')
let $savedFilters = $headerNav.querySelector(`.${SLUG}-header-nav`)
if ($savedFilters) {
$savedFilters.remove()
}
$savedFilters = document.createElement('details')
$savedFilters.classList.add(
`${SLUG}-header-nav`,
'dropdown',
'details-overlay',
'details-reset'
)
$savedFilters.innerHTML = endent`
<summary class="Header-link py-2 py-lg-3 mr-0 mr-lg-3" aria-haspopup="menu" role="button">
Saved filters <span class="dropdown-caret"></span>
</summary>
<details-menu class="dropdown-menu dropdown-menu-se mt-n2" role="menu">
${
options.savedFilters
|> map(
filter =>
`<a role="menuitem" class="dropdown-item" href="/issues?q=${encodeURIComponent(
filter.query
)}">${filter.name}</a>`
)
|> join('\n')
}
</details-menu>
`
$headerNav.prepend($savedFilters)
}
74 changes: 74 additions & 0 deletions model/open-delete-dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { remove } from '@dword-design/functions'
import { SLUG } from './variables.config'

export default (filter, options) => {
let $dialog = document.querySelector(`.${SLUG}-dialog`)
if ($dialog) {
$dialog.remove()
}
$dialog = document.createElement('div')
$dialog.setAttribute('role', 'dialog')
$dialog.classList.add(
`${SLUG}-dialog`,
'Box',
'Box--overlay',
'd-flex',
'flex-column',
'anim-fade-in',
'fast',
'position-fixed'
)
$dialog.style.left = '50%'
$dialog.style.top = '50%'
$dialog.style.transform = 'translate(-50%, -50%)'
$dialog.style.maxWidth = 'calc(100% - 32px)'
$dialog.style.zIndex = 34

const $header = document.createElement('div')
$header.classList.add('Box-header')

const $close = document.createElement('button')
$close.classList.add('Box-btn-octicon', 'btn-octicon', 'float-right')
$close.setAttribute('type', 'button')
$close.setAttribute('aria-label', 'Close dialog')
$close.innerHTML =
'<svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"></path></svg>'
$close.onclick = () => $dialog.remove()
$header.append($close)

const $title = document.createElement('h3')
$title.classList.add('Box-title')
$title.innerText = `Do you really want to delete filter '${filter.name}'?`
$header.append($title)
$dialog.append($header)
document.body.append($dialog)

const $form = document.createElement('form')
$form.onsubmit = async event => {
event.preventDefault()
await browser.storage.sync.set({
githubSavedFilters:
options.savedFilters
|> remove(_filter => _filter.query === filter.query),
})
window.location.reload()
}
$dialog.append($form)

const $footer = document.createElement('div')
$footer.classList.add('Box-footer', 'text-right')
$form.append($footer)

const $cancel = document.createElement('button')
$cancel.type = 'button'
$cancel.classList.add('btn', 'mr-2')
$cancel.innerText = 'Cancel'
$cancel.onclick = () => $dialog.remove()
$footer.append($cancel)

const $delete = document.createElement('button')
$delete.classList.add('btn', 'btn-danger')
$delete.type = 'submit'
$delete.innerText = 'Delete'
$footer.append($delete)
}
91 changes: 91 additions & 0 deletions model/open-save-dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { SLUG } from './variables.config'

export default options => {
let $dialog = document.querySelector(`.${SLUG}-dialog`)
if ($dialog) {
$dialog.remove()
}
$dialog = document.createElement('div')
$dialog.setAttribute('role', 'dialog')
$dialog.classList.add(
`${SLUG}-dialog`,
'Box',
'Box--overlay',
'd-flex',
'flex-column',
'anim-fade-in',
'fast',
'position-fixed'
)
$dialog.style.left = '50%'
$dialog.style.top = '50%'
$dialog.style.transform = 'translate(-50%, -50%)'
$dialog.style.maxWidth = 'calc(100% - 32px)'
$dialog.style.zIndex = 34

const $header = document.createElement('div')
$header.classList.add('Box-header')

const $close = document.createElement('button')
$close.classList.add('Box-btn-octicon', 'btn-octicon', 'float-right')
$close.setAttribute('type', 'button')
$close.setAttribute('aria-label', 'Close dialog')
$close.innerHTML =
'<svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"></path></svg>'
$close.onclick = () => $dialog.remove()
$header.append($close)

const $title = document.createElement('h3')
$title.classList.add('Box-title')
$title.innerText = 'Save filter'
$header.append($title)
$dialog.append($header)
document.body.append($dialog)

// ///////////////////////////////////////////////////////////////////

const $name = document.createElement('input')
$name.classList.add('form-control', 'input-block')
$name.type = 'text'
$name.placeholder = 'Filter name'
$name.setAttribute('aria-label', 'Filter name')
$name.required = true

const $form = document.createElement('form')
$form.onsubmit = async event => {
event.preventDefault()
const $query = document.querySelector('.subnav-search-input')
await browser.storage.sync.set({
githubSavedFilters: [
...options.savedFilters,
{ name: $name.value, query: $query.value },
],
})
window.location.reload()
}
$dialog.append($form)

const $body = document.createElement('div')
$body.classList.add('Box-body')
$form.append($body)

$body.append($name)
$name.focus()

const $footer = document.createElement('div')
$footer.classList.add('Box-footer', 'text-right')
$form.append($footer)

const $cancel = document.createElement('button')
$cancel.type = 'button'
$cancel.classList.add('btn', 'mr-2')
$cancel.innerText = 'Cancel'
$cancel.onclick = () => $dialog.remove()
$footer.append($cancel)

const $save = document.createElement('button')
$save.classList.add('btn', 'btn-primary')
$save.type = 'submit'
$save.innerText = 'Save'
$footer.append($save)
}
1 change: 1 addition & 0 deletions model/variables.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SLUG = 'github-saved-filters'
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@
"prepublishOnly": "base prepublishOnly",
"test": "base test"
},
"dependencies": {
"@dword-design/functions": "^1.1.2"
},
"devDependencies": {
"@dword-design/base": "^6.15.1",
"@dword-design/base-config-web-extension": "^1.6.3"
},
"publishConfig": {
"access": "public"
},
"baseConfig": "web-extension"
"baseConfig": {
"name": "web-extension",
"startUrl": "https://github.com/issues"
}
}
Loading

0 comments on commit a5775f8

Please sign in to comment.