From 18193778971e27d18b5a35df8c2d0e2953b48111 Mon Sep 17 00:00:00 2001
From: Ramires Viana <59319979+ramiresviana@users.noreply.github.com>
Date: Tue, 16 Feb 2021 15:39:11 +0000
Subject: [PATCH] feat: improved sharing prompt
---
frontend/public/themes/dark.css | 4 +-
frontend/src/components/prompts/Share.vue | 172 +++++++++++++---------
frontend/src/css/_share.css | 7 +-
frontend/src/css/dashboard.css | 12 ++
http/share.go | 12 --
5 files changed, 116 insertions(+), 91 deletions(-)
diff --git a/frontend/public/themes/dark.css b/frontend/public/themes/dark.css
index 9a5be1f7..2a70351c 100644
--- a/frontend/public/themes/dark.css
+++ b/frontend/public/themes/dark.css
@@ -119,8 +119,8 @@ nav > div {
.dashboard p label {
color: var(--textPrimary);
}
-.card#share ul li input,
-.card#share ul li select,
+.card#share input,
+.card#share select,
.input {
background: var(--surfaceSecondary);
color: var(--textPrimary);
diff --git a/frontend/src/components/prompts/Share.vue b/frontend/src/components/prompts/Share.vue
index 043847d8..f4163975 100644
--- a/frontend/src/components/prompts/Share.vue
+++ b/frontend/src/components/prompts/Share.vue
@@ -4,61 +4,82 @@
<h2>{{ $t('buttons.share') }}</h2>
</div>
- <div class="card-content">
- <ul>
+ <template v-if="listing">
+ <div class="card-content">
+ <table>
+ <tr>
+ <th>#</th>
+ <th>{{ $t('settings.shareDuration') }}</th>
+ <th></th>
+ <th></th>
+ </tr>
- <li v-for="link in links" :key="link.hash">
- <a :href="buildLink(link.hash)" target="_blank">
- <template v-if="link.expire !== 0">{{ humanTime(link.expire) }}</template>
- <template v-else>{{ $t('permanent') }}</template>
- </a>
+ <tr v-for="link in links" :key="link.hash">
+ <td>{{ link.hash }}</td>
+ <td>
+ <template v-if="link.expire !== 0">{{ humanTime(link.expire) }}</template>
+ <template v-else>{{ $t('permanent') }}</template>
+ </td>
+ <td class="small">
+ <button class="action copy-clipboard"
+ :data-clipboard-text="buildLink(link.hash)"
+ :aria-label="$t('buttons.copyToClipboard')"
+ :title="$t('buttons.copyToClipboard')"><i class="material-icons">content_paste</i></button>
+ </td>
+ <td class="small">
+ <button class="action"
+ @click="deleteLink($event, link)"
+ :aria-label="$t('buttons.delete')"
+ :title="$t('buttons.delete')"><i class="material-icons">delete</i></button>
+ </td>
+ </tr>
+ </table>
+ </div>
- <button class="action"
- @click="deleteLink($event, link)"
- :aria-label="$t('buttons.delete')"
- :title="$t('buttons.delete')"><i class="material-icons">delete</i></button>
+ <div class="card-action">
+ <button class="button button--flat button--grey"
+ @click="$store.commit('closeHovers')"
+ :aria-label="$t('buttons.close')"
+ :title="$t('buttons.close')">{{ $t('buttons.close') }}</button>
+ <button class="button button--flat button--blue"
+ @click="() => switchListing()"
+ :aria-label="$t('buttons.new')"
+ :title="$t('buttons.new')">{{ $t('buttons.new') }}</button>
+ </div>
+ </template>
- <button class="action copy-clipboard"
- :data-clipboard-text="buildLink(link.hash)"
- :aria-label="$t('buttons.copyToClipboard')"
- :title="$t('buttons.copyToClipboard')"><i class="material-icons">content_paste</i></button>
- </li>
+ <template v-else>
+ <div class="card-content">
+ <p>{{ $t('settings.shareDuration') }}</p>
+ <div class="input-group input">
+ <input v-focus
+ type="number"
+ max="2147483647"
+ min="1"
+ @keyup.enter="submit"
+ v-model.trim="time">
+ <select class="right" v-model="unit" :aria-label="$t('time.unit')">
+ <option value="seconds">{{ $t('time.seconds') }}</option>
+ <option value="minutes">{{ $t('time.minutes') }}</option>
+ <option value="hours">{{ $t('time.hours') }}</option>
+ <option value="days">{{ $t('time.days') }}</option>
+ </select>
+ </div>
+ <p>{{ $t('prompts.optionalPassword') }}</p>
+ <input class="input input--block" type="password" v-model.trim="password">
+ </div>
- <li v-if="!hasPermanent">
- <div>
- <input type="password" :placeholder="$t('prompts.optionalPassword')" v-model="passwordPermalink">
- <a @click="getPermalink" :aria-label="$t('buttons.permalink')">{{ $t('buttons.permalink') }}</a>
- </div>
- </li>
-
- <li>
- <input v-focus
- type="number"
- max="2147483647"
- min="0"
- @keyup.enter="submit"
- v-model.trim="time">
- <select v-model="unit" :aria-label="$t('time.unit')">
- <option value="seconds">{{ $t('time.seconds') }}</option>
- <option value="minutes">{{ $t('time.minutes') }}</option>
- <option value="hours">{{ $t('time.hours') }}</option>
- <option value="days">{{ $t('time.days') }}</option>
- </select>
- <input type="password" :placeholder="$t('prompts.optionalPassword')" v-model="password">
- <button class="action"
- @click="submit"
- :aria-label="$t('buttons.create')"
- :title="$t('buttons.create')"><i class="material-icons">add</i></button>
- </li>
- </ul>
- </div>
-
- <div class="card-action">
- <button class="button button--flat"
- @click="$store.commit('closeHovers')"
- :aria-label="$t('buttons.close')"
- :title="$t('buttons.close')">{{ $t('buttons.close') }}</button>
- </div>
+ <div class="card-action">
+ <button class="button button--flat button--grey"
+ @click="() => switchListing()"
+ :aria-label="$t('buttons.cancel')"
+ :title="$t('buttons.cancel')">{{ $t('buttons.cancel') }}</button>
+ <button class="button button--flat button--blue"
+ @click="submit"
+ :aria-label="$t('buttons.share')"
+ :title="$t('buttons.share')">{{ $t('buttons.share') }}</button>
+ </div>
+ </template>
</div>
</template>
@@ -75,11 +96,10 @@ export default {
return {
time: '',
unit: 'hours',
- hasPermanent: false,
links: [],
clip: null,
password: '',
- passwordPermalink: ''
+ listing: true
}
},
computed: {
@@ -104,11 +124,8 @@ export default {
this.links = links
this.sort()
- for (let link of this.links) {
- if (link.expire === 0) {
- this.hasPermanent = true
- break
- }
+ if (this.links.length == 0) {
+ this.listing = false
}
} catch (e) {
this.$showError(e)
@@ -125,22 +142,25 @@ export default {
},
methods: {
submit: async function () {
- if (!this.time) return
+ let isPermanent = !this.time || this.time == 0
try {
- const res = await api.create(this.url, this.password, this.time, this.unit)
+ let res = null
+
+ if (isPermanent) {
+ res = await api.create(this.url, this.password)
+ } else {
+ res = await api.create(this.url, this.password, this.time, this.unit)
+ }
+
this.links.push(res)
this.sort()
- } catch (e) {
- this.$showError(e)
- }
- },
- getPermalink: async function () {
- try {
- const res = await api.create(this.url, this.passwordPermalink)
- this.links.push(res)
- this.sort()
- this.hasPermanent = true
+
+ this.time = ''
+ this.unit = 'hours'
+ this.password = ''
+
+ this.listing = true
} catch (e) {
this.$showError(e)
}
@@ -149,8 +169,11 @@ export default {
event.preventDefault()
try {
await api.remove(link.hash)
- if (link.expire === 0) this.hasPermanent = false
this.links = this.links.filter(item => item.hash !== link.hash)
+
+ if (this.links.length == 0) {
+ this.listing = false
+ }
} catch (e) {
this.$showError(e)
}
@@ -167,6 +190,13 @@ export default {
if (b.expire === 0) return 1
return new Date(a.expire) - new Date(b.expire)
})
+ },
+ switchListing () {
+ if (this.links.length == 0 && !this.listing) {
+ this.$store.commit('closeHovers')
+ }
+
+ this.listing = !this.listing
}
}
}
diff --git a/frontend/src/css/_share.css b/frontend/src/css/_share.css
index c043a73c..a5f2d35f 100644
--- a/frontend/src/css/_share.css
+++ b/frontend/src/css/_share.css
@@ -70,9 +70,4 @@
padding: .5em;
text-align: center;
animation: .2s opac forwards;
-}
-
-.share__promt__card {
- max-width: max-content !important;
- width: auto !important;
-}
+}
\ No newline at end of file
diff --git a/frontend/src/css/dashboard.css b/frontend/src/css/dashboard.css
index b29e907f..52a8d41e 100644
--- a/frontend/src/css/dashboard.css
+++ b/frontend/src/css/dashboard.css
@@ -226,6 +226,18 @@ table tr>*:last-child {
opacity: 1;
}
+.card#share .input-group {
+ display: flex;
+}
+
+.card#share .input-group * {
+ border: none;
+}
+
+.card#share .input-group input {
+ flex: 1;
+}
+
.overlay {
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
diff --git a/http/share.go b/http/share.go
index 9ee28587..d813500e 100644
--- a/http/share.go
+++ b/http/share.go
@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"net/http"
- "path"
"sort"
"strconv"
"strings"
@@ -91,17 +90,6 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
defer r.Body.Close()
}
- if body.Expires == "" {
- var err error
- s, err = d.store.Share.GetPermanent(r.URL.Path, d.user.ID)
- if err == nil {
- if _, err := w.Write([]byte(path.Join(d.server.BaseURL, "/share/", s.Hash))); err != nil {
- return http.StatusInternalServerError, err
- }
- return 0, nil
- }
- }
-
bytes := make([]byte, 6)
_, err := rand.Read(bytes)
if err != nil {