Skip to content

Commit

Permalink
Pin - rich text editor + theme
Browse files Browse the repository at this point in the history
  • Loading branch information
Bowserinator committed Aug 1, 2023
1 parent 149fc2e commit 63edff4
Show file tree
Hide file tree
Showing 8 changed files with 492 additions and 54 deletions.
19 changes: 17 additions & 2 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ board page:
- save sort preference - localstoragen
- instead of board fixed size adaptive columns



- also maybe compact left side more?
- toggle
- autocomplete keyboard nav
Expand All @@ -35,8 +33,25 @@ make it so editors can also update board and share


pins:
- have a dropdown in new pin
- select what type of modal to use
- markdown is current
- image gallery - preview images, only file upload
- link - select link, preview
- review - same as markdown, but add score
- no file upload
- pin colors

pin create/edit modal:
- show last edited in corner
- https://github.com/patleeman/quill-markdown-shortcuts
- https://github.com/visualjerk/quill-magic-url
- https://github.com/NoelOConnell/quill-image-uploader
- https://vueup.github.io/vue-quill/guide/modules.html
- theme for the custom editor



- board dropdown
- edit
- share
Expand Down
65 changes: 65 additions & 0 deletions assets/css/quill-theme.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.ql-container {
font-family: 'Tenor Sans', Arial, sans-serif;
font-size: 1rem;
height: 250px;
overflow-y: auto;
}

.ql-toolbar.ql-snow {
background: rgba(var(--v-theme-on-surface-variant), 0.5);
box-shadow: 0px 11px 15px -7px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, 0.2)),
0px 24px 38px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, 0.14)),
0px 9px 46px 8px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, 0.12));
}

.ql-snow .ql-picker-options,
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
background: rgb(var(--v-theme-on-surface-variant));
border: 1px solid #444;
}

/* Borders */
.ql-toolbar.ql-snow,
.ql-container.ql-snow,
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
border: 1px solid #444;
}

/* Text color in toolbar */
.ql-snow .ql-picker {
color: rgba(var(--v-theme-on-surface), 0.7);
}

/* Icon fill */
.ql-snow .ql-fill,
.ql-snow .ql-stroke.ql-fill {
fill: rgb(var(--v-theme-on-surface));
}
.ql-snow .ql-stroke {
stroke: rgb(var(--v-theme-on-surface));
}

/* Active selected */
.ql-snow.ql-toolbar button.ql-active,
.ql-snow .ql-toolbar button.ql-active,
.ql-snow.ql-toolbar .ql-picker-label.ql-active,
.ql-snow .ql-toolbar .ql-picker-label.ql-active,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected {
background: #555;
color: #eee;
}

/* Hover */
.ql-snow.ql-toolbar button:hover,
.ql-snow .ql-toolbar button:hover,
.ql-snow.ql-toolbar button:focus,
.ql-snow .ql-toolbar button:focus,
.ql-snow.ql-toolbar .ql-picker-label:hover,
.ql-snow .ql-toolbar .ql-picker-label:hover,
.ql-snow.ql-toolbar .ql-picker-item:hover,
.ql-snow .ql-toolbar .ql-picker-item:hover {
background: #777;
color: #eee;
}

4 changes: 2 additions & 2 deletions components/board/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Example usage:

<v-btn
v-for="(col, index) in swatches" :key="col"
density="compact"
density="compact" width="40" style="min-width: 40px;"
:color="col" class="mr-1 mb-1"
@click="[color, selectedSwatchIndex] = [col, index]"
>
Expand Down Expand Up @@ -91,7 +91,7 @@ export default {
this.description = this.board?.desc || 'Default description';
this.color = this.board?.color || swatches[0];
this.name = this.board?.name;
this.selectedSwatchIndex = swatches.indexOf(this.color.toUpperCase()) || 0;
this.selectedSwatchIndex = Math.max(0, swatches.indexOf(this.color.toUpperCase()));
}
},
methods: {
Expand Down
140 changes: 140 additions & 0 deletions components/pin/Modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<!--
TODO
-->

<template>
<v-dialog
v-model="showModal"
width="720"
>
<v-card rounded="0" width="720" class="py-2">
<v-card-text class="px-4">
<h1 class="mb-4 text-truncate">{{ editMode ? 'Edit' : 'Create' }} Pin</h1>

<!-- TODO: type, content box, attachments
or insert files by url?? -->

<client-only>
<QuillEditor
theme="snow" contentType="html" v-model:content="content"
:toolbar="[['bold', 'italic', 'underline', 'strike'], ['image', 'link'], [{ 'align': [] }], ['clean']]"
/>
<br><br>
</client-only>

<!-- <v-textarea
v-model="description" density="compact" class="mb-4" label="Description"
oninput="this.value = this.value.substring(0, 300)"
rounded="0" variant="solo-filled"></v-textarea> -->

<v-btn
v-for="(col, index) in swatches" :key="col"
density="compact" width="40" style="min-width: 40px;"
:color="col" class="mr-1 mb-1"
@click="[color, selectedSwatchIndex] = [col, index]"
>
<v-icon v-if="selectedSwatchIndex === index" icon="mdi-check" />
</v-btn>

<v-file-input
label="Attachments" variant="solo-filled"
multiple show-size rounded=0 chips
density="compact" style="min-height: 47px"
clearable counter class="mt-2 mb-4"
/>
</v-card-text>
<v-card-actions class="mr-3">
<v-spacer />
<v-btn color="primary" @click="$emit('update', false)">Cancel</v-btn>
<v-btn color="primary" variant="elevated" :loading="loading" @click="createPin">{{ editMode ? 'Apply' : 'Create' }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script>
const QuillEditor = process.client ? (await import('@vueup/vue-quill')).QuillEditor : null;
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import '~/assets/css/quill-theme.css';

// TODO: move to shared js file
const swatches =
'#F44336,#E91E63,#9C27B0,#673AB7,#3F51B5,#2196F3,#03A9F4,#009688,#4CAF50,#8BC34A,#CDDC39,#FFC107,#FF9800,#FF5722,#607D8B'.split(',');


export default {
name: 'PinModal',
components: {
QuillEditor
},
props: {
editMode: { // Edit existing pin instead of create
type: Boolean,
default: false
},
pin: {
type: Object,
default: () => ({})
},
show: {
type: Boolean,
required: true
}
},
data() {
return {
content: this.pin?.content,
color: this.pin?.metadata?.color,
loading: false,

swatches,
selectedSwatchIndex: 0
};
},
computed: {
showModal: {
get() { return this.show; },
set(val) { this.$emit('show', val); }
}
},
watch: {
show() {
this.content = this.pin?.content || '';
this.color = this.pin?.metadata?.color || swatches[0];
this.selectedSwatchIndex = Math.max(0, swatches.indexOf(this.color.toUpperCase()));
}
},
methods: {
async createPin() {
// TODO: per type checks
console.log(this.content)
if (!this.content) {
this.$emit('error', 'Content cannot be empty');
return;
}

let params = {
name: this.name,
desc: this.description,
color: this.color,
};

// Editing requires id
if (!this.editMode)
params.id = this.pin.id;

this.loading = true;
try {
await this.$fetchApi('/api/board/pins', this.editMode ? 'PUT' : 'POST', params);
} catch (e) {
let errorMsg = `Failed to modify pin: ${this.$apiErrorToString(e)}`;
this.$emit('error', errorMsg);
this.loading = false;
return;
}
this.loading = false;
this.$emit('update', true);
}
}
}
</script>
Empty file removed components/pins/Modal.vue
Empty file.
Loading

0 comments on commit 63edff4

Please sign in to comment.