123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- <template>
- <div
- class='post'
- :class='{
- "post--highlighted": highlight,
- "post--selected": selected
- }'
- @mouseenter='hover = true'
- @mouseleave='hover = false'
- @click='goToPost'
- >
- <span
- class='post__remove_icon fa fa-check'
- :class='{"post__remove_icon--show": showSelect && !post.removed}'
- @click.stop='toggleSelected'
- ></span>
- <modal-window v-model='showShareModal' @click.stop='() => {}'>
- <div slot='main'>
- <p>Copy this URL to share the post</p>
- <fancy-input placeholder='Post URL' :value='postURL' width='100%'></fancy-input>
- </div>
- <button slot='footer' class='button button--modal' @click.stop='setShareModalState(false)'>OK</button>
- </modal-window>
- <report-post-modal v-model='showReportPostModal' :post-id='post.id'></report-post-modal>
- <div class='post__meta_data'>
- <div style='display: inline-flex;'>
- <avatar-icon :user='post.User' class='post__avatar'></avatar-icon>
- <div class='post__thread' v-if='showThread' @click.stop='goToThread'>
- In thread <span class='post__thread__name'>{{post.Thread.name}}</span>
- ·
- </div>
- <div class='post__user' v-else>{{username}}</div>
- <replying-to
- style='margin-right: 0.5rem;'
- v-if='post.replyingToUsername'
- :replyId='post.replyId'
- :username='post.replyingToUsername'
- @click='$emit("goToPost", post.replyId, true)'
- ></replying-to>
- </div>
- <div class='post__date'>{{post.createdAt | formatDate('time|date', ', ')}}</div>
- </div>
- <div class='post__date post__date--mobile'>{{post.createdAt | formatDate('time|date', ', ')}}</div>
- <div class='post__content' v-html='postContentHTML'></div>
- <div class='post__footer'>
- <div
- class='post__footer_group'
- >
- <div class='post__footer_sub_group'>
- <heart-button :post='post' v-if='showReply'></heart-button>
- </div>
- <div class='post__footer_sub_group' v-if='post.Replies.length'>
- <span class='post__footer_sub_group__text post__footer_sub_group__text--replies'>replies</span>
- <post-reply
- v-for='(reply, index) in post.Replies'
- :key='reply.postNumber'
- :post='reply'
- :hover='hover'
- :first='index === 0'
- @click='$emit("goToPost", reply.postNumber)'
- ></post-reply>
- </div>
-
- </div>
- <div
- class='post__footer_group post__actions'
- :class='{ "post__actions--show": showActions }'
- >
- <div class='post__action post__share' @click.stop='setShareModalState(true)'>share</div>
- <div
- class='post__action'
- @click.stop='setShowReportPostModal(true)'
- v-if='$store.state.username && !post.removed'
- >
- report
- </div>
- <div
- class='post__action post__reply'
- v-if='$store.state.username && showReply'
- @click.stop='$emit("reply", post.id, username)'
- >
- reply
- </div>
- </div>
- </div>
- <div class='post__replies'>
- </div>
- </div>
- </template>
- <script>
- import PostReply from './PostReply'
- import HeartButton from './HeartButton'
- import ModalWindow from './ModalWindow'
- import FancyInput from './FancyInput'
- import ReplyingTo from './ReplyingTo'
- import AvatarIcon from './AvatarIcon'
- import ReportPostModal from './ReportPostModal'
- import AjaxErrorHandler from '../assets/js/errorHandler'
- export default {
- name: 'ThreadPost',
- props: [
- 'post',
- 'highlight',
- 'showReply',
- 'showThread',
- 'showSelect',
- 'clickForPost'
- ],
- components: {
- PostReply,
- ModalWindow,
- FancyInput,
- ReplyingTo,
- AvatarIcon,
- HeartButton,
- ReportPostModal
- },
- data () {
- let post = this.post
- return {
- hover: false,
- showShareModal: false,
- showReportPostModal: false,
- postURL: `${location.origin}/p/${post.id}`,
- selected: false,
- postContentHTML: post.content
- }
- },
- computed: {
- username () {
- if(this.post.User) {
- return this.post.User.username
- } else {
- return '[deleted]'
- }
- },
- showActions () {
- return this.hover || this.showShareModal || this.showReportPostModal
- }
- },
- methods: {
- setShareModalState (val) {
- this.showShareModal = val
- },
- setShowReportPostModal (val) {
- this.showReportPostModal = val
- },
- goToThread () {
- this.$router.push(`/thread/${this.post.Thread.slug}/${this.post.Thread.id}`)
- },
- goToPost () {
- if(this.clickForPost) {
- this.$router.push(
- '/thread/' +
- this.post.Thread.slug + '/' +
- this.post.Thread.id + '/' +
- this.post.postNumber
- )
- }
- },
- toggleSelected () {
- this.selected = !this.selected
- this.$emit('selected', this.post.id)
- }
- },
- watch: {
- showSelect () {
- if(this.selected) {
- this.$emit('selected', this.post.id)
- }
- this.selected = false
- }
- },
- mounted () {
- this.$linkExpander(this.post.content, v => this.postContentHTML = v);
- }
- }
- </script>
- <style lang='scss' scoped>
- @import '../assets/scss/variables.scss';
- @keyframes shake {
- 0% {
- left: 0rem;
- }
- 25% {
- left: -0.5rem;
- }
- 75% {
- left: 0.5rem;
- }
- 100% {
- left: 0rem;
- }
- }
- .post {
- position: relative;
- border-bottom: thin solid $color__gray--darker;
- transition: background-color 0.5s;
- margin: 0.5rem -0.5rem;
- padding: 0 0.5rem;
- border-radius: 0.25rem;
- @at-root #{&}--highlighted {
- background-color: $color__lightgray--darkest;
- animation-name: shake;
- animation-iteration-count: 5;
- animation-timing-function: linear;
- animation-duration: 0.25s;
- }
- @at-root #{&}--last {
- border-bottom: none;
- margin-bottom: 0;
- }
- @at-root #{&}__remove_icon {
- position: absolute;
- right: 1rem;
- display: inline-block;
- top: 1rem;
- color: #fff;
- cursor: pointer;
- background-color: gray;
- z-index: 1;
- border-radius: 100%;
- opacity: 0;
- pointer-events: none;
- padding: 0.25rem;
- transition: all 0.2s;
- @at-root #{&}--show {
- opacity: 1;
- pointer-events: all;
- }
- }
- @at-root #{&}--selected {
- transform: scale(0.95);
- padding: 1rem;
- background-color: $color__lightgray--primary;
- }
- @at-root #{&}__meta_data {
- display: flex;
- justify-content: space-between;
- padding-top: 0.75rem;
- position: relative;
- margin-left: 4rem;
- }
- @at-root #{&}__avatar {
- position: absolute;
- left: -4rem;
- }
- @at-root #{&}__user {
- @include text($font--role-default, 1rem, 600);
- margin-right: 0.5rem;
- }
- @at-root #{&}__thread {
- color: $color__text--secondary;
-
- @at-root #{&}__name {
- cursor: pointer;
- @include text($font--role-default, 1rem, 600);
- &:hover {
- color: $color__darkgray--primary;
- }
- }
- }
- @at-root #{&}__date {
- @at-root #{&}--mobile {
- display: none;
- }
- }
- @at-root #{&}__content {
- padding: 0 0.5rem 0 4rem;
- }
- @at-root #{&}__footer {
- padding: 0.5rem 0 0.75rem 0.5rem;
- display: flex;
- align-items: center;
- justify-content: space-between;
- transition: opacity 0.2s;
- @at-root #{&}_sub_group {
- display: flex;
- align-items: baseline;
- margin-right: 1rem;
- @at-root #{&}__text {
- font-variant: small-caps;
- margin: 0 0.25rem;
- margin-left: 0;
- font-size: 0.9rem;
- position: relative;
- bottom: 0.1rem;
- }
- }
- @at-root #{&}_group {
- align-items: center;
- display: inline-flex;
- position: relative;
- }
- }
- @at-root #{&}__action {
- color: $color__darkgray--primary;
- cursor: pointer;
- margin-right: 0.75rem;
- font-size: 0.9rem;
- font-variant: small-caps;
- position: relative;
- bottom: 0.1rem;
- transition: all 0.2s;
- &:hover {
- color: $color__darkgray--darkest;
- }
- }
- @at-root #{&}__actions {
- opacity: 0;
- @at-root #{&}--show {
- opacity: 1;
- transition: opacity 0.2s;
- }
- }
- }
- @media (max-width: 420px) {
- .post {
- @at-root #{&}__actions {
- opacity: 1;
- }
- @at-root #{&}__content {
- padding: 0 0.5rem;
- }
- @at-root #{&}__date {
- display: none;
- @at-root #{&}--mobile {
- display: block;
- padding-left: 4rem;
- font-size: 0.9rem;
- }
- }
- }
- }
- </style>
|