Merge branch 'drafts-improvements' into shigusegubu-themes3
This commit is contained in:
commit
d1db92c896
6 changed files with 334 additions and 303 deletions
|
@ -1,21 +1,5 @@
|
|||
<template>
|
||||
<article class="Draft">
|
||||
<div class="actions">
|
||||
<button
|
||||
class="btn button-default"
|
||||
:class="{ toggled: editing }"
|
||||
:aria-expanded="editing"
|
||||
@click.prevent.stop="toggleEditing"
|
||||
>
|
||||
{{ $t('drafts.continue') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn button-default"
|
||||
@click.prevent.stop="abandon"
|
||||
>
|
||||
{{ $t('drafts.abandon') }}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-if="!editing"
|
||||
class="status-content"
|
||||
|
@ -66,6 +50,22 @@
|
|||
{{ $t('drafts.abandon_confirm') }}
|
||||
</confirm-modal>
|
||||
</teleport>
|
||||
<div class="actions">
|
||||
<button
|
||||
class="btn button-default"
|
||||
:class="{ toggled: editing }"
|
||||
:aria-expanded="editing"
|
||||
@click.prevent.stop="toggleEditing"
|
||||
>
|
||||
{{ $t('drafts.continue') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn button-default"
|
||||
@click.prevent.stop="abandon"
|
||||
>
|
||||
{{ $t('drafts.abandon') }}
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
|
@ -73,13 +73,7 @@
|
|||
|
||||
<style lang="scss">
|
||||
.Draft {
|
||||
margin: 1em;
|
||||
|
||||
.status-content {
|
||||
border: 1px solid;
|
||||
border-color: var(--faint);
|
||||
border-radius: var(--inputRadius);
|
||||
color: var(--text);
|
||||
padding: 0.5em;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p v-if="drafts.length === 0">
|
||||
{{ $t('drafts.no_drafts') }}
|
||||
</p>
|
||||
<List
|
||||
v-else
|
||||
:items="drafts"
|
||||
>
|
||||
<template #item="{ item: draft }">
|
||||
|
|
|
@ -7,6 +7,7 @@ import PollForm from '../poll/poll_form.vue'
|
|||
import Attachment from '../attachment/attachment.vue'
|
||||
import Gallery from 'src/components/gallery/gallery.vue'
|
||||
import StatusContent from '../status_content/status_content.vue'
|
||||
import Popover from 'src/components/popover/popover.vue'
|
||||
import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
||||
import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js'
|
||||
|
@ -25,7 +26,10 @@ import {
|
|||
faUpload,
|
||||
faBan,
|
||||
faTimes,
|
||||
faCircleNotch
|
||||
faCircleNotch,
|
||||
faChevronDown,
|
||||
faChevronLeft,
|
||||
faChevronRight
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
|
@ -34,7 +38,10 @@ library.add(
|
|||
faUpload,
|
||||
faBan,
|
||||
faTimes,
|
||||
faCircleNotch
|
||||
faCircleNotch,
|
||||
faChevronDown,
|
||||
faChevronLeft,
|
||||
faChevronRight
|
||||
)
|
||||
|
||||
const buildMentionsString = ({ user, attentions = [] }, currentUser) => {
|
||||
|
@ -123,7 +130,8 @@ const PostStatusForm = {
|
|||
Attachment,
|
||||
StatusContent,
|
||||
Gallery,
|
||||
DraftCloser
|
||||
DraftCloser,
|
||||
Popover
|
||||
},
|
||||
mounted () {
|
||||
this.updateIdempotencyKey()
|
||||
|
|
249
src/components/post_status_form/post_status_form.scss
Normal file
249
src/components/post_status_form/post_status_form.scss
Normal file
|
@ -0,0 +1,249 @@
|
|||
.post-status-form {
|
||||
position: relative;
|
||||
|
||||
.attachments {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.form-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.5em;
|
||||
height: 2.5em;
|
||||
|
||||
.post-button {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.35em;
|
||||
padding: 0.35em;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.more-post-actions {
|
||||
height: 100%;
|
||||
|
||||
.btn {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-bottom-left {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding-right: 7px;
|
||||
margin-right: 7px;
|
||||
max-width: 10em;
|
||||
}
|
||||
|
||||
.preview-heading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.preview-toggle {
|
||||
flex: 10 0 auto;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding-left: 0.5em;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
svg,
|
||||
i {
|
||||
margin-left: 0.2em;
|
||||
font-size: 0.8em;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.preview-error {
|
||||
font-style: italic;
|
||||
color: var(--textFaint);
|
||||
}
|
||||
|
||||
.preview-status {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--roundness);
|
||||
padding: 0.5em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.reply-or-quote-selector {
|
||||
flex: 1 0 auto;
|
||||
margin-bottom: 0.5em;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.text-format {
|
||||
.only-format {
|
||||
color: var(--textFaint);
|
||||
}
|
||||
}
|
||||
|
||||
.visibility-tray {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 5px;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.visibility-notice.edit-warning {
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
> :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Order is not necessary but a good indicator
|
||||
.media-upload-icon {
|
||||
order: 1;
|
||||
justify-content: left;
|
||||
}
|
||||
|
||||
.emoji-icon {
|
||||
order: 2;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.poll-icon {
|
||||
order: 3;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.media-upload-icon,
|
||||
.poll-icon,
|
||||
.emoji-icon {
|
||||
font-size: 1.85em;
|
||||
line-height: 1.1;
|
||||
flex: 1;
|
||||
padding: 0 0.1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.error {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.media-upload-wrapper {
|
||||
margin-right: 0.2em;
|
||||
margin-bottom: 0.5em;
|
||||
width: 18em;
|
||||
|
||||
img,
|
||||
video {
|
||||
object-fit: contain;
|
||||
max-height: 10em;
|
||||
}
|
||||
|
||||
.video {
|
||||
max-height: 10em;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.status-input-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0.6em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.25em 0.5em 0.5em;
|
||||
line-height: 1.85;
|
||||
}
|
||||
|
||||
.input.form-post-body {
|
||||
// TODO: make a resizable textarea component?
|
||||
box-sizing: content-box; // needed for easier computation of dynamic size
|
||||
overflow: hidden;
|
||||
transition: min-height 200ms 100ms;
|
||||
// stock padding + 1 line of text (for counter)
|
||||
padding-bottom: calc(var(--_padding) + var(--post-line-height) * 1em);
|
||||
// two lines of text
|
||||
height: calc(var(--post-line-height) * 1em);
|
||||
min-height: calc(var(--post-line-height) * 1em);
|
||||
resize: none;
|
||||
background: transparent;
|
||||
|
||||
&.scrollable-form {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.main-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.character-counter {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
margin: 0 0.5em;
|
||||
|
||||
&.error {
|
||||
color: var(--cRed);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 0.6; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 0.6; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
.drop-indicator {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0.6;
|
||||
color: var(--text);
|
||||
background-color: var(--bg);
|
||||
border-radius: var(--roundness);
|
||||
border: 2px dashed var(--text);
|
||||
}
|
||||
|
||||
.auto-save-status {
|
||||
align-self: center;
|
||||
}
|
||||
}
|
|
@ -264,6 +264,12 @@
|
|||
:visible="pollFormVisible"
|
||||
:params="newStatus.poll"
|
||||
/>
|
||||
<span
|
||||
v-if="!disableDraft && shouldAutoSaveDraft"
|
||||
class="auto-save-status"
|
||||
>
|
||||
{{ autoSaveState }}
|
||||
</span>
|
||||
<div
|
||||
ref="bottom"
|
||||
class="form-bottom"
|
||||
|
@ -296,41 +302,52 @@
|
|||
<FAIcon icon="poll-h" />
|
||||
</button>
|
||||
</div>
|
||||
<span
|
||||
v-if="!disableDraft && shouldAutoSaveDraft"
|
||||
class="auto-save-status"
|
||||
>
|
||||
{{ autoSaveState }}
|
||||
</span>
|
||||
<div class="btn-group">
|
||||
<button
|
||||
v-else-if="!disableDraft"
|
||||
class="btn button-default"
|
||||
@click="saveDraft"
|
||||
class="btn button-default post-button"
|
||||
:disabled="isOverLengthLimit || posting || uploadingFiles || disableSubmit"
|
||||
@click.stop.prevent="postStatus($event, newStatus)"
|
||||
>
|
||||
<template v-if="posting">
|
||||
{{ $t('post_status.posting') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $t('post_status.post') }}
|
||||
</template>
|
||||
</button>
|
||||
<Popover
|
||||
v-if="!disableDraft"
|
||||
class="more-post-actions"
|
||||
:normal-button="true"
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
:offset="{ y: 5 }"
|
||||
:bound-to="{ x: 'container' }"
|
||||
>
|
||||
<template #trigger>
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
icon="chevron-down"
|
||||
/>
|
||||
</template>
|
||||
<template #content="{close}">
|
||||
<div
|
||||
class="dropdown-menu"
|
||||
role="menu"
|
||||
>
|
||||
<button
|
||||
class="menu-item dropdown-item dropdown-item-icon"
|
||||
role="menu"
|
||||
@click.prevent="saveDraft"
|
||||
@click="close"
|
||||
v-if="!disableDraft"
|
||||
>
|
||||
{{ $t('post_status.save_to_drafts_button') }}
|
||||
</button>
|
||||
<button
|
||||
v-if="posting"
|
||||
disabled
|
||||
class="btn button-default"
|
||||
>
|
||||
{{ $t('post_status.posting') }}
|
||||
</button>
|
||||
<button
|
||||
v-else-if="isOverLengthLimit"
|
||||
disabled
|
||||
class="btn button-default"
|
||||
>
|
||||
{{ $t('post_status.post') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
:disabled="uploadingFiles || disableSubmit"
|
||||
class="btn button-default"
|
||||
@click.stop.prevent="postStatus($event, newStatus)"
|
||||
>
|
||||
{{ $t('post_status.post') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-show="showDropIcon !== 'hide'"
|
||||
|
@ -391,246 +408,4 @@
|
|||
|
||||
<script src="./post_status_form.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
.post-status-form {
|
||||
position: relative;
|
||||
|
||||
.attachments {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.form-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.5em;
|
||||
height: 2.5em;
|
||||
|
||||
button {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.35em;
|
||||
padding: 0.35em;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.form-bottom-left {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding-right: 7px;
|
||||
margin-right: 7px;
|
||||
max-width: 10em;
|
||||
}
|
||||
|
||||
.preview-heading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.preview-toggle {
|
||||
flex: 10 0 auto;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding-left: 0.5em;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
svg,
|
||||
i {
|
||||
margin-left: 0.2em;
|
||||
font-size: 0.8em;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.preview-error {
|
||||
font-style: italic;
|
||||
color: var(--textFaint);
|
||||
}
|
||||
|
||||
.preview-status {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--roundness);
|
||||
padding: 0.5em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.reply-or-quote-selector {
|
||||
flex: 1 0 auto;
|
||||
margin-bottom: 0.5em;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.text-format {
|
||||
.only-format {
|
||||
color: var(--textFaint);
|
||||
}
|
||||
}
|
||||
|
||||
.visibility-tray {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 5px;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.visibility-notice.edit-warning {
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
> :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Order is not necessary but a good indicator
|
||||
.media-upload-icon {
|
||||
order: 1;
|
||||
justify-content: left;
|
||||
}
|
||||
|
||||
.emoji-icon {
|
||||
order: 2;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.poll-icon {
|
||||
order: 3;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.media-upload-icon,
|
||||
.poll-icon,
|
||||
.emoji-icon {
|
||||
font-size: 1.85em;
|
||||
line-height: 1.1;
|
||||
flex: 1;
|
||||
padding: 0 0.1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.error {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.media-upload-wrapper {
|
||||
margin-right: 0.2em;
|
||||
margin-bottom: 0.5em;
|
||||
width: 18em;
|
||||
|
||||
img,
|
||||
video {
|
||||
object-fit: contain;
|
||||
max-height: 10em;
|
||||
}
|
||||
|
||||
.video {
|
||||
max-height: 10em;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.status-input-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0.6em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.25em 0.5em 0.5em;
|
||||
line-height: 1.85;
|
||||
}
|
||||
|
||||
.input.form-post-body {
|
||||
// TODO: make a resizable textarea component?
|
||||
box-sizing: content-box; // needed for easier computation of dynamic size
|
||||
overflow: hidden;
|
||||
transition: min-height 200ms 100ms;
|
||||
// stock padding + 1 line of text (for counter)
|
||||
padding-bottom: calc(var(--_padding) + var(--post-line-height) * 1em);
|
||||
// two lines of text
|
||||
height: calc(var(--post-line-height) * 1em);
|
||||
min-height: calc(var(--post-line-height) * 1em);
|
||||
resize: none;
|
||||
background: transparent;
|
||||
|
||||
&.scrollable-form {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.main-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.character-counter {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
margin: 0 0.5em;
|
||||
|
||||
&.error {
|
||||
color: var(--cRed);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 0.6; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 0.6; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
.drop-indicator {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0.6;
|
||||
color: var(--text);
|
||||
background-color: var(--bg);
|
||||
border-radius: var(--roundness);
|
||||
border: 2px dashed var(--text);
|
||||
}
|
||||
|
||||
.auto-save-status {
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style src="./post_status_form.scss" lang="scss"></style>
|
||||
|
|
|
@ -1513,6 +1513,7 @@
|
|||
},
|
||||
"drafts": {
|
||||
"drafts": "Drafts",
|
||||
"no_drafts": "You have no drafts",
|
||||
"continue": "Continue composing",
|
||||
"abandon": "Abandon draft",
|
||||
"abandon_confirm_title": "Abandon confirmation",
|
||||
|
|
Loading…
Add table
Reference in a new issue