diff options
-rw-r--r-- | client/src/App.vue | 15 | ||||
-rw-r--r-- | client/src/components/Header.vue | 5 | ||||
-rw-r--r-- | client/src/main.js | 2 | ||||
-rw-r--r-- | client/src/views/GetSmile.vue | 75 | ||||
-rw-r--r-- | server/service.raku | 26 |
5 files changed, 114 insertions, 9 deletions
diff --git a/client/src/App.vue b/client/src/App.vue index e137e15..92e6133 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -41,9 +41,20 @@ p { line-height:1.5; margin:0 0 1rem 0; } -.content-wrapper { - padding: 0.8rem; +.content-wrapper { padding: 1rem; } +@media screen and (min-width: 35.5em) { + .content-wrapper { padding: 2rem; } } +@media screen and (min-width: 48em) { + .content-wrapper { padding: 3rem; } +} +@media screen and (min-width: 64em) { + .content-wrapper { padding: 4rem; } +} +@media screen and (min-width: 80em) { + .content-wrapper { padding: 6rem; } +} + .card { background: var(--surface-e); padding: 2rem; diff --git a/client/src/components/Header.vue b/client/src/components/Header.vue index 2eedc83..04eaf5f 100644 --- a/client/src/components/Header.vue +++ b/client/src/components/Header.vue @@ -22,11 +22,6 @@ export default { label: 'Create Smiles', icon: 'pi pi-fw pi-user-plus', to: '/create' - }, - { - label: 'huh', - icon: 'pi pi-fw pi-user-plus', - to: '/5a1PNZAMafXGGEFU17xcRX3bx6wyebeK/lNtEBCOd5yLlXT5enRQoh4ai4q3vcg7F' } ] } diff --git a/client/src/main.js b/client/src/main.js index 03f0e65..5e2c6fc 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -13,6 +13,7 @@ import Toast from 'primevue/toast'; import ProgressBar from 'primevue/progressbar'; import Message from 'primevue/message'; import FileUpload from 'primevue/fileupload'; +import Image from 'primevue/image'; import 'primevue/resources/themes/lara-dark-blue/theme.css'; import 'primevue/resources/primevue.min.css'; @@ -33,5 +34,6 @@ app.component('Toast', Toast); app.component('Message', Message); app.component('ProgressBar', ProgressBar); app.component('FileUpload', FileUpload); +app.component('Image', Image); app.mount('#app'); diff --git a/client/src/views/GetSmile.vue b/client/src/views/GetSmile.vue index 1553a65..8d565ec 100644 --- a/client/src/views/GetSmile.vue +++ b/client/src/views/GetSmile.vue @@ -1,9 +1,82 @@ <template> <div class="get-smile"> <p id="subtitle">Get a Smile :)</p> + <ProgressBar v-if="showLoading" mode="indeterminate" style="height: .4em;" /> - {{ $route.params.id }} + <div v-if="!gotSmile && !showLoading" style="text-align: center;"> + <Button @click="getSmile" label="Try Again" + class="p-button-outlined p-button-info p-button-lg" icon="pi pi-refresh" /> + </div> + <div v-if="gotSmile" style="text-align: center;"> + <Button @click="again" label="Again!" icon="pi pi-refresh" /> + </div> + <div v-if="gotSmile" id="smile"> + </div> <Toast /> </div> </template> + +<script> +export default { + data() { + return { + name: '', + showLoading: true, + gotSmile: false, + id: this.$route.params.id, + } + }, + methods: { + beforeSend(xhr) { + xhr.formData.append('id', this.id); + + }, + again() { + document.getElementById('smile').innerHTML = ''; + this.getSmile(); + }, + getSmile() { + const toast = this.$toast; + + this.showLoading = true; + fetch( + `http://localhost:9090/smile/${this.id}`, + { cache: 'no-cache', referrerPolicy: 'no-referrer', responseType: 'blob' } + ).then(response => { + if (response.status === 404) + throw new Error(response.status + ' # ' + 'Smiles deleted or invalid link'); + if (response.status === 406) + throw new Error(response.status + ' # ' + 'No smiles available'); + if (!response.ok) + throw new Error('HTTP error, status = ' + response.status); + return response; + }).then(res => { + (async () => { + const blob = await res.blob(); + const img = new Image(); + img.src = URL.createObjectURL(blob); + await img.decode(); + document.getElementById('smile').append(img); + URL.revokeObjectURL(img.src); + })(); + + this.gotSmile = true; + }).catch(error => { + console.log(error) + toast.add({severity: 'error', summary: 'Service error', detail: error}); + }).finally(() => { + this.showLoading = false; + // <<<< -- fat arrows mess with polymode formatting. + }); + }, + }, + beforeMount() { + this.getSmile(); + }, +} +</script> + +<style> +img { max-width: 100%; padding: 1em; } +</style> diff --git a/server/service.raku b/server/service.raku index 638989c..1ccbb85 100644 --- a/server/service.raku +++ b/server/service.raku @@ -67,7 +67,7 @@ my $application = route { my Str @messages; @messages.push("Max file size exceeded") if $img.body-blob.bytes > 2097152; # 1024 * 1024 * 2 - @messages.push("Only png/jpeg allowed"); + @messages.push("Only png/jpeg allowed") if $img.content-type ne "image/png"|"image/jpeg"; $stored = False if @messages.elems; @@ -86,6 +86,30 @@ my $application = route { } } + get -> 'smile', $id { + my IO() $user-store = "%s/%s".sprintf: $store, $id; + + my $img; + if "$user-store/images".IO.d { + put "huh"; + my @imgs = dir("$user-store/images").grep(*.f); + if @imgs.elems { + $img = @imgs.pick(1).first; + } else { + response.status = 406; + } + } else { + response.status = 404; + } + + if $img { + static $img; + $img.unlink; + } else { + content 'text/plain', ''; + } + } + # Serving static assets. get -> 'js', *@path { static 'dist/js', @path; } get -> 'css', *@path { static 'dist/css', @path; } |