Skip to content

Commit 2671261

Browse files
author
Philipp Heckel
committed
Fix formatting in curl and UI
1 parent 1a621ac commit 2671261

File tree

3 files changed

+62
-18
lines changed

3 files changed

+62
-18
lines changed

server/curl.tmpl

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
{{- /*gotype: heckel.io/pcopy.webTemplateConfig*/ -}}
1+
{{- /*gotype: heckel.io/pcopy/server.webTemplateConfig*/ -}}
22
{{- $url := .Config.ServerAddr | expandServerAddr -}}
33
NAME
44
pcopy - copy/paste across machines
55

66
USAGE:
7-
curl [-T FILE] [-d DATA] [-u:PASS] {{$url}}[/FILENAME][?s=1][&m=rw|ro][&t=<duration>][&f=text|json]
7+
curl [-T FILE] [-d DATA] [-u:PASS] {{$url}}[/FILENAME][?s=1][&m=rw|ro][&t=DURATION][&f=text|json]
88

99
DESCRIPTION:
1010
This is is the curl-endpoint for pcopy, a tool to copy/paste across machines. You may use
@@ -30,10 +30,10 @@ DESCRIPTION:
3030

3131
OPTIONS:
3232
Query params:
33-
?s=1 stream data without storing on the server
34-
?m=rw|ro defines whether to set the file mode as read-write or read-only (default: {{index .Config.FileModesAllowed 0}}, allowed: {{stringsJoin .Config.FileModesAllowed ", "}})
35-
?t=<duration> time-to-live (TTL) for this file, after which it will be deleted (default/max: {{if .Config.FileExpireAfter}}{{.Config.FileExpireAfter | durationToHuman}}{{else}}never{{end}})
36-
?f=text|json output format for PUT/POSTs (default: text)
33+
?s=1 stream data without storing on the server
34+
?m=rw|ro defines whether to set the file mode as read-write or read-only (default: {{index .Config.FileModesAllowed 0}}, allowed: {{stringsJoin .Config.FileModesAllowed ", "}})
35+
?t=DURATION time-to-live after which the file will be deleted (default: {{if .Config.FileExpireAfterDefault}}{{.Config.FileExpireAfterDefault | durationToHuman}}{{else}}never{{end}}, nontext-max: {{if .Config.FileExpireAfterNonTextMax}}{{.Config.FileExpireAfterNonTextMax | durationToHuman}}{{else}}never{{end}}, text-max: {{if .Config.FileExpireAfterTextMax}}{{.Config.FileExpireAfterTextMax | durationToHuman}}{{else}}never{{end}})
36+
?f=text|json output format for PUT/POSTs (default: text)
3737

3838
Common curl options (see 'man curl' for more):
3939
-T FILE uploads file FILE to the server
@@ -47,7 +47,7 @@ LIMITS:
4747
Total clipboard size limit: {{if .Config.ClipboardSizeLimit}}{{.Config.ClipboardSizeLimit | bytesToHuman }}{{else}}no limit{{end}}
4848
Total number of files: {{if .Config.ClipboardCountLimit}} max. {{.Config.ClipboardCountLimit }} files{{else}}no limit{{end}}
4949
Per-file size limit: {{if .Config.FileSizeLimit}}{{.Config.FileSizeLimit | bytesToHuman }}{{else}}no limit{{end}}
50-
Per-file expiration: {{if .Config.FileExpireAfter}}deleted after {{.Config.FileExpireAfter | durationToHuman }}{{else}}never{{end}}
50+
Per-file expiration limits: {{if .Config.FileExpireAfterTextMax}}{{.Config.FileExpireAfterTextMax | durationToHuman }}{{else}}never{{end}} if text, {{if .Config.FileExpireAfterNonTextMax}}{{.Config.FileExpireAfterNonTextMax | durationToHuman }}{{else}}never{{end}} otherwise
5151
Allowed file modes: {{stringsJoin .Config.FileModesAllowed ", "}}
5252

5353
To find out more about pcopy, check out https://heckel.io/pcopy.

server/index.gohtml

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{- /*gotype: heckel.io/pcopy.webTemplateConfig*/ -}}
1+
{{- /*gotype: heckel.io/pcopy/server.webTemplateConfig*/ -}}
22
<!DOCTYPE html>
33
<html lang="en">
44
<head>
@@ -83,16 +83,21 @@
8383
</div>
8484
<div class="col-auto">
8585
<div class="divider"></div>
86-
<label for="ttl">Expires: {{if lt .Config.FileExpireAfter.Seconds 1800.0}} {{.Config.FileExpireAfter | durationToHuman}}{{end}}</label>
86+
<label for="ttl">Expires: {{if lt .Config.FileExpireAfterDefault.Seconds 600.0}} {{.Config.FileExpireAfterDefault | durationToHuman}}{{end}}</label>
8787
<select id="ttl" class="button">
88+
<option value="600">10 min</option>
8889
<option value="1800">30 min</option>
8990
<option value="3600">1 hour</option>
9091
<option value="10800">3 hours</option>
92+
<option value="21600">6 hours</option>
9193
<option value="86400">1 day</option>
9294
<option value="259200">3 days</option>
9395
<option value="604800">1 week</option>
9496
<option value="1814400">3 weeks</option>
95-
<option value="3628800">6 weeks</option>
97+
<option value="5184000">2 months</option>
98+
<option value="15552000">6 months</option>
99+
<option value="31536000">1 year</option>
100+
<option value="63072000">2 years</option>
96101
<option value="0">never</option>
97102
</select>
98103
</div>
@@ -136,7 +141,7 @@
136141
<b>Total clipboard size limit:</b> <em>{{if .Config.ClipboardSizeLimit}}{{.Config.ClipboardSizeLimit | bytesToHuman }}{{else}}no limit{{end}}</em><br/>
137142
<b>Total number of files:</b> <em>{{if .Config.ClipboardCountLimit}} max. {{.Config.ClipboardCountLimit }} files{{else}}no limit{{end}}</em><br/>
138143
<b>Per-file size limit:</b> <em>{{if .Config.FileSizeLimit}}{{.Config.FileSizeLimit | bytesToHuman }}{{else}}no limit{{end}}</em><br/>
139-
<b>Per-file expiration:</b> <em>{{if .Config.FileExpireAfter}}deleted after {{.Config.FileExpireAfter | durationToHuman }}{{else}}never{{end}}</em>
144+
<b>Per-file expiration limits:</b> <em>{{if .Config.FileExpireAfterTextMax}}{{.Config.FileExpireAfterTextMax | durationToHuman }}{{else}}never{{end}} if text, {{if .Config.FileExpireAfterNonTextMax}}{{.Config.FileExpireAfterNonTextMax | durationToHuman }}{{else}}never{{end}} otherwise</em>
140145
</p>
141146
</div>
142147
<div id="info-upload-header-active" class="info-header">
@@ -243,7 +248,9 @@
243248
KeyLenBytes: {{.KeyLenBytes}},
244249
DefaultPort: {{.DefaultPort}},
245250
FileSizeLimit: {{.Config.FileSizeLimit}},
246-
FileExpireAfter: {{.Config.FileExpireAfter.Seconds}}
251+
FileExpireAfterDefault: {{.Config.FileExpireAfterDefault.Seconds}},
252+
FileExpireAfterTextMax: {{.Config.FileExpireAfterTextMax.Seconds}},
253+
FileExpireAfterNonTextMax: {{.Config.FileExpireAfterNonTextMax.Seconds}}
247254
}
248255
</script>
249256
<script src="static/vendor/crypto-js.min.js"></script>

server/static/js/app.js

+43-6
Original file line numberDiff line numberDiff line change
@@ -217,24 +217,57 @@ headerStream.addEventListener('change', (e) => { storeStreamEnabled(e.target.che
217217

218218
headerTTL.addEventListener('change', (e) => {
219219
storeTTL(e.target.value)
220+
changeWidth(e.target)
220221
})
221222

222223
let ttl = getTTL()
223224
Array.from(headerTTL.options).forEach(function(option) {
224-
const removeNeverOption = parseInt(option.value) === 0 && config.FileExpireAfter > 0
225-
const removeHigherOption = option.value > config.FileExpireAfter && config.FileExpireAfter > 0
226-
const isStoredTTL = ttl !== null && parseInt(option.value) === ttl
227-
if (removeNeverOption || removeHigherOption) {
225+
const value = parseInt(option.value)
226+
const allowOptionText = config.FileExpireAfterTextMax === 0 || (value > 0 && value <= config.FileExpireAfterTextMax)
227+
const allowOptionNonText = config.FileExpireAfterNonTextMax === 0 || (value > 0 && value <= config.FileExpireAfterNonTextMax)
228+
229+
// Remove option if not allowed
230+
if (!allowOptionText && !allowOptionNonText) {
228231
headerTTL.removeChild(option)
229-
} else if (isStoredTTL) {
232+
return
233+
}
234+
235+
// Change option text if only allowed for text or non-text
236+
if (allowOptionText && !allowOptionNonText) {
237+
option.text += " (text only)"
238+
} else if (!allowOptionText && allowOptionNonText) {
239+
option.text += " (non-text only)"
240+
}
241+
242+
// Select option if stored in local storage
243+
if (value === ttl || (value > 0 && value < ttl)) {
230244
option.selected = 'selected'
245+
changeWidth(headerTTL)
231246
}
232247
})
233248

234249
if (headerTTL.options.length === 0) {
235250
headerTTL.classList.add('hidden')
236251
}
237252

253+
/* From: https://stackoverflow.com/a/35567280/1440785 & https://jsfiddle.net/Hatchet/a0xzz6mf/ */
254+
function changeWidth(select) {
255+
var o = select.options[select.selectedIndex];
256+
var s = document.createElement('span');
257+
258+
s.textContent = o.textContent;
259+
260+
var ostyles = getComputedStyle(o);
261+
s.style.fontFamily = ostyles.fontFamily;
262+
s.style.fontStyle = ostyles.fontStyle;
263+
s.style.fontWeight = ostyles.fontWeight;
264+
s.style.fontSize = ostyles.fontSize;
265+
266+
document.body.appendChild(s);
267+
select.style.width = (s.offsetWidth + 30) + 'px';
268+
document.body.removeChild(s);
269+
}
270+
238271
/* Text field & saving text */
239272

240273
headerSaveButton.addEventListener('click', save)
@@ -726,7 +759,7 @@ function getTTL() {
726759
if (localStorage.getItem('ttl') !== null) {
727760
return parseInt(localStorage.getItem('ttl'))
728761
} else {
729-
return parseInt(headerTTL.value)
762+
return parseInt(config.FileExpireAfterDefault)
730763
}
731764
}
732765

@@ -750,6 +783,10 @@ function secondsToHuman(seconds) {
750783
function numberEnding (number) {
751784
return (number > 1) ? 's' : '';
752785
}
786+
let years = Math.floor(seconds / 31536000)
787+
if (years) {
788+
return years + ' year' + numberEnding(years);
789+
}
753790
let days = Math.floor((seconds %= 31536000) / 86400);
754791
if (days) {
755792
return days + ' day' + numberEnding(days);

0 commit comments

Comments
 (0)