commit: 091532d577ae9a23f7a43f681bfd344f040c7738
parent bfdad56b0d4b4f8ed89295661ff8abba22dca7f0
Author: Ekaterina Vaartis <vaartis@kotobank.ch>
Date: Sun, 7 Jan 2024 02:45:49 +0300
Editing emojis in popover, pack creation/deletion
Also fixed some API calls since they weren't working apparently
Diffstat:
5 files changed, 272 insertions(+), 89 deletions(-)
diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.js b/src/components/settings_modal/admin_tabs/emoji_tab.js
@@ -1,20 +1,46 @@
+import { clone } from 'lodash'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import StringSetting from '../helpers/string_setting.vue'
import Checkbox from 'components/checkbox/checkbox.vue'
import StillImage from 'components/still-image/still-image.vue'
+import Select from 'components/select/select.vue'
+import Popover from 'components/popover/popover.vue'
+import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
+import ModifiedIndicator from '../helpers/modified_indicator.vue'
const EmojiTab = {
components: {
TabSwitcher,
StringSetting,
Checkbox,
- StillImage
+ StillImage,
+ Select,
+ Popover,
+ ConfirmModal,
+ ModifiedIndicator
},
data () {
return {
knownPacks: { },
- editedParts: { }
+ editedParts: { },
+ editedMetadata: { },
+ packName: '',
+ newPackName: '',
+ deleteModalVisible: false
+ }
+ },
+
+ computed: {
+ pack () {
+ return this.packName !== '' ? this.knownPacks[this.packName] : undefined
+ },
+ packMeta () {
+ if (this.editedMetadata[this.packName] === undefined) {
+ this.editedMetadata[this.packName] = clone(this.knownPacks[this.packName].pack)
+ }
+
+ return this.editedMetadata[this.packName]
}
},
@@ -25,37 +51,90 @@ const EmojiTab = {
importFromFS () {
this.$store.state.api.backendInteractor.importEmojiFromFS()
},
- emojiAddr (packName, name) {
- return `${this.$store.state.instance.server}/emoji/${encodeURIComponent(packName)}/${name}`
+ emojiAddr (name) {
+ return `${this.$store.state.instance.server}/emoji/${encodeURIComponent(this.packName)}/${name}`
},
- editEmoji (packName, shortcode) {
- if (this.editedParts[packName] === undefined) { this.editedParts[packName] = {} }
- this.editedParts[packName][shortcode] = {
- shortcode, file: this.knownPacks[packName].files[shortcode]
+ createEmojiPack () {
+ this.$store.state.api.backendInteractor.createEmojiPack(
+ { name: this.newPackName }
+ ).then(resp => resp.json()).then(resp => {
+ if (resp === 'ok') {
+ return this.refreshPackList()
+ } else {
+ return Promise.reject(resp)
+ }
+ }).then(done => {
+ this.$refs.createPackPopover.hidePopover()
+
+ this.packName = this.newPackName
+ this.newPackName = ''
+ })
+ },
+ deleteEmojiPack () {
+ this.$store.state.api.backendInteractor.deleteEmojiPack(
+ { name: this.packName }
+ ).then(resp => resp.json()).then(resp => {
+ if (resp === 'ok') {
+ return this.refreshPackList()
+ } else {
+ return Promise.reject(resp)
+ }
+ }).then(done => {
+ delete this.editedMetadata[this.packName]
+ delete this.editedParts[this.packName]
+
+ this.deleteModalVisible = false
+ this.packName = ''
+ })
+ },
+
+ metaEdited (prop) {
+ return this.pack && this.packMeta[prop] !== this.pack.pack[prop]
+ },
+ savePackMetadata () {
+ this.$store.state.api.backendInteractor.saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta }).then(
+ resp => resp.json()
+ ).then(resp => {
+ // Update actual pack data
+ this.pack.pack = resp
+ // Delete edited pack data, should auto-update itself
+ delete this.editedMetadata[this.packName]
+ })
+ },
+
+ editEmoji (shortcode) {
+ if (this.editedParts[this.packName] === undefined) { this.editedParts[this.packName] = {} }
+
+ if (this.editedParts[this.packName][shortcode] === undefined) {
+ this.editedParts[this.packName][shortcode] = {
+ shortcode, file: this.knownPacks[this.packName].files[shortcode]
+ }
}
},
- saveEditedEmoji (packName, shortcode) {
- const edited = this.editedParts[packName][shortcode]
+ saveEditedEmoji (shortcode) {
+ const edited = this.editedParts[this.packName][shortcode]
this.$store.state.api.backendInteractor.updateEmojiFile(
- { packName, shortcode, newShortcode: edited.shortcode, newFilename: edited.file, force: false }
+ { packName: this.packName, shortcode, newShortcode: edited.shortcode, newFilename: edited.file, force: false }
).then(resp =>
resp.ok ? resp.json() : resp.text().then(respText => Promise.reject(respText))
).then(resp => {
- this.knownPacks[packName].files = resp
- delete this.editedParts[packName][shortcode]
+ this.knownPacks[this.packName].files = resp
+ delete this.editedParts[this.packName][shortcode]
})
+ },
+ refreshPackList () {
+ return this.$store.state.api.backendInteractor.listEmojiPacks()
+ .then(data => data.json())
+ .then(packData => {
+ this.knownPacks = packData.packs
+ })
}
},
mounted () {
- this.$store.state.api.backendInteractor.listEmojiPacks()
- .then(data => data.json())
- .then(packData => {
- this.knownPacks = packData.packs
- console.log(this.knownPacks)
- })
+ this.refreshPackList()
}
}
diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.scss b/src/components/settings_modal/admin_tabs/emoji_tab.scss
@@ -1,3 +1,5 @@
+@import "src/variables";
+
.emoji-tab {
.btn-group .btn {
margin-left: 0.5em;
@@ -21,4 +23,24 @@
width: 32px;
height: 32px;
}
+
+ .emoji-unsaved {
+ box-shadow: 2px 3px 5px var(--cBlue, $fallback--cBlue);
+ }
+
+ .emoji-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1em 1em;
+ }
+}
+
+.emoji-tab-edit-popover {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ padding-bottom: 0.5em;
+}
+
+.emoji-tab-popover-button {
+ margin-left: 0.5em;
}
diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.vue b/src/components/settings_modal/admin_tabs/emoji_tab.vue
@@ -6,84 +6,166 @@
<div class="setting-item">
<h2>{{ $t('admin_dash.tabs.emoji') }}</h2>
- <span class="btn-group">
- <button
- class="button button-default btn"
- type="button"
- @click="reloadEmoji">
- {{ $t('admin_dash.emoji.reload') }}
- </button>
- <button
- class="button button-default btn"
- type="button"
- @click="importFromFS">
- {{ $t('admin_dash.emoji.importFS') }}
- </button>
- </span>
+ <ul class="setting-list">
+ <li class="btn-group setting-item">
+ <button
+ class="button button-default btn"
+ type="button"
+ @click="reloadEmoji">
+ {{ $t('admin_dash.emoji.reload') }}
+ </button>
+ <button
+ class="button button-default btn"
+ type="button"
+ @click="importFromFS">
+ {{ $t('admin_dash.emoji.importFS') }}
+ </button>
+ </li>
- <tab-switcher :scrollable-tabs="true" v-if="Object.keys(knownPacks).length > 0">
- <div v-for="(pack, packName) in knownPacks" :label="packName" :key="packName">
- <div class="pack-info-wrapper">
- <ul class="setting-list">
- <li>
- <div>Description</div>
- <textarea
- v-model="pack.pack.description"
- class="bio resize-height" />
- </li>
- <li>
- <div>Homepage</div>
- <input class="emoji-info-input" v-model="pack.pack.homepage">
- </li>
- <li>
- <div>Fallback source</div>
- <input class="emoji-info-input" v-model="pack.pack['fallback-src']">
- </li>
- <li>
- <Checkbox v-model="pack.pack['can-download']">Downloadable</Checkbox>
- </li>
- </ul>
- </div>
+ <li class="setting-item btn-group">
+ <button
+ class="button button-default btn"
+ type="button"
+ @click="$refs.createPackPopover.showPopover">
+ Create pack
+ </button>
+ <Popover
+ ref="createPackPopover"
+ trigger="click"
+ placement="bottom"
+ bound-to-selector=".emoji-tab"
+ :bound-to="{ x: 'container' }"
+ :offset="{ y: 5 }"
+ >
+ <template #content>
+ <input v-model="newPackName" placeholder="New pack name">
+ <button
+ class="button button-default btn emoji-tab-popover-button"
+ type="button"
+ @click="createEmojiPack">
+ Create
+ </button>
+ </template>
+ </Popover>
- <h2>Files</h2>
+ <button
+ class="button button-default btn"
+ :disabled="packName == ''"
+ type="button"
+ @click="deleteModalVisible = true">
+ Delete pack
+ </button>
+ <ConfirmModal
+ v-if="deleteModalVisible"
+ title="Delete?"
+ :cancel-text="$t('status.delete_confirm_cancel_button')"
+ :confirm-text="$t('status.delete_confirm_accept_button')"
+ @cancelled="deleteModalVisible = false"
+ @accepted="deleteEmojiPack" >
+ Are you sure you want to delete {{ packName }}?
+ </ConfirmModal>
+ </li>
+ <li>
+ <Select class="form-control" v-model="packName">
+ <option value="" disabled hidden>Emoji pack</option>
+ <option v-for="(pack, listPackName) in knownPacks" :label="listPackName" :key="listPackName">
+ {{ listPackName }}
+ </option>
+ </Select>
+ </li>
+ </ul>
+
+ <div v-if="packName !== ''">
+ <div class="pack-info-wrapper">
<ul class="setting-list">
- <li v-for="(file, shortcode) in pack.files" :key="shortcode">
- <StillImage
- class="emoji img"
- :src="emojiAddr(packName, file)"
- :title="`:${shortcode}:`"
- :alt="`:${shortcode}:`"
- />
+ <li>
+ <div>
+ Description
+ <ModifiedIndicator :changed="metaEdited('description')" />
+ </div>
+ <textarea
+ v-model="packMeta.description"
+ class="bio resize-height" />
+ </li>
+ <li>
+ <div>
+ Homepage
+ <ModifiedIndicator :changed="metaEdited('homepage')" />
+ </div>
+ <input class="emoji-info-input" v-model="packMeta.homepage">
+ </li>
+ <li>
+ <div>
+ Fallback source
+ <ModifiedIndicator :changed="metaEdited('fallback-src')" />
+ </div>
+ <input class="emoji-info-input" v-model="packMeta['fallback-src']">
+ </li>
+ <li>
+ <div>Fallback SHA256</div>
+ <input :disabled="true" class="emoji-info-input" v-model="packMeta['fallback-src-sha256']">
+ </li>
+ <li>
+ <Checkbox v-model="packMeta['share-files']">Share</Checkbox>
+
+ <ModifiedIndicator :changed="metaEdited('share-files')" />
+ </li>
+ <li>
+ <button
+ class="button button-default btn"
+ type="button"
+ @click="savePackMetadata">
+ Save
+ </button>
+ </li>
+ </ul>
+ </div>
+
+ <h2>Files</h2>
- <template v-if="editedParts[packName] !== undefined && editedParts[packName][shortcode] !== undefined">
+ <div class="emoji-list" v-if="pack">
+ <Popover
+ v-for="(file, shortcode) in pack.files" :key="shortcode"
+ trigger="click"
+ placement="top"
+ :class="{'emoji-unsaved': editedParts[packName] !== undefined && editedParts[packName][shortcode] !== undefined}"
+ popover-class="emoji-tab-edit-popover popover-default"
+ bound-to-selector=".emoji-list"
+ :bound-to="{ x: 'container' }"
+ :offset="{ y: 5 }"
+ @show="editEmoji(shortcode)"
+ >
+ <template #content>
+ <h3>
+ Editing <i>{{ shortcode }}</i>
+ </h3>
+ <div v-if="editedParts[packName] !== undefined && editedParts[packName][shortcode] !== undefined">
<input class="emoji-data-input"
v-model="editedParts[packName][shortcode].shortcode">
<input class="emoji-data-input"
v-model="editedParts[packName][shortcode].file">
<button
- class="button button-default btn"
+ class="button button-default btn emoji-tab-popover-button"
type="button"
- @click="saveEditedEmoji(packName, shortcode)">
+ @click="saveEditedEmoji(shortcode)">
Save
</button>
- </template>
- <template v-else>
- <input disabled class="emoji-data-input" :value="shortcode">
- <input disabled class="emoji-data-input" :value="file">
- <button
- class="button button-default btn"
- type="button"
- @click="editEmoji(packName, shortcode)">
- Edit
- </button>
- </template>
- </li>
- </ul>
+ </div>
+ </template>
+ <template #trigger>
+ <StillImage
+ class="emoji"
+ :src="emojiAddr(file)"
+ :title="`:${shortcode}:`"
+ :alt="`:${shortcode}:`"
+ />
+ </template>
+ </Popover>
</div>
- </tab-switcher>
+ </div>
</div>
</div>
</template>
diff --git a/src/components/settings_modal/settings_modal_admin_content.vue b/src/components/settings_modal/settings_modal_admin_content.vue
@@ -63,7 +63,7 @@
<div
:label="$t('admin_dash.tabs.emoji')"
- icon="laptop-code"
+ icon="face-smile-beam"
data-tab-name="emoji"
>
<EmojiTab />
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
@@ -116,12 +116,12 @@ const PLEROMA_ADMIN_FRONTENDS_INSTALL_URL = '/api/pleroma/admin/frontends/instal
const PLEROMA_EMOJI_RELOAD_URL = '/api/pleroma/admin/reload_emoji'
const PLEROMA_EMOJI_IMPORT_FS_URL = '/api/pleroma/emoji/packs/import'
-const PLEROMA_EMOJI_PACKS_URL = (page, pageSize) => `/api/pleroma/emoji/packs?page=${page}&page_size=${pageSize}`
-const PLEROMA_EMOJI_PACK_URL = (name) => `/api/pleroma/emoji/pack?name=${name}`
-const PLEROMA_EMOJI_PACKS_DL_REMOTE_URL = '/api/pleroma/emoji/packs/download'
+const PLEROMA_EMOJI_PACKS_URL = (page, pageSize) => `/api/v1/pleroma/emoji/packs?page=${page}&page_size=${pageSize}`
+const PLEROMA_EMOJI_PACK_URL = (name) => `/api/v1/pleroma/emoji/pack?name=${name}`
+const PLEROMA_EMOJI_PACKS_DL_REMOTE_URL = '/api/v1/pleroma/emoji/packs/download'
const PLEROMA_EMOJI_PACKS_LS_REMOTE_URL =
- (url, page, pageSize) => `/api/pleroma/emoji/packs/remote?url=${url}&page=${page}&page_size=${pageSize}`
-const PLEROMA_EMOJI_UPDATE_FILE_URL = (name) => `/api/pleroma/emoji/packs/files?name=${name}`
+ (url, page, pageSize) => `/api/v1/pleroma/emoji/packs/remote?url=${url}&page=${page}&page_size=${pageSize}`
+const PLEROMA_EMOJI_UPDATE_FILE_URL = (name) => `/api/v1/pleroma/emoji/packs/files?name=${name}`
const oldfetch = window.fetch
@@ -1809,7 +1809,7 @@ const importEmojiFromFS = () => {
}
const createEmojiPack = ({ name }) => {
- return fetch(PLEROMA_EMOJI_PACK_URL(name), { method: 'PUT' })
+ return fetch(PLEROMA_EMOJI_PACK_URL(name), { method: 'POST' })
}
const listEmojiPacks = () => {
@@ -1850,7 +1850,7 @@ const saveEmojiPackMetadata = ({ name, newData }) => {
{
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ name, new_data: newData })
+ body: JSON.stringify({ metadata: newData })
}
)
}