Add minimal draft management tool

This commit is contained in:
tusooa 2023-03-10 12:10:39 -05:00
parent d4444cd0b1
commit dcd4587525
No known key found for this signature in database
GPG Key ID: 42AEC43D48433C51
10 changed files with 186 additions and 45 deletions

View File

@ -25,6 +25,7 @@ import ListsTimeline from 'components/lists_timeline/lists_timeline.vue'
import ListsEdit from 'components/lists_edit/lists_edit.vue' import ListsEdit from 'components/lists_edit/lists_edit.vue'
import NavPanel from 'src/components/nav_panel/nav_panel.vue' import NavPanel from 'src/components/nav_panel/nav_panel.vue'
import AnnouncementsPage from 'components/announcements_page/announcements_page.vue' import AnnouncementsPage from 'components/announcements_page/announcements_page.vue'
import Drafts from 'components/drafts/drafts.vue'
export default (store) => { export default (store) => {
const validateAuthenticatedRoute = (to, from, next) => { const validateAuthenticatedRoute = (to, from, next) => {
@ -78,6 +79,7 @@ export default (store) => {
{ name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute }, { name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute },
{ name: 'about', path: '/about', component: About }, { name: 'about', path: '/about', component: About },
{ name: 'announcements', path: '/announcements', component: AnnouncementsPage }, { name: 'announcements', path: '/announcements', component: AnnouncementsPage },
{ name: 'drafts', path: '/drafts', component: Drafts },
{ name: 'user-profile', path: '/users/:name', component: UserProfile }, { name: 'user-profile', path: '/users/:name', component: UserProfile },
{ name: 'legacy-user-profile', path: '/:name', component: UserProfile }, { name: 'legacy-user-profile', path: '/:name', component: UserProfile },
{ name: 'lists', path: '/lists', component: Lists }, { name: 'lists', path: '/lists', component: Lists },

View File

@ -0,0 +1,42 @@
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
const Draft = {
components: {
PostStatusForm
},
props: {
draft: {
type: Object,
required: true
}
},
data () {
return {
editing: false
}
},
computed: {
relAttrs () {
if (this.draft.type === 'edit') {
return { statusId: this.draft.refId }
} else if (this.draft.type === 'reply') {
return { replyTo: this.draft.refId }
} else {
return {}
}
},
postStatusFormProps () {
return {
draftId: this.draft.id,
...this.relAttrs
}
}
},
methods: {
toggleEditing () {
this.editing = !this.editing
}
}
}
export default Draft

View File

@ -0,0 +1,35 @@
<template>
<article class="Draft">
<div>
{{ draft.id }}
</div>
<div v-if="draft.inReplyToStatusId">
{{ draft.inReplyToStatusId }}
</div>
<div
class="draft-content"
>
{{ draft.status }}
</div>
<div>
<button
class="btn button-default"
:aria-expanded="editing"
@click.prevent.stop="toggleEditing"
>
{{ $t('drafts.continue') }}
</button>
</div>
<div v-if="editing">
<PostStatusForm v-bind="postStatusFormProps" />
</div>
</article>
</template>
<script src="./draft.js"></script>
<style lang="scss">
.Draft {
margin: 1em;
}
</style>

View File

@ -0,0 +1,17 @@
import Draft from 'src/components/draft/draft.vue'
import List from 'src/components/list/list.vue'
const Drafts = {
components: {
Draft,
List
},
computed: {
drafts () {
console.debug('available drafts:', this.$store.getters.draftsArray)
return this.$store.getters.draftsArray
}
}
}
export default Drafts

View File

@ -0,0 +1,24 @@
<template>
<div class="Drafts">
<div class="panel panel-default">
<div class="panel-heading">
<div class="title">
{{ $t('drafts.drafts') }}
</div>
</div>
<div class="panel-body">
<List
:items="drafts"
>
<template #item="{ item: draft }">
<Draft
:draft="draft"
/>
</template>
</List>
</div>
</div>
</div>
</template>
<script src="./drafts.js"></script>

View File

@ -19,7 +19,8 @@ import {
faInfoCircle, faInfoCircle,
faStream, faStream,
faList, faList,
faBullhorn faBullhorn,
faFilePen
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
library.add( library.add(
@ -34,7 +35,8 @@ library.add(
faInfoCircle, faInfoCircle,
faStream, faStream,
faList, faList,
faBullhorn faBullhorn,
faFilePen
) )
const NavPanel = { const NavPanel = {
props: ['forceExpand', 'forceEditMode'], props: ['forceExpand', 'forceEditMode'],

View File

@ -78,6 +78,11 @@ export const ROOT_ITEMS = {
label: 'nav.announcements', label: 'nav.announcements',
badgeGetter: 'unreadAnnouncementCount', badgeGetter: 'unreadAnnouncementCount',
criteria: ['announcements'] criteria: ['announcements']
},
drafts: {
route: 'drafts',
icon: 'file-pen',
label: 'nav.drafts'
} }
} }

View File

@ -137,58 +137,47 @@ const PostStatusForm = {
const [statusType, refId] = typeAndRefId({ replyTo: this.replyTo, statusId: this.statusId }) const [statusType, refId] = typeAndRefId({ replyTo: this.replyTo, statusId: this.statusId })
if (statusType === 'reply') { let statusParams = this.getDraft(statusType, refId)
const currentUser = this.$store.state.users.currentUser
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
const scope = ((this.copyMessageScope && scopeCopy) || this.copyMessageScope === 'direct') if (!statusParams) {
? this.copyMessageScope if (statusType === 'reply') {
: this.$store.state.users.currentUser.default_scope const currentUser = this.$store.state.users.currentUser
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig const scope = ((this.copyMessageScope && scopeCopy) || this.copyMessageScope === 'direct')
? this.copyMessageScope
: this.$store.state.users.currentUser.default_scope
let statusParams = { const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig
type: statusType,
refId,
spoilerText: this.subject || '',
status: statusText,
nsfw: !!sensitiveByDefault,
files: [],
poll: {},
mediaDescriptions: {},
visibility: scope,
contentType
}
if (statusType === 'edit') {
const statusContentType = this.statusContentType || contentType
statusParams = { statusParams = {
type: statusType, type: statusType,
refId, refId,
spoilerText: this.subject || '', spoilerText: this.subject || '',
status: this.statusText || '', status: statusText,
nsfw: this.statusIsSensitive || !!sensitiveByDefault, nsfw: !!sensitiveByDefault,
files: this.statusFiles || [], files: [],
poll: this.statusPoll || {}, poll: {},
mediaDescriptions: this.statusMediaDescriptions || {}, mediaDescriptions: {},
visibility: this.statusScope || scope, visibility: scope,
contentType: statusContentType contentType
} }
}
console.debug('type and ref:', [statusType, refId]) if (statusType === 'edit') {
const statusContentType = this.statusContentType || contentType
const maybeDraft = this.$store.state.drafts.drafts[this.draftId] statusParams = {
if (this.draftId && maybeDraft) { type: statusType,
console.debug('current draft:', maybeDraft) refId,
statusParams = maybeDraft spoilerText: this.subject || '',
} else { status: this.statusText || '',
const existingDrafts = this.$store.getters.draftsByTypeAndRefId(statusType, refId) nsfw: this.statusIsSensitive || !!sensitiveByDefault,
files: this.statusFiles || [],
console.debug('existing drafts:', existingDrafts) poll: this.statusPoll || {},
if (existingDrafts.length) { mediaDescriptions: this.statusMediaDescriptions || {},
statusParams = existingDrafts[0] visibility: this.statusScope || scope,
contentType: statusContentType
}
} }
} }
@ -683,6 +672,23 @@ const PostStatusForm = {
} }
}) })
} }
},
getDraft (statusType, refId) {
console.debug('type and ref:', [statusType, refId])
const maybeDraft = this.$store.state.drafts.drafts[this.draftId]
if (this.draftId && maybeDraft) {
console.debug('current draft:', maybeDraft)
return maybeDraft
} else {
const existingDrafts = this.$store.getters.draftsByTypeAndRefId(statusType, refId)
console.debug('existing drafts:', existingDrafts)
if (existingDrafts.length) {
return existingDrafts[0]
}
}
// No draft available, fall back
} }
} }
} }

View File

@ -189,7 +189,8 @@
"mobile_notifications": "Open notifications", "mobile_notifications": "Open notifications",
"mobile_notifications": "Open notifications (there are unread ones)", "mobile_notifications": "Open notifications (there are unread ones)",
"mobile_notifications_close": "Close notifications", "mobile_notifications_close": "Close notifications",
"announcements": "Announcements" "announcements": "Announcements",
"drafts": "Drafts"
}, },
"notifications": { "notifications": {
"broken_favorite": "Unknown status, searching for it…", "broken_favorite": "Unknown status, searching for it…",
@ -1154,5 +1155,9 @@
}, },
"unicode_domain_indicator": { "unicode_domain_indicator": {
"tooltip": "This domain contains non-ascii characters." "tooltip": "This domain contains non-ascii characters."
},
"drafts": {
"drafts": "Drafts",
"continue": "Continue editing"
} }
} }

View File

@ -22,6 +22,9 @@ export const getters = {
return (type, refId) => { return (type, refId) => {
return Object.values(state.drafts).filter(draft => draft.type === type && draft.refId === refId) return Object.values(state.drafts).filter(draft => draft.type === type && draft.refId === refId)
} }
},
draftsArray (state) {
return Object.values(state.drafts)
} }
} }