Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Commit

Permalink
Merge pull request #501 from beakerbrowser/dat-picker
Browse files Browse the repository at this point in the history
DatArchive.selectArchive
  • Loading branch information
pfrazee authored Jun 4, 2017
2 parents 0cecd3c + 74ebde0 commit 9ebc4d0
Show file tree
Hide file tree
Showing 16 changed files with 529 additions and 17 deletions.
9 changes: 9 additions & 0 deletions app/background-process/protocols/beaker.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,15 @@ async function beakerServer (req, res) {
if (requestUrl === 'beaker://prompt-modal/main.js') {
return cb(200, 'OK', 'application/javascript', path.join(__dirname, 'builtin-pages/build/prompt-modal.build.js'))
}
if (requestUrl === 'beaker://select-archive-modal/') {
return cb(200, 'OK', 'text/html', path.join(__dirname, 'builtin-pages/select-archive-modal.html'))
}
if (requestUrl === 'beaker://select-archive-modal/main.css') {
return cb(200, 'OK', 'text/css', path.join(__dirname, 'stylesheets/builtin-pages/select-archive-modal.css'))
}
if (requestUrl === 'beaker://select-archive-modal/main.js') {
return cb(200, 'OK', 'application/javascript', path.join(__dirname, 'builtin-pages/build/select-archive-modal.build.js'))
}

// debugging
if (requestUrl === 'beaker://internal-archives/') {
Expand Down
1 change: 1 addition & 0 deletions app/background-process/ui/modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const SIZES = {
'create-archive': {width: 500, height: 340},
'fork-archive': {width: 500, height: 390},
'basic-auth': {width: 500, height: 320},
'select-archive': {width: 500, height: 450},
prompt: {width: 500, height: 170}
}

Expand Down
4 changes: 2 additions & 2 deletions app/background-process/web-apis/archives.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ function toKey (url) {
if (DAT_HASH_REGEX.test(url)) {
// simple case: given the key
return url
}
}

var urlp = parseURL(url)

// validate
Expand Down
16 changes: 15 additions & 1 deletion app/background-process/web-apis/dat-archive.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,21 @@ export default {

async resolveName(name) {
return datDns.resolveName(name)
}
},

async selectArchive ({title, buttonLabel, filters} = {}) {
// initiate the modal
var win = getWebContentsWindow(this.sender)
// DISABLED
// this mechanism is a bit too temperamental
// are we sure it's the best policy anyway?
// -prf
// await assertSenderIsFocused(this.sender)
var createdBy = this.sender.getURL()
var res = await showModal(win, 'select-archive', {title, buttonLabel, filters, createdBy})
if (!res || !res.url) throw new UserDeniedError()
return res.url
},
}

// internal helpers
Expand Down
13 changes: 13 additions & 0 deletions app/builtin-pages/select-archive-modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Select Archive</title>
<link rel="stylesheet" href="beaker://assets/font-awesome.css">
<link rel="stylesheet" href="beaker://select-archive-modal/main.css">
</head>
<body>
<main></main>
<script src="beaker://select-archive-modal/main.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion app/builtin-pages/views/basic-auth-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function render () {
<div class="modal">
<div class="modal-inner">
<div class="basic-auth-modal">
<h2 class="title">Login required</h2>
<h1 class="title">Login required</h1>
<p class="help-text">
${authInfo.host} requires a username and password
Expand Down
2 changes: 1 addition & 1 deletion app/builtin-pages/views/create-archive-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function render () {
<div class="modal">
<div class="modal-inner">
<div class="edit-site-modal">
<h2 class="title">${uititle}</h2>
<h1 class="title">${uititle}</h1>
<p class="help-text">
${helpText}
Expand Down
2 changes: 1 addition & 1 deletion app/builtin-pages/views/fork-archive-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function render () {
<div class="modal">
<div class="modal-inner">
<div class="fork-dat-modal">
<h2 class="title">Fork ${renderArchiveTitle('archive')}</h2>
<h1 class="title">Fork ${renderArchiveTitle('archive')}</h1>
<p class="help-text">${helpText}</p>
<form onsubmit=${onSubmit}>
Expand Down
202 changes: 202 additions & 0 deletions app/builtin-pages/views/select-archive-modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import * as yo from 'yo-yo'
import {Archive} from 'builtin-pages-lib'

var currentFilter = ''
var selectedArchiveKey = ''
var archives
var title = ''
var description = ''
var createdBy
var buttonLabel = 'Submit'
var customTitle = ''
var currentTab = 'archivePicker'
var isFormDisabled = true

// exported api
// =

window.setup = async function (opts) {
try {
buttonLabel = opts.buttonLabel || buttonLabel
customTitle = opts.title || ''

if (opts.filters && opts.filters.isOwner) archives = await beaker.archives.list({isOwner: true})
else archives = await beaker.archives.list()

// render
createdBy = opts.createdBy || undefined
render()
} catch (e) {
console.error(e)
// ditch out
return beakerBrowser.closeModal({
name: e.name,
message: e.message || e.toString(),
internalError: true
})
}
}

// event handlers
// =

window.addEventListener('keyup', e => {
if (e.which === 27) {
beakerBrowser.closeModal()
}
})

function onChangeTitle (e) {
selectedArchiveKey = ''
title = e.target.value
}

function onChangeDescription (e) {
selectedArchiveKey = ''
description = e.target.value
}

function onClickCancel (e) {
e.preventDefault()
beakerBrowser.closeModal()
}

function onChangeFilter (e) {
currentFilter = e.target.value.toLowerCase()
render()
}

function onChangeSelectedArchive (e) {
isFormDisabled = false
selectedArchiveKey = e.currentTarget.dataset.key
render()
}

function onUpdateActiveTab (e) {
isFormDisabled = false
currentTab = e.target.dataset.content
render()
}

async function onSubmit (e) {
e.preventDefault()
if (!selectedArchiveKey) {
try {
var newArchive = await beaker.archives.create({title, description, createdBy})
beakerBrowser.closeModal(null, {url: newArchive.url})
} catch (e) {
beakerBrowser.closeModal({
name: e.name,
message: e.message || e.toString(),
internalError: true
})
}
} else {
beakerBrowser.closeModal(null, {url: `dat://${selectedArchiveKey}/`})
}
}

// internal methods
// =

function render () {
yo.update(document.querySelector('main'), yo`<main>
<div class="modal">
<div class="modal-inner">
<div class="select-archive-modal">
<h1 class="title">${customTitle || 'Select an archive'}</h1>
<p class="help-text">
Choose an existing Dat archive or create a new one.
</p>
<form onsubmit=${onSubmit}>
<div class="tabs-container">
<div class="tabs">
<div onclick=${onUpdateActiveTab} data-content="archivePicker" class="tab ${currentTab === 'archivePicker' ? 'selected' : ''}">
Select an archive
</div>
<div onclick=${onUpdateActiveTab} data-content="newArchive" class="tab ${currentTab === 'newArchive' ? 'selected' : ''} ">
Create new archive
</div>
</div>
${renderActiveTabContent()}
</div>
<div class="form-actions">
<button type="button" onclick=${onClickCancel} class="btn cancel" tabindex="4">Cancel</button>
<button disabled=${isFormDisabled ? 'disabled' : 'false'} type="submit" class="btn primary" tabindex="5">
${buttonLabel}
</button>
</div>
</form>
</div>
</div>
</div>
</main>`)
}

function renderActiveTabContent () {
if (currentTab === 'archivePicker') return renderArchivePicker()
else if (currentTab === 'newArchive') return renderNewArchiveForm()
}

function renderNewArchiveForm () {
return yo`
<div class="tab-content create-archive">
<label for="title">Title</label>
<input autofocus name="title" tabindex="2" value=${title || ''} placeholder="Title" onchange=${onChangeTitle} />
<label for="desc">Description</label>
<textarea name="desc" tabindex="3" placeholder="Description (optional)" onchange=${onChangeDescription}>${description || ''}</textarea>
</div>
`
}

function renderArchivePicker () {
if (!archives.length) {
return 'No archives'
}

return yo`
<div class="tab-content archive-picker">
<div class="filter-container">
<i class="fa fa-search"></i>
<input autofocus onkeyup=${onChangeFilter} id="filter" class="filter" type="text" placeholder="Search your archives..."/>
</div>
<ul class="archives-list">${renderArchivesList()}</ul>
</div>
`
}

function renderArchivesList () {
var filtered = archives.filter(a => (a.title && a.title.toLowerCase().includes(currentFilter)) || (a.description && a.description.toLowerCase().includes(currentFilter)))

return yo`<ul class="archivs-list">${filtered.map(renderArchive)}</ul>`
}

function renderArchive (archive) {
var isSelected = selectedArchiveKey === archive.key
return yo`
<li class="archive ${isSelected ? 'selected' : ''} ${archive.isOwner ? '' : 'readonly'}" onclick=${onChangeSelectedArchive} data-key=${archive.key}>
<div class="info">
<span class="title" title="${archive.title} ${archive.isOwner ? '' : '(Read-only)'}">
${archive.title || 'Untitled'}
${archive.isOwner ? '' : yo`<i class="fa fa-eye"></i>`}
</span>
<span class="path" title=${archive.userSettings.localPath}>${archive.userSettings.localPath}</span>
</div>
${archive.isOwner ? '' : yo`<span class="readonly">Read-only</span>`}
<span class="description">${archive.description || yo`<em>No description</em>`}</span>
</li>
`
}

function renderArchiveTitle() {
var t = archive.info.title ? `"${archive.info.title}"` : 'site'
if (t.length > 100) {
t = t.slice(0, 96) + '..."'
}
return t
}
4 changes: 3 additions & 1 deletion app/lib/api-manifests/external/dat-archive.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ export default {
exportToFilesystem: 'promise',
exportToArchive: 'promise',

resolveName: 'promise'
resolveName: 'promise',

selectArchive: 'promise'
}
8 changes: 6 additions & 2 deletions app/lib/web-apis/dat-archive.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,22 @@ export default class DatArchive extends EventTarget {
static importFromFilesystem(opts={}) {
return dat.importFromFilesystem(opts)
}

static exportToFilesystem(opts={}) {
return dat.exportToFilesystem(opts)
}

static exportToArchive(opts={}) {
return dat.exportToArchive(opts)
}

static resolveName(name) {
return dat.resolveName(name)
}

static selectArchive (opts={}) {
return dat.selectArchive(opts)
}
}

function joinPath (url, path) {
Expand Down
4 changes: 0 additions & 4 deletions app/stylesheets/builtin-pages/create-archive-modal.less
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,4 @@ body {

.modal {
margin: 0;
}

.placeholder {
color: #aaa;
}
Loading

0 comments on commit 9ebc4d0

Please sign in to comment.