Последняя версия с сервера прошлого разработчика

This commit is contained in:
2025-07-10 04:35:51 +00:00
commit c731570032
1174 changed files with 134314 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" static
class="fixed z-[1000] inset-0 overflow-y-auto" :open="open"
@close="staticCloseModal"
>
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0" enter-to="opacity-100"
leave="ease-in duration-200" leave-from="opacity-100"
leave-to="opacity-0"
>
<DialogOverlay class="fixed inset-0 bg-indigo-200 bg-opacity-75 transition-opacity" />
</TransitionChild>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100"
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div class="inline-block align-bottom bg-indigo-300 md:rounded-md text-left overflow-hidden shadow-xl transform transition-all md:align-middle md:max-w-6xl w-full">
<div class="md:grid grid-cols-12">
<button class="flex md:hidden w-full items-center justify-center p-3 bg-indigo-300 text-gray-light text-sm border-b border-indigo-100" @click="staticCloseModal">
Закрыть
</button>
<modal-feed-media
:type="feed.type"
:feed_id="feed.id"
:title="feed.entity.title"
:preview="feed.entity.preview"
:medias="feed.entity.collection_medias"
/>
<modal-feed-body
:user="feed.user"
:feed_id="feed.id"
:entity="feed.entity"
@openShare="showShareModal"
@onRemoveFeed="onRemoveFeed"
@disableModal="checkCloseModal"
/>
</div>
</div>
</TransitionChild>
</div>
<modal-warning
:feed_id="modalFeedId"
:open="warningShow"
@action="deleteActionModal"
/>
<modal-share ref="shareModalNode" :entity="feed.entity" />
</Dialog>
</TransitionRoot>
</template>
<script>
import {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
} from '@headlessui/vue'
import ModalWarning from '@/Shared/Overlay/ModalWarning.vue'
import ModalShare from '@/Shared/Overlay/ModalShare.vue'
import ModalFeedMedia from '@/Shared/Overlay/ModalFeedMedia.vue'
import ModalFeedBody from '@/Shared/Overlay/ModalFeedBody.vue'
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ModalFeedMedia,
ModalFeedBody,
ModalWarning,
ModalShare,
},
provide() {
return {
is_exist_menu: this.is_exist_menu
}
},
props: {
modalFeed: Object,
is_exist_menu: {
type: Boolean,
default: true,
},
open: {
type: Boolean,
default: false,
},
},
emits: ['closeModal', 'destroyFeed'],
data() {
return {
disabled: 0,
modalFeedId: 0,
warningShow: false,
feed: {},
}
},
watch: {
open(open) {
if (open) {
this.feed = this.modalFeed
}
},
},
methods: {
deleteActionModal(removeFeed) {
if (removeFeed) {
this.$emit('destroyFeed')
this.$nextTick(() => {
this.staticCloseModal()
})
}
this.warningShow = false
},
showShareModal() {
this.$refs.shareModalNode.openModal()
},
onRemoveFeed(feed_id) {
this.modalFeedId = feed_id
this.warningShow = true
},
checkCloseModal(value) {
this.disabled = value
},
staticCloseModal() {
if (!this.disabled) {
this.$emit('closeModal', false)
}
},
},
}
</script>

View File

@@ -0,0 +1,361 @@
<template>
<div class="col-span-5 modal-body flex flex-col">
<div class="modal-head mb-3 px-2 py-4 md:py-4 md:px-6 flex justify-between items-center border-b border-indigo-100">
<div v-if="entity.is_ads" class="flex items-center space-x-4">
<user-avatar :user="user" size="small"
class="w-12 h-12 md:w-16 md:h-16 border-2 border-orange text-lg"
/>
<p class="text-base md:text-xl font-semibold text-gray">
{{ user.name }}
</p>
</div>
<div v-else class="flex items-center space-x-4">
<inertia-link :href="route('profile.user', user.username)" class="flex-shrink-0 block">
<user-avatar :user="user" size="small"
class="w-12 h-12 md:w-16 md:h-16 border-2 border-orange text-lg"
/>
</inertia-link>
<inertia-link :href="route('profile.user', user.username)" class="flex flex-col">
<p class="text-base md:text-xl font-semibold text-gray">
{{ user.name }}
</p>
<p class="min-h-[24px]">
<span v-show="user.count_posts" class="md:mt-1 text-sm text-gray-light">{{ user.count_posts }} {{ countPosts }}</span>
</p>
</inertia-link>
</div>
<div v-if="is_exist_menu && entity.is_ads == false" class="text-white">
<dropdown-menu-point v-if="$page.props.auth.user">
<MenuItems class="origin-top-right absolute right-0 mt-2 w-64 bg-indigo-200 shadow-lg max-h-60 rounded-md text-base ring-1 ring-indigo-100 overflow-auto focus:outline-none">
<MenuItem v-if="user.id === $page.props.auth.user.id">
<inertia-link :href="route(`${entity.type}.edit`, entity.slug)" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-300 text-gray-light">
<PencilAltIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Редактировать
</inertia-link>
</MenuItem>
<MenuItem v-if="user.id === $page.props.auth.user.id">
<button class="w-full group flex items-center px-4 py-2 text-base hover:bg-indigo-300 text-gray-light" @click="onRemoveFeed()">
<MinusCircleIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Удалить
</button>
</MenuItem>
<MenuItem v-if="user.id !== $page.props.auth.user.id">
<inertia-link :href="route('complaint.reason', feed_id)" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-300 text-gray-light">
<ExclamationIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Пожаловаться
</inertia-link>
</MenuItem>
</MenuItems>
</dropdown-menu-point>
</div>
</div>
<!-- -->
<!-- max-h-[20rem] h-[20rem] -->
<div data-simplebar class="modal-feed min-h-[4rem] md:min-h-[22rem] max-h-[22rem] overflow-auto">
<div class="p-2 md:py-4 md:px-6 space-y-3 md:space-y-6">
<div v-if="entity.tags.length" class="">
<feed-tags :tags="entity.tags" />
</div>
<div v-if="entity.body" class="comment-line comment-line--head flex flex-col text-gray text-sm">
<div v-if="entity.is_ads" class="prose-content"
v-html="entity.body"
></div>
<div v-else class="flex group">
<inertia-link :href="route('profile.user', user.username)" class="flex-shrink-0 block mr-3">
<user-avatar :user="user" size="small"
class="w-10 h-10 border border-orange text-xs"
/>
</inertia-link>
<div>
<inertia-link :href="route('profile.user', user.username)" class="font-semibold underline inline-block mr-2">
{{ user.username }}
</inertia-link>
{{ entity.body }}
<div class="transition-opacity opacity-0 group-hover:opacity-100 flex space-x-4">
<span class="text-xs text-gray-light">{{ entity.created_at_humans }}</span>
</div>
</div>
</div>
</div>
<div v-for="comment in comments" :key="comment.id"
class="comment-line flex flex-col text-gray text-sm"
>
<user-comment :creator_id="user.id" :comment="comment"
@showChildren="loadChildrenComment" @toAnswer="sendAnswerParent"
@removeCommentItem="removeCommentItem"
/>
</div>
<div v-if="cursor" class="flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24"
height="24"
viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round"
class="cursor-pointer text-white" @click="loadComments"
><circle cx="12" cy="12"
r="10"
></circle><line x1="12" y1="8"
x2="12" y2="16"
></line><line x1="8" y1="12"
x2="16" y2="12"
></line></svg>
</div>
</div>
</div>
<div v-if="$page.props.auth.user" class="modal-footer mt-auto p-2 md:py-4 md:px-6 border-t border-indigo-100">
<feed-paid-block
:is_paid="entity.is_paid"
:user_id="user.id"
:price="entity.price"
:feed_id="feed_id"
:paid_open="entity.paid_open"
class="text-white"
@onReplaceFeed="onReplaceFeed"
/>
<div class="misc-info mt-2 md:mt-0 mb-2 flex flex-row-reverse">
<div class="flex space-x-4">
<template v-if="entity.is_ads == false">
<like-count :likes="entity.likes" :liked="entity.liked"
@likeFeed="likeFeed"
/>
<comment-count :comments="entity.comments" />
<share-count @click="openShareModal" />
</template>
<view-count :count="entity.views_count" />
</div>
</div>
<div v-if="entity.is_ads == false" class="modal-send flex">
<div class="flex-1">
<textarea v-model="new_comment"
class="pl-0 pr-2 resize-none bg-indigo-300 w-full outline-none focus:ring-transparent focus:border-transparent focus:ring-offset-0 text-base text-gray border-transparent" placeholder="Написать комментарий..."
> </textarea>
</div>
<div class="mt-1 flex-shrink-0 text-pink">
<button class="default" @click="addComment">
<svg class="w-8 h-8 flex-shrink-0">
<use xlink:href="#arrow-circle"></use>
</svg>
</button>
</div>
</div>
</div>
<div v-else class="modal-footer mt-auto p-2 md:py-4 md:px-6 border-t border-indigo-100 flex justify-center">
<a rel="nofollow" href="/login"
class="my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-pink focus:outline-none"
>
Купить
</a>
</div>
</div>
</template>
<script>
import { Inertia } from '@inertiajs/inertia'
import axios from 'axios'
import { MenuItem, MenuItems } from '@headlessui/vue'
import {
MinusCircleIcon,
ExclamationIcon,
PencilAltIcon,
} from '@heroicons/vue/solid'
import helper from '@/includes/helper'
import DropdownMenuPoint from '@/Shared/Form/DropdownMenuPoint.vue'
import FeedPaidBlock from '@/Shared/FeedList/FeedPaidBlock.vue'
import UserAvatar from '@/Shared/Misc/UserAvatar.vue'
import LikeCount from '@/Shared/Misc/LikeCount.vue'
import FeedTags from '@/Shared/Misc/FeedTags.vue'
import CommentCount from '@/Shared/Misc/CommentCount.vue'
import ShareCount from '@/Shared/Misc/ShareCount.vue'
import UserComment from '@/Shared/Partials/UserComment.vue'
import ViewCount from '@/Shared/Misc/ViewCount.vue'
export default {
components: {
DropdownMenuPoint,
MenuItem,
MenuItems,
MinusCircleIcon,
ExclamationIcon,
PencilAltIcon,
UserAvatar,
LikeCount,
ShareCount,
CommentCount,
UserComment,
FeedTags,
FeedPaidBlock,
ViewCount,
},
inject: ['is_exist_menu'],
props: {
user: Object,
entity: Object,
feed_id: Number,
},
emits: ['disableModal', 'onRemoveFeed', 'openShare'],
data() {
return {
new_comment: null,
to_user: null,
parent_send_comment: null,
comments: [],
cursor: null,
}
},
computed: {
countPosts() {
return helper.declNumPosts(this.user.count_posts)
},
},
mounted() {
if(this.entity.is_ads == false){
this.loadComments()
this.loadCountPostsUser()
}
this.addView()
},
unmounted() {
this.comments = []
this.cursor = null
},
methods: {
openShareModal(){
this.$emit('openShare')
},
sendAnswerParent(id, to_user_id, username) {
this.parent_send_comment = id
this.to_user = to_user_id
if (this.new_comment) {
this.new_comment = `@${username} ${this.new_comment}`
} else {
this.new_comment = `@${username} `
}
},
onReplaceFeed(data) {
this.entity.collection_medias = data.collection
this.entity.preview = data.preview
this.entity.paid_open = 1
},
loadCountPostsUser() {
if (
typeof this.user.count_posts === 'undefined' ||
parseInt(this.user.count_posts, 10) === 0
) {
axios.post(route('user.posts.count', this.user.id)).then(({ data }) => {
this.user.count_posts = data
})
}
},
onRemoveFeed() {
this.$emit('onRemoveFeed', this.feed_id)
},
loadComments() {
this.$emit('disableModal', 1)
const that = this
axios.post(route('comments.show', this.feed_id), { cursor: this.cursor }).then(({ data }) => {
data.items.forEach(element => {
that.comments.push(element)
})
that.cursor = data.nextCursor
that.$emit('disableModal', 0)
})
},
loadChildrenComment(id, items) {
const index = this.comments.findIndex((comment) => comment.id === id)
this.comments[index].closed_children_comments = 0
items.forEach(element => {
this.comments[index].childrens.push(element)
})
},
removeCommentItem(id, remove_count = 1, parent_id = null) {
if(parent_id){
const index = this.comments.findIndex((comment) => comment.id === parent_id)
const indexChild = this.comments[index].childrens.findIndex((comment) => comment.id === id)
this.comments[index].childrens.splice(indexChild, 1)
}else{
const index = this.comments.findIndex((comment) => comment.id === id)
this.comments.splice(index, 1)
}
this.entity.comments = this.entity.comments - remove_count
},
addView() {
axios
.post(route('add.view.feed', this.feed_id))
.then(({ data }) => {
data && this.entity.views_count++
})
},
addComment() {
if (!this.new_comment) {
return false
}
this.$emit('disableModal', 1)
axios
.post(route('comments.store', this.feed_id), {
body: this.new_comment,
parent: this.parent_send_comment,
to: this.to_user,
})
.then(({ data }) => {
if (this.parent_send_comment) {
const index = this.comments.findIndex(
(comment) => comment.id === this.parent_send_comment
)
this.comments[index].childrens.push(data)
} else {
this.comments.push(data)
}
this.entity.comments++
this.parent_send_comment = null
this.to_user = null
this.$emit('disableModal', 0)
})
this.new_comment = null
},
likeFeed() {
axios
.post(route('feed.like', this.feed_id))
.then(() => {
if (this.entity.liked) {
this.entity.liked = false
this.entity.likes--
} else {
this.entity.liked = true
this.entity.likes++
}
})
// Inertia.post(
// route('feed.like', this.feed_id),
// {},
// {
// preserveScroll: true,
// preserveState: true,
// }
// )
// if (this.entity.liked) {
// this.entity.liked = false
// this.entity.likes--
// } else {
// this.entity.liked = true
// this.entity.likes++
// }
},
},
}
</script>

View File

@@ -0,0 +1,38 @@
<template>
<div class="col-span-7 modal-media modal-media-height border-r border-indigo-100">
<component
:title="title"
:feed_id="feed_id"
:preview="preview"
:medias="medias"
:is="currentModalMedia"
></component>
</div>
</template>
<script>
import ModalFeedMediaImages from "@/Shared/Overlay/ModalFeedMediaImages.vue";
import ModalFeedMediaVideos from "@/Shared/Overlay/ModalFeedMediaVideos.vue";
import ModalFeedMediaMusics from "@/Shared/Overlay/ModalFeedMediaMusics.vue";
export default {
components: {
ModalFeedMediaImages,
ModalFeedMediaVideos,
ModalFeedMediaMusics,
},
props: {
medias: Array,
type: String,
feed_id: Number,
title: String,
preview: String,
},
computed: {
currentModalMedia() {
return "modal-feed-media-" + this.type.toLowerCase();
},
},
methods: {},
};
</script>

View File

@@ -0,0 +1,33 @@
<template>
<swiper class="h-full" :grabCursor="true" navigation :pagination="{ clickable: true }">
<swiper-slide v-for="media in medias" :key="media.id">
<img class="w-full h-full object-contain" :src="media.url" alt="" />
</swiper-slide>
</swiper>
</template>
<script>
import SwiperCore, { Navigation, Pagination } from 'swiper/core';
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";
// import "swiper/components/navigation/navigation.min.css";
// import "swiper/components/pagination/pagination.min.css";
SwiperCore.use([Navigation, Pagination]);
export default {
components: {
Swiper,
SwiperSlide,
},
props: {
medias: Array,
title: String,
preview: String,
},
methods: {},
};
</script>

View File

@@ -0,0 +1,110 @@
<template>
<div class="modal-media h-full">
<div class="flex items-center border-b border-indigo-100">
<div class="flex-shrink-0 mr-5">
<feed-preview
class="h-28 w-28 md:w-56 md:h-56 object-cover"
type="music"
:source="preview"
/>
</div>
<div class="flex flex-col">
<span class="text-base md:text-xl font-semibold text-gray">{{
title
}}</span>
</div>
</div>
<div data-simplebar class="max-h-96 overflow-auto">
<div class="divide-y divide-indigo-100">
<div
@click.prevent="startPlay(media)"
v-for="media in medias"
:key="media.id"
:class="[
currentSong?.id === media.id
? 'bg-indigo-200 bg-opacity-25'
: 'hover:bg-indigo-200 hover:bg-opacity-25',
'p-4 flex items-center space-x-4',
]"
>
<div class="flex">
<toggle-play-button :media_id="media.id" />
</div>
<div class="flex-1 text-sm text-gray-light">
{{ media.name }}
</div>
<div class="text-sm text-gray-light">
<div v-show="currentSong?.id === media.id">{{seek}}</div>
<div v-show="currentSong?.id !== media.id">{{media.time}}</div>
</div>
<music-add-count v-if="$page.props.auth.user" @addAudio="likeAudio" :media_id='media.id' :liked='media.liked' />
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState, mapGetters } from "vuex";
import { Inertia } from "@inertiajs/inertia";
import find from "lodash/find";
import FeedPreview from "@/Shared/Feed/FeedPreview.vue";
import TogglePlayButton from "@/Shared/Misc/TogglePlayButton.vue";
import MusicAddCount from "@/Shared/Misc/MusicAddCount.vue";
export default {
components: {
FeedPreview,
TogglePlayButton,
MusicAddCount,
},
props: {
medias: Array,
title: String,
preview: String,
feed_id: Number,
},
methods: {
...mapActions(["toggleAudio", "newCurrentPlaylist", "skipToIndexByMusic"]),
startPlay(music) {
if (this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
// if (this.playlist_id === this.feed_id) {
// this.skipToIndexByMusic(music);
// return;
// }
this.newCurrentPlaylist([music, this.medias, this.feed_id]);
},
likeAudio(media_id) {
Inertia.post(
route("feed.audio.like", media_id),
{},
{
preserveScroll: true,
preserveState: true,
}
);
let media = find(this.medias, (item) => item.id === media_id);
if(media){
media.liked = !media.liked;
}
},
},
computed: {
...mapGetters(["playing"]),
...mapState({
playlist_id: (state) => state.player.playlist_id,
seek: (state) => state.player.seek,
currentSong: (state) => state.player.currentSong,
}),
},
};
</script>

View File

@@ -0,0 +1,32 @@
<template>
<swiper class="h-full" :grabCursor="true" navigation :pagination="{ clickable: true }">
<swiper-slide v-for="media in medias" class="aspect-w-16 aspect-h-12 md:aspect-h-9" :key="media.id">
<video :src="media.url" controls></video>
</swiper-slide>
</swiper>
</template>
<script>
import SwiperCore, { Navigation, Pagination } from 'swiper/core';
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";
// import "swiper/components/navigation/navigation.min.css";
// import "swiper/components/pagination/pagination.min.css";
SwiperCore.use([Navigation, Pagination]);
export default {
components: {
Swiper,
SwiperSlide,
},
props: {
medias: Array,
title: String,
preview: String,
},
methods: {},
};
</script>

View File

@@ -0,0 +1,175 @@
<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" static
class="fixed z-[1000] inset-0 overflow-y-auto" :open="open"
@close="staticCloseModal"
>
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0" enter-to="opacity-100"
leave="ease-in duration-200" leave-from="opacity-100"
leave-to="opacity-0"
>
<DialogOverlay class="fixed inset-0 bg-indigo-200 bg-opacity-75 transition-opacity" />
</TransitionChild>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100"
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div class="inline-block align-bottom bg-indigo-300 rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6">
<div class="">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<DialogTitle as="h3" class="text-lg leading-6 font-medium text-gray-light">
Поделиться
</DialogTitle>
<div class="my-4">
<input :value="route(`${entity.type}.show`, entity.slug)" class="js-input-text-share w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light"
type="text" readonly
>
</div>
<div class="flex items-center justify-end -mx-1">
<div class="transition-shadow shadow-none hover:shadow-classic2 p-2 bg-[#4C75A3] text-white mx-1 cursor-pointer" title="Скопировать текст"
@click="copyText"
>
<svg xmlns="http://www.w3.org/2000/svg" width="24"
height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-copy"
><rect x="9" y="9"
width="13" height="13"
rx="2" ry="2"
></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
</div>
<div class="transition-shadow shadow-none hover:shadow-classic2 p-2 bg-[#4C75A3] text-white mx-1 cursor-pointer" @click="shareVK">
<svg xmlns="http://www.w3.org/2000/svg" width="24"
height="24" viewBox="0 0 576 512"
><path fill="currentColor" d="M545 117.7c3.7-12.5 0-21.7-17.8-21.7h-58.9c-15 0-21.9 7.9-25.6 16.7 0 0-30 73.1-72.4 120.5-13.7 13.7-20 18.1-27.5 18.1-3.7 0-9.4-4.4-9.4-16.9V117.7c0-15-4.2-21.7-16.6-21.7h-92.6c-9.4 0-15 7-15 13.5 0 14.2 21.2 17.5 23.4 57.5v86.8c0 19-3.4 22.5-10.9 22.5-20 0-68.6-73.4-97.4-157.4-5.8-16.3-11.5-22.9-26.6-22.9H38.8c-16.8 0-20.2 7.9-20.2 16.7 0 15.6 20 93.1 93.1 195.5C160.4 378.1 229 416 291.4 416c37.5 0 42.1-8.4 42.1-22.9 0-66.8-3.4-73.1 15.4-73.1 8.7 0 23.7 4.4 58.7 38.1 40 40 46.6 57.9 69 57.9h58.9c16.8 0 25.3-8.4 20.4-25-11.2-34.9-86.9-106.7-90.3-111.5-8.7-11.2-6.2-16.2 0-26.2 .1-.1 72-101.3 79.4-135.6z"></path></svg>
</div>
</div>
</div>
</div>
<div class="mt-5 sm:mt-4 sm:flex">
<button type="button"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none"
@click="staticCloseModal"
>
Отменить
</button>
</div>
</div>
</TransitionChild>
</div>
</Dialog>
</TransitionRoot>
</template>
<script>
import {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
} from '@headlessui/vue'
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
},
// emits: {
// close: null,
// },
props: {
entity: Object,
},
data() {
return {
open: false,
}
},
methods: {
openModal() {
this.open = true
},
staticCloseModal() {
this.open = false
},
copyText(){
const text = document.querySelector('.js-input-text-share')
text.select()
text.setSelectionRange(0, 99999)
navigator.clipboard.writeText(text.value)
},
shareTwitter() {
const urlInner = route(`${this.entity.type}.show`, this.entity.slug)
const body = this.entity.body ?? ''
const url = `https://twitter.com/intent/tweet?text=${body}&url=${urlInner}`
this.openWindow(url)
},
shareFB() {
const urlInner = route(`${this.entity.type}.show`, this.entity.slug)
const body = this.entity.body ?? ''
const url = `https://www.facebook.com/sharer.php?u=${urlInner}&t=${body}`
this.openWindow(url)
},
shareVK() {
const urlInner = route(`${this.entity.type}.show`, this.entity.slug)
const title = this.entity.title ?? ''
const url = `https://vk.com/share.php?url=${urlInner}&title=${title}`
this.openWindow(url)
},
openWindow(url) {
this.popupCenter({url, title: 'share', w: 600, h: 400})
},
popupCenter({ url, title, w, h }) {
const dualScreenLeft =
window.screenLeft !== undefined ? window.screenLeft : window.screenX
const dualScreenTop =
window.screenTop !== undefined ? window.screenTop : window.screenY
const width = window.innerWidth
? window.innerWidth
: document.documentElement.clientWidth
? document.documentElement.clientWidth
: screen.width
const height = window.innerHeight
? window.innerHeight
: document.documentElement.clientHeight
? document.documentElement.clientHeight
: screen.height
const systemZoom = width / window.screen.availWidth
const left = (width - w) / 2 / systemZoom + dualScreenLeft
const top = (height - h) / 2 / systemZoom + dualScreenTop
const newWindow = window.open(
url,
title,
`
scrollbars=yes,
width=${w / systemZoom},
height=${h / systemZoom},
top=${top},
left=${left}
`
)
if (window.focus) newWindow.focus()
},
},
}
</script>

View File

@@ -0,0 +1,98 @@
<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" static
class="fixed z-[1000] inset-0 overflow-y-auto" :open="open"
@close="staticCloseModal"
>
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0" enter-to="opacity-100"
leave="ease-in duration-200" leave-from="opacity-100"
leave-to="opacity-0"
>
<DialogOverlay class="fixed inset-0 bg-indigo-200 bg-opacity-75 transition-opacity" />
</TransitionChild>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100"
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div class="inline-block align-bottom bg-indigo-300 rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-orange sm:mx-0 sm:h-10 sm:w-10">
<ExclamationIcon class="h-6 w-6 text-red-600" aria-hidden="true" />
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<DialogTitle as="h3" class="text-lg leading-6 font-medium text-gray-light">
Удалить контент
</DialogTitle>
<div class="mt-2">
<p class="text-sm text-gray-light">
Вы уверены, что хотите удалить этот контент? Восстановить можно, но будет сложно!
</p>
</div>
</div>
</div>
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<button type="button"
class="mx-3 my-1 transition shadow-none hover:shadow-pink inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-pink focus:outline-none"
@click="remove"
>
Удалить
</button>
<button type="button"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none"
@click="staticCloseModal"
>
Отменить
</button>
</div>
</div>
</TransitionChild>
</div>
</Dialog>
</TransitionRoot>
</template>
<script>
import {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
} from '@headlessui/vue'
import { ExclamationIcon } from '@heroicons/vue/outline'
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ExclamationIcon,
},
props: {
feed_id: Number,
open: {
type: Boolean,
default: false,
},
},
emits: ['action'],
methods: {
staticCloseModal() {
this.$emit('action', false)
},
remove() {
this.$emit('action', true)
},
},
}
</script>