Skip to content

Commit 993a8e2

Browse files
authored
Autoptions (#17)
* Add Option to Always Show Site Auth * Update Internal Options * Auto Options Step 1 w/ Migrations * Update Migration and Logging
1 parent 1d8f6e5 commit 993a8e2

File tree

7 files changed

+267
-168
lines changed

7 files changed

+267
-168
lines changed

manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"manifest_version": 3,
3-
"version": "0.2.5",
3+
"version": "0.3.0",
44
"name": "Django Files",
5-
"description": "Django Files Web Extension designed to work with django-files/django-files.",
5+
"description": "Django Files Web Extension designed to work with github.com/django-files/django-files.",
66
"homepage_url": "https://github.com/django-files/web-extension",
77
"author": "Shane",
88
"commands": {

src/html/options.html

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,34 @@ <h1 class="align-middle">Django Files Extension</h1>
3333
<td class="bg-transparent text-end"><kbd id="mainKey">Unknown</kbd></td>
3434
</tr></tbody>
3535
</table>
36-
<form id="options-form">
36+
<form id="options-form" class="options">
3737
<div class="mb-2">
38-
<label for="url" class="form-label">Django Files URL</label>
39-
<input type="text" class="form-control" id="url" aria-describedby="urlHelp" autocomplete="off">
40-
<div id="urlHelp" class="form-text">The Full URL to your Django Files server.</div>
38+
<label for="siteUrl" class="form-label">Django Files URL</label>
39+
<input id="siteUrl" aria-describedby="siteUrlHelp" type="text" class="form-control" autocomplete="off">
40+
<div class="form-text" id="siteUrlHelp" >The Full URL to your Django Files server.</div>
4141
</div>
4242
<div class="mb-2">
43-
<label for="token" class="form-label">Auth Token</label>
44-
<input type="password" class="form-control" id="token" aria-describedby="tokenHelp" autocomplete="off">
45-
<div id="tokenHelp" class="form-text">Token From Django Files Settings.</div>
43+
<label for="authToken" class="form-label">Auth Token</label>
44+
<input id="authToken" aria-describedby="authTokenHelp" type="password" class="form-control" autocomplete="off">
45+
<div class="form-text" id="authTokenHelp">Token From Django Files Settings.</div>
4646
</div>
4747
<div class="mb-2">
4848
<label for="recentFiles" class="form-label">Recent Files</label>
49-
<input type="number" class="form-control" id="recentFiles" aria-describedby="recentFilesHelp" autocomplete="off">
50-
<div id="recentFilesHelp" class="form-text">Number of Recent Files in Popup (0 to disable).</div>
49+
<input id="recentFiles" aria-describedby="recentFilesHelp" type="number" class="form-control" autocomplete="off">
50+
<div class="form-text" id="recentFilesHelp">Recent Files (0-99) in Popup (0 to disable).</div>
5151
</div>
5252
<div class="form-check form-switch mb-2">
53-
<input class="form-check-input" type="checkbox" role="switch" id="contextMenu">
53+
<input class="form-check-input" id="contextMenu" type="checkbox" role="switch">
5454
<label class="form-check-label" for="contextMenu" aria-describedby="contextMenuHelp">Enable Right Click Menu</label>
5555
</div>
56-
<div class="form-check form-switch mb-3">
57-
<input class="form-check-input" type="checkbox" role="switch" id="showUpdate">
56+
<div class="form-check form-switch mb-2">
57+
<input class="form-check-input" id="checkAuth" type="checkbox" role="switch">
58+
<label class="form-check-label" for="checkAuth" aria-describedby="checkAuthHelp">Always Check for Site Auth</label>
59+
</div>
60+
<div class="form-check form-switch mb-2">
61+
<input class="form-check-input" id="showUpdate" type="checkbox" role="switch">
5862
<label class="form-check-label" for="showUpdate" aria-describedby="showUpdateHelp">Show Release Notes on Update</label>
5963
</div>
60-
<button id="submit" type="submit" class="btn btn-outline-success w-100">
61-
Save Options <i class="fa-regular fa-floppy-disk ms-2"></i></button>
6264
</form>
6365
</div>
6466
<div class="text-center">
@@ -76,10 +78,6 @@ <h1 class="align-middle">Django Files Extension</h1>
7678
</div>
7779
</div>
7880

79-
<div id="bottom-container" class="position-fixed bottom-0 end-0">
80-
<div id="toast-container" class=""></div>
81-
</div>
82-
8381
<script type="text/javascript" src="../dist/polyfill/browser-polyfill.min.js"></script>
8482
<script type="text/javascript" src="../dist/jquery/jquery.min.js"></script>
8583
<script type="text/javascript" src="../dist/bootstrap/bootstrap.bundle.min.js"></script>

src/html/popup.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ <h2>Django Files Extension</h2>
4141
<thead class="visually-hidden"><tr><th>Number</th><th>File URL</th></tr></thead>
4242
<tbody></tbody>
4343
</table>
44-
<div id="error-alert" class="alert alert-warning mt-2 mb-0" role="alert" style="display: none;" ></div>
44+
<div id="error-alert" class="alert alert-warning mt-2 mb-0 visually-hidden" role="alert"></div>
4545
</div>
4646

4747
<script type="text/javascript" src="../dist/polyfill/browser-polyfill.min.js"></script>

src/js/auth.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
// eslint-disable-next-line no-extra-semi
44
;(async () => {
5-
console.log('auth.js')
6-
const response = await chrome.runtime.sendMessage(getCredentials())
7-
console.log(response)
5+
const credentials = getCredentials()
6+
if (credentials) {
7+
await chrome.runtime.sendMessage(credentials)
8+
}
89
})()
910

1011
/**
@@ -15,7 +16,7 @@
1516
function getCredentials() {
1617
const siteUrl = document.getElementById('site-url')
1718
const authToken = document.getElementById('auth-token')
18-
if (siteUrl && authToken) {
19+
if (siteUrl?.value && authToken?.value) {
1920
return {
2021
siteUrl: siteUrl.value,
2122
authToken: authToken.value,

src/js/options.js

Lines changed: 70 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,97 @@
11
// JS for options.html
22

33
document.addEventListener('DOMContentLoaded', initOptions)
4-
document.getElementById('options-form').addEventListener('submit', saveOptions)
5-
document.getElementById('submit').addEventListener('click', saveOptions)
4+
5+
document
6+
.querySelectorAll('input')
7+
.forEach((el) => el.addEventListener('change', saveOptions))
8+
document
9+
.getElementById('options-form')
10+
.addEventListener('submit', (e) => e.preventDefault())
11+
12+
chrome.runtime.onMessage.addListener(onMessage)
613

714
/**
815
* Options Init Function
916
* @function initOptions
1017
*/
1118
async function initOptions() {
12-
console.log('initOptions')
13-
const { auth, options } = await chrome.storage.sync.get(['auth', 'options'])
14-
console.log(auth, options)
15-
const url_input = document.getElementById('url')
16-
if (auth?.url) {
17-
url_input.value = auth.url
18-
} else {
19-
url_input.placeholder = 'https://example.com'
20-
url_input.focus()
21-
}
19+
// console.log('initOptions')
2220
document.getElementById('version').textContent =
2321
chrome.runtime.getManifest().version
24-
document.getElementById('token').value = auth?.token || ''
25-
document.getElementById('recentFiles').value = options.recentFiles || '10'
26-
document.getElementById('contextMenu').checked = options.contextMenu
27-
document.getElementById('showUpdate').checked = options.showUpdate
22+
23+
const { options } = await chrome.storage.sync.get(['options'])
24+
console.log('options:', options)
25+
updateOptions(options)
26+
if (!options?.siteUrl) {
27+
const siteUrl = document.getElementById('siteUrl')
28+
siteUrl.placeholder = 'https://example.com'
29+
siteUrl.focus()
30+
}
31+
2832
const commands = await chrome.commands.getAll()
2933
document.getElementById('mainKey').textContent =
3034
commands.find((x) => x.name === '_execute_action').shortcut || 'Not Set'
3135
}
3236

3337
/**
34-
* Save Options Submit Callback
38+
* Save Options Callback
3539
* @function saveOptions
36-
* @param {SubmitEvent} event
40+
* @param {FormDataEvent} event
3741
*/
3842
async function saveOptions(event) {
39-
console.log('saveOptions:', event)
40-
event.preventDefault()
41-
let auth = {
42-
url: document.getElementById('url').value.replace(/\/$/, ''),
43-
token: document.getElementById('token').value,
43+
// console.log('saveOptions:', event)
44+
const { options } = await chrome.storage.sync.get(['options'])
45+
if (event.target.type === 'checkbox') {
46+
options[event.target.id] = event.target.checked
47+
} else if (event.target.id === 'siteUrl') {
48+
event.target.value = event.target.value.replace(/\/+$/, '')
49+
options[event.target.id] = event.target.value
50+
} else if (event.target.id === 'recentFiles') {
51+
const number = parseFloat(event.target.value)
52+
console.log('number:', number)
53+
if (!isNaN(number) && number <= 99) {
54+
console.log('number.toString():', number.toString())
55+
event.target.value = number.toString()
56+
options[event.target.id] = event.target.value
57+
} else {
58+
event.target.value = options[event.target.id]
59+
}
60+
} else {
61+
options[event.target.id] = event.target.value
4462
}
45-
console.log('auth:', auth)
46-
let options = {}
47-
options.recentFiles = document.getElementById('recentFiles').value
48-
options.contextMenu = document.getElementById('contextMenu').checked
49-
options.showUpdate = document.getElementById('showUpdate').checked
63+
console.log(`Set: "${event.target.id}" to target:`, event.target)
5064
console.log('options:', options)
51-
await chrome.storage.sync.set({ auth, options })
52-
document.getElementById('url').value = auth.url
53-
showToast('Options Saved')
65+
await chrome.storage.sync.set({ options })
66+
}
67+
68+
/**
69+
* On Message Callback
70+
* @function onMessage
71+
* @param {Object} message
72+
*/
73+
async function onMessage(message) {
74+
// console.log('onMessage: message, sender:', message, sender)
75+
if (message === 'reload-options') {
76+
window.location.reload()
77+
}
5478
}
5579

5680
/**
57-
* Show Bootstrap Toast
58-
* Requires: jQuery
59-
* @function showToast
60-
* @param {String} message
61-
* @param {String} bsClass
81+
* Update Options
82+
* @function initOptions
83+
* @param {Object} options
6284
*/
63-
function showToast(message, bsClass = 'success') {
64-
// TODO: Remove jQuery Dependency
65-
const toastEl = $(
66-
'<div class="toast align-items-center border-0 my-3" role="alert" aria-live="assertive" aria-atomic="true">\n' +
67-
' <div class="d-flex">\n' +
68-
' <div class="toast-body">Options Saved</div>\n' +
69-
' <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>\n' +
70-
' </div>\n' +
71-
'</div>'
72-
)
73-
toastEl.find('.toast-body').text(message)
74-
toastEl.addClass('text-bg-' + bsClass)
75-
$('#toast-container').append(toastEl)
76-
const toast = new bootstrap.Toast(toastEl) // eslint-disable-line
77-
toast.show()
85+
function updateOptions(options) {
86+
for (const [key, value] of Object.entries(options)) {
87+
// console.log(`${key}: ${value}`)
88+
const element = document.getElementById(key)
89+
if (element) {
90+
if (typeof value === 'boolean') {
91+
element.checked = value
92+
} else if (typeof value === 'string') {
93+
element.value = value
94+
}
95+
}
96+
}
7897
}

0 commit comments

Comments
 (0)