mirror of
https://github.com/YunoHost-Apps/pixelfed_ynh.git
synced 2024-09-03 20:06:04 +02:00
Update ComposeModal.vue component
This commit is contained in:
parent
69189cfe9b
commit
5c256558d5
1 changed files with 454 additions and 215 deletions
|
@ -1,197 +1,234 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<input type="file" name="media" class="d-none file-input" multiple="" v-bind:accept="config.uploader.media_types">
|
<input type="file" id="pf-dz" name="media" class="w-100 h-100 d-none file-input" draggable="true" multiple="true" v-bind:accept="config.uploader.media_types">
|
||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
<div class="card status-card card-md-rounded-0">
|
<div class="card status-card card-md-rounded-0 w-100 h-100" style="display:flex;">
|
||||||
<div class="card-header d-inline-flex align-items-center bg-white">
|
<div class="card-header d-inline-flex align-items-center bg-white">
|
||||||
<img v-bind:src="profile.avatar" width="32px" height="32px" style="border-radius: 32px;" class="box-shadow">
|
<div>
|
||||||
<a class="username font-weight-bold pl-2 text-dark" v-bind:href="profile.url">
|
<a v-if="page == 1" href="#" @click.prevent="closeModal()" class="font-weight-bold text-decoration-none text-muted">
|
||||||
{{profile.username}}
|
<i class="fas fa-times fa-lg"></i>
|
||||||
|
<span class="font-weight-bold mb-0">{{pageTitle}}</span>
|
||||||
</a>
|
</a>
|
||||||
|
<span v-else>
|
||||||
|
<span>
|
||||||
|
<a class="text-lighter text-decoration-none mr-3" href="#" @click.prevent="goBack()"><i class="fas fa-long-arrow-alt-left fa-lg"></i></a>
|
||||||
|
</span>
|
||||||
|
<span class="font-weight-bold mb-0">{{pageTitle}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="text-right" style="flex-grow:1;">
|
<div class="text-right" style="flex-grow:1;">
|
||||||
<div class="dropdown">
|
<!-- <a v-if="page > 1" class="font-weight-bold text-decoration-none" href="#" @click.prevent="page--">Back</a> -->
|
||||||
<button class="btn btn-link text-dark no-caret dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Post options">
|
<span v-if="pageLoading">
|
||||||
<span class="fas fa-ellipsis-v fa-lg text-muted"></span>
|
<div class="spinner-border spinner-border-sm" role="status">
|
||||||
</button>
|
<span class="sr-only">Loading...</span>
|
||||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
|
</div>
|
||||||
<div class="dropdown-item small font-weight-bold" v-on:click="createCollection">Create Collection</div>
|
</span>
|
||||||
<div class="dropdown-divider"></div>
|
<a v-if="!pageLoading && (page > 1 && page <= 3) || (page == 1 && ids.length != 0)" class="font-weight-bold text-decoration-none" href="#" @click.prevent="nextPage">Next</a>
|
||||||
<div class="dropdown-item small font-weight-bold" v-on:click="about">About</div>
|
<a v-if="!pageLoading && page == 4" class="font-weight-bold text-decoration-none" href="#" @click.prevent="compose">Post</a>
|
||||||
<div class="dropdown-item small font-weight-bold" v-on:click="closeModal">Close</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card-body p-0 border-top">
|
||||||
</div>
|
<div v-if="page == 1" class="w-100 h-100 d-flex justify-content-center align-items-center" style="min-height: 400px;">
|
||||||
|
<div class="text-center">
|
||||||
<div class="postPresenterContainer">
|
<p>
|
||||||
<div v-if="uploading">
|
<a class="btn btn-primary font-weight-bold" href="/i/compose">Compose Post</a>
|
||||||
<div class="w-100 h-100 bg-light py-5" style="border-bottom: 1px solid #f1f1f1">
|
</p>
|
||||||
<div class="p-5">
|
<hr>
|
||||||
<b-progress :value="uploadProgress" :max="100" striped :animated="true"></b-progress>
|
<p>
|
||||||
<p class="text-center mb-0 font-weight-bold">Uploading ... ({{uploadProgress}}%)</p>
|
<button type="button" class="btn btn-outline-primary font-weight-bold" @click.prevent="addMedia">Compose Post <sup>BETA</sup></button>
|
||||||
</div>
|
</p>
|
||||||
</div>
|
<p>
|
||||||
</div>
|
<button class="btn btn-outline-primary font-weight-bold" @click.prevent="createCollection">New Collection</button>
|
||||||
<div v-else>
|
</p>
|
||||||
<div v-if="ids.length > 0 && ids.length != config.uploader.album_limit" class="card-header py-2 bg-primary m-2 rounded cursor-pointer" v-on:click="addMedia($event)">
|
<!-- <p>
|
||||||
<p class="text-center mb-0 font-weight-bold text-white"><i class="fas fa-plus mr-1"></i> Add Photo</p>
|
<button class="btn btn-outline-primary font-weight-bold" @click.prevent="showAddToStoryCard()">Add To My Story</button>
|
||||||
</div>
|
</p> -->
|
||||||
<div v-if="ids.length == 0" class="w-100 h-100 bg-light py-5 cursor-pointer" style="border-bottom: 1px solid #f1f1f1" v-on:click="addMedia($event)">
|
<p>
|
||||||
<div class="p-5">
|
<a class="font-weight-bold" href="/site/help">Need Help?</a>
|
||||||
<p class="text-center font-weight-bold">{{composeMessage()}}</p>
|
</p>
|
||||||
<p class="text-muted mb-0 small text-center">Accepted Formats: <b>{{acceptedFormats()}}</b></p>
|
<p class="text-muted mb-0 small text-center">Formats: <b>{{acceptedFormats()}}</b> up to <b>{{maxSize()}}</b></p>
|
||||||
<p class="text-muted mb-0 small text-center">Max File Size: <b>{{maxSize()}}</b></p>
|
|
||||||
<p class="text-muted mb-0 small text-center">Albums can contain up to <b>{{config.uploader.album_limit}}</b> photos or videos</p>
|
<p class="text-muted mb-0 small text-center">Albums can contain up to <b>{{config.uploader.album_limit}}</b> photos or videos</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="ids.length > 0">
|
|
||||||
|
|
||||||
<b-carousel id="p-carousel"
|
<div v-if="page == 2" class="w-100 h-100">
|
||||||
style="text-shadow: 1px 1px 2px #333;"
|
<div v-if="ids.length > 0">
|
||||||
controls
|
<vue-cropper
|
||||||
indicators
|
ref="cropper"
|
||||||
background="#ffffff"
|
:relativeZoom="cropper.zoom"
|
||||||
:interval="0"
|
:aspectRatio="cropper.aspectRatio"
|
||||||
v-model="carouselCursor"
|
:viewMode="cropper.viewMode"
|
||||||
|
:zoomable="cropper.zoomable"
|
||||||
|
:rotatable="true"
|
||||||
|
:src="media[0].url"
|
||||||
>
|
>
|
||||||
<b-carousel-slide v-if="ids.length > 0" v-for="(preview, index) in media" :key="'preview_media_'+index">
|
</vue-cropper>
|
||||||
<div slot="img" :class="[media[index].filter_class?media[index].filter_class:'']" style="display:flex;min-height: 320px;align-items: center;">
|
|
||||||
<img class="d-block img-fluid w-100" :src="preview.url" :alt="preview.description" :title="preview.description">
|
|
||||||
</div>
|
</div>
|
||||||
</b-carousel-slide>
|
|
||||||
</b-carousel>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="ids.length > 0 && media[carouselCursor].type == 'Image'" class="bg-dark align-items-center">
|
|
||||||
|
<div v-if="page == 3" class="w-100 h-100">
|
||||||
|
<div slot="img" style="display:flex;min-height: 420px;align-items: center;">
|
||||||
|
<img :class="'d-block img-fluid w-100 ' + [media[carouselCursor].filter_class?media[carouselCursor].filter_class:'']" :src="media[carouselCursor].url" :alt="media[carouselCursor].description" :title="media[carouselCursor].description">
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div v-if="ids.length > 0 && media[carouselCursor].type == 'Image'" class="align-items-center px-2 pt-2">
|
||||||
<ul class="nav media-drawer-filters text-center">
|
<ul class="nav media-drawer-filters text-center">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<div class="p-1 pt-3">
|
<div class="p-1 pt-3">
|
||||||
<img :src="media[carouselCursor].url" width="100px" height="60px" v-on:click.prevent="toggleFilter($event, null)" class="cursor-pointer">
|
<img :src="media[carouselCursor].url" width="100px" height="60px" v-on:click.prevent="toggleFilter($event, null)" class="cursor-pointer">
|
||||||
</div>
|
</div>
|
||||||
<a :class="[media[carouselCursor].filter_class == null ? 'nav-link text-white active' : 'nav-link text-muted']" href="#" v-on:click.prevent="toggleFilter($event, null)">No Filter</a>
|
<a :class="[media[carouselCursor].filter_class == null ? 'nav-link text-primary active' : 'nav-link text-muted']" href="#" v-on:click.prevent="toggleFilter($event, null)">No Filter</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" v-for="(filter, index) in filters">
|
<li class="nav-item" v-for="(filter, index) in filters">
|
||||||
<div class="p-1 pt-3">
|
<div class="p-1 pt-3">
|
||||||
<img :src="media[carouselCursor].url" width="100px" height="60px" :class="filter[1]" v-on:click.prevent="toggleFilter($event, filter[1])">
|
<img :src="media[carouselCursor].url" width="100px" height="60px" :class="filter[1]" v-on:click.prevent="toggleFilter($event, filter[1])">
|
||||||
</div>
|
</div>
|
||||||
<a :class="[media[carouselCursor].filter_class == filter[1] ? 'nav-link text-white active' : 'nav-link text-muted']" href="#" v-on:click.prevent="toggleFilter($event, filter[1])">{{filter[0]}}</a>
|
<a :class="[media[carouselCursor].filter_class == filter[1] ? 'nav-link text-primary active' : 'nav-link text-muted']" href="#" v-on:click.prevent="toggleFilter($event, filter[1])">{{filter[0]}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="ids.length > 0 && ['Image', 'Video'].indexOf(media[carouselCursor].type) != -1" class="bg-lighter p-2 row">
|
|
||||||
<div v-if="media[carouselCursor].type == 'Image'" class="col-12">
|
<div v-if="page == 4" class="w-100 h-100">
|
||||||
|
<div class="border-bottom mt-2">
|
||||||
|
<div class="media px-3">
|
||||||
|
<img :src="media[0].url" width="42px" height="42px" :class="[media[0].filter_class?'mr-2 ' + media[0].filter_class:'mr-2']">
|
||||||
|
<div class="media-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" class="form-control" v-model="media[carouselCursor].alt" placeholder="Optional image description">
|
<label class="font-weight-bold text-muted small d-none">Caption</label>
|
||||||
</div>
|
<textarea class="form-control border-0 rounded-0 no-focus" rows="2" placeholder="Write a caption..." style="resize:none" v-model="composeText"></textarea>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control" v-model="media[carouselCursor].license" placeholder="Optional media license">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- <div class="col-6 pt-2">
|
|
||||||
<button class="btn btn-outline-secondary btn-sm mr-1"><i class="fas fa-map-marker-alt"></i></button>
|
|
||||||
<button class="btn btn-outline-secondary btn-sm"><i class="fas fa-tools"></i></button>
|
|
||||||
</div> -->
|
|
||||||
<div class="col-12 text-right pt-2">
|
|
||||||
<button class="btn btn-outline-danger btn-sm font-weight-bold mr-1" v-on:click="deleteMedia()">Delete Media</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="card-body p-0 border-top">
|
<div class="border-bottom">
|
||||||
<div class="caption">
|
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showTagCard()">Tag people</p>
|
||||||
<textarea class="form-control mb-0 border-0 rounded-0" rows="3" placeholder="Add an optional caption" v-model="composeText"></textarea>
|
</div>
|
||||||
|
<div class="border-bottom">
|
||||||
|
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showLocationCard()" v-if="!place">Add location</p>
|
||||||
|
<p v-else class="px-4 mb-0 py-2">
|
||||||
|
<span class="text-lighter">Location:</span> {{place.name}}, {{place.country}}
|
||||||
|
<span class="float-right">
|
||||||
|
<a href="#" @click.prevent="showLocationCard()" class="text-muted font-weight-bold small mr-2">Change</a>
|
||||||
|
<a href="#" @click.prevent="place = false" class="text-muted font-weight-bold small">Remove</a>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="border-bottom">
|
||||||
|
<p class="px-4 mb-0 py-2">
|
||||||
|
<span class="text-lighter">Visibility:</span> {{visibilityTag}}
|
||||||
|
<span class="float-right">
|
||||||
|
<a href="#" @click.prevent="showVisibilityCard()" class="text-muted font-weight-bold small mr-2">Change</a>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style="min-height: 200px;">
|
||||||
|
<p class="px-4 mb-0 py-2 small font-weight-bold text-muted cursor-pointer" @click="showAdvancedSettingsCard()">Advanced settings</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-footer">
|
<div v-if="page == 'tagPeople'" class="w-100 h-100 p-3">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<p class="text-center lead text-muted mb-0 py-5">This feature is not available yet.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="page == 'addLocation'" class="w-100 h-100 p-3">
|
||||||
|
<p class="mb-0">Add Location</p>
|
||||||
|
<autocomplete
|
||||||
|
:search="locationSearch"
|
||||||
|
placeholder="Search locations ..."
|
||||||
|
aria-label="Search locations ..."
|
||||||
|
:get-result-value="getResultValue"
|
||||||
|
@submit="onSubmitLocation"
|
||||||
|
>
|
||||||
|
</autocomplete>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="page == 'advancedSettings'" class="w-100 h-100">
|
||||||
|
<div class="list-group list-group-flush">
|
||||||
|
<div class="list-group-item d-flex justify-content-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="custom-control custom-switch d-inline mr-3">
|
<div class="text-dark ">Turn off commenting</div>
|
||||||
<input type="checkbox" class="custom-control-input" id="nsfwToggle" v-model="nsfw">
|
<p class="text-muted small mb-0">Disables comments for this post, you can change this later.</p>
|
||||||
<label class="custom-control-label small font-weight-bold text-muted pt-1" for="nsfwToggle">NSFW</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown d-inline">
|
<div>
|
||||||
<button class="btn btn-outline-secondary btn-sm py-0 dropdown-toggle" type="button" id="visibility" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<div class="custom-control custom-switch" style="z-index: 9999;">
|
||||||
{{visibility[0].toUpperCase() + visibility.slice(1)}}
|
<input type="checkbox" class="custom-control-input" id="asdisablecomments" v-model="commentsDisabled">
|
||||||
</button>
|
<label class="custom-control-label" for="asdisablecomments"></label>
|
||||||
<div class="dropdown-menu" aria-labelledby="visibility" style="width: 200px;">
|
|
||||||
<a :class="[visibility=='public'?'dropdown-item active':'dropdown-item']" href="#" data-id="public" data-title="Public" v-on:click.prevent="visibility = 'public'">
|
|
||||||
<div class="row">
|
|
||||||
<div class="d-none d-block-sm col-sm-2 px-0 text-center">
|
|
||||||
<i class="fas fa-globe"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-10 pl-2">
|
|
||||||
<p class="font-weight-bold mb-0">Public</p>
|
|
||||||
<p class="small mb-0">Anyone can see</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list-group-item d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
<div class="text-dark ">Contains NSFW Media</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="custom-control custom-switch" style="z-index: 9999;">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="asnsfw" v-model="nsfw">
|
||||||
|
<label class="custom-control-label" for="asnsfw"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="list-group-item" @click.prevent="page = 'altText'">
|
||||||
|
<div class="text-dark">Write alt text</div>
|
||||||
|
<p class="text-muted small mb-0">Alt text describes your photos for people with visual impairments.</p>
|
||||||
</a>
|
</a>
|
||||||
<a :class="[visibility=='private'?'dropdown-item active':'dropdown-item']" href="#" data-id="private" data-title="Followers Only" v-on:click.prevent="visibility = 'private'">
|
<a href="#" class="list-group-item" @click.prevent="page = 'addToCollection'">
|
||||||
<div class="row">
|
<div class="text-dark">Add to Collection</div>
|
||||||
<div class="d-none d-block-sm col-sm-2 px-0 text-center">
|
<p class="text-muted small mb-0">Add this post to a collection.</p>
|
||||||
<i class="fas fa-lock"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-10 pl-2">
|
|
||||||
<p class="font-weight-bold mb-0">Followers Only</p>
|
|
||||||
<p class="small mb-0">Only followers can see</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
<a :class="[visibility=='unlisted'?'dropdown-item active':'dropdown-item']" href="#" data-id="private" data-title="Unlisted" v-on:click.prevent="visibility = 'unlisted'">
|
<a href="#" class="list-group-item" @click.prevent="page = 'schedulePost'">
|
||||||
<div class="row">
|
<div class="text-dark">Schedule</div>
|
||||||
<div class="d-none d-block-sm col-sm-2 px-0 text-center">
|
<p class="text-muted small mb-0">Schedule post for a future date.</p>
|
||||||
<i class="fas fa-lock"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-10 pl-2">
|
|
||||||
<p class="font-weight-bold mb-0">Unlisted</p>
|
|
||||||
<p class="small mb-0">Not listed on public timelines</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
<!-- <a class="dropdown-item" href="#" data-id="circle" data-title="Circle">
|
<a href="#" class="list-group-item" @click.prevent="page = 'mediaMetadata'">
|
||||||
<div class="row">
|
<div class="text-dark">Metadata</div>
|
||||||
<div class="col-12 col-sm-2 px-0 text-center">
|
<p class="text-muted small mb-0">Manage media exif and metadata.</p>
|
||||||
<i class="far fa-circle"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-10 pl-2">
|
|
||||||
<p class="font-weight-bold mb-0">Circle</p>
|
|
||||||
<p class="small mb-0">Select a circle</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
<a class="dropdown-item" href="#" data-id="direct" data-title="Direct Message">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 col-sm-2 px-0 text-center">
|
|
||||||
<i class="fas fa-envelope"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-10 pl-2">
|
|
||||||
<p class="font-weight-bold mb-0">Direct Message</p>
|
|
||||||
<p class="small mb-0">Recipients only</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a> -->
|
|
||||||
|
<div v-if="page == 'visibility'" class="w-100 h-100">
|
||||||
|
<div class="list-group list-group-flush">
|
||||||
|
<div :class="'list-group-item lead cursor-pointer ' + [visibility == 'public'?'text-primary':'']" @click="toggleVisibility('public')">Public</div>
|
||||||
|
<div :class="'list-group-item lead cursor-pointer ' + [visibility == 'unlisted'?'text-primary':'']" @click="toggleVisibility('unlisted')">Unlisted</div>
|
||||||
|
<div :class="'list-group-item lead cursor-pointer ' + [visibility == 'private'?'text-primary':'']" @click="toggleVisibility('private')">Followers Only</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="page == 'altText'" class="w-100 h-100 p-3">
|
||||||
|
<p class="text-center lead text-muted mb-0 py-5">This feature is not available yet.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="small text-muted font-weight-bold">
|
|
||||||
{{composeText.length}} / {{config.uploader.max_caption_length}}
|
<div v-if="page == 'addToCollection'" class="w-100 h-100 p-3">
|
||||||
|
<p class="text-center lead text-muted mb-0 py-5">This feature is not available yet.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-md-5">
|
|
||||||
<!-- <div class="btn-group">
|
<div v-if="page == 'schedulePost'" class="w-100 h-100 p-3">
|
||||||
<button type="button" class="btn btn-primary btn-sm font-weight-bold" v-on:click="compose()">{{composeState[0].toUpperCase() + composeState.slice(1)}}</button>
|
<p class="text-center lead text-muted mb-0 py-5">This feature is not available yet.</p>
|
||||||
<button type="button" class="btn btn-primary btn-sm dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="sr-only">Toggle Dropdown</span>
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
|
||||||
<a :class="[composeState == 'publish' ?'dropdown-item font-weight-bold active':'dropdown-item font-weight-bold ']" href="#" v-on:click.prevent="composeState = 'publish'">Publish now</a>
|
|
||||||
<!- - <a :class="[composeState == 'draft' ?'dropdown-item font-weight-bold active':'dropdown-item font-weight-bold ']" href="#" v-on:click.prevent="composeState = 'draft'">Save as draft</a>
|
|
||||||
<a :class="[composeState == 'schedule' ?'dropdown-item font-weight-bold active':'dropdown-item font-weight-bold ']" href="#" v-on:click.prevent="composeState = 'schedule'">Schedule for later</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a :class="[composeState == 'delete' ?'dropdown-item font-weight-bold active':'dropdown-item font-weight-bold ']" href="#" v-on:click.prevent="composeState = 'delete'">Delete</a> - ->
|
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
|
||||||
<button class="btn btn-primary btn-sm font-weight-bold px-3" v-on:click="compose()">Publish</button>
|
<div v-if="page == 'mediaMetadata'" class="w-100 h-100 p-3">
|
||||||
|
<p class="text-center lead text-muted mb-0 py-5">This feature is not available yet.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="page == 'addToStory'" class="w-100 h-100 p-3">
|
||||||
|
<p class="text-center lead text-muted mb-0 py-5">This feature is not available yet.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- card-footers -->
|
||||||
|
<div v-if="page == 2" class="card-footer bg-white d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" @click="rotate"><i class="fas fa-undo"></i></button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="d-inline-block button-group">
|
||||||
|
<button :class="'btn font-weight-bold ' + [cropper.aspectRatio == 16/9 ? 'btn-primary':'btn-light']" @click.prevent="changeAspect(16/9)">16:9</button>
|
||||||
|
<button :class="'btn font-weight-bold ' + [cropper.aspectRatio == 4/3 ? 'btn-primary':'btn-light']" @click.prevent="changeAspect(4/3)">4:3</button>
|
||||||
|
<button :class="'btn font-weight-bold ' + [cropper.aspectRatio == 3/2 ? 'btn-primary':'btn-light']" @click.prevent="changeAspect(3/2)">3:2</button>
|
||||||
|
<button :class="'btn font-weight-bold ' + [cropper.aspectRatio == 1 ? 'btn-primary':'btn-light']" @click.prevent="changeAspect(1)">1:1</button>
|
||||||
|
<button :class="'btn font-weight-bold ' + [cropper.aspectRatio == 2/3 ? 'btn-primary':'btn-light']" @click.prevent="changeAspect(2/3)">2:3</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -219,12 +256,36 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.no-focus {
|
||||||
|
border-color: none;
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
a.list-group-item {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a.list-group-item:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: #f8f9fa !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
import VueCropper from 'vue-cropperjs';
|
||||||
|
import 'cropperjs/dist/cropper.css';
|
||||||
|
import Autocomplete from '@trevoreyre/autocomplete-vue'
|
||||||
|
import '@trevoreyre/autocomplete-vue/dist/style.css'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
VueCropper,
|
||||||
|
Autocomplete
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: window.App.config,
|
config: window.App.config,
|
||||||
|
pageLoading: false,
|
||||||
profile: {},
|
profile: {},
|
||||||
composeText: '',
|
composeText: '',
|
||||||
composeTextLength: 0,
|
composeTextLength: 0,
|
||||||
|
@ -233,12 +294,37 @@ export default {
|
||||||
ids: [],
|
ids: [],
|
||||||
media: [],
|
media: [],
|
||||||
carouselCursor: 0,
|
carouselCursor: 0,
|
||||||
visibility: 'public',
|
|
||||||
mediaDrawer: false,
|
|
||||||
composeState: 'publish',
|
|
||||||
uploading: false,
|
uploading: false,
|
||||||
uploadProgress: 0,
|
uploadProgress: 100,
|
||||||
composeType: false
|
composeType: false,
|
||||||
|
page: 1,
|
||||||
|
composeState: 'publish',
|
||||||
|
visibility: 'public',
|
||||||
|
visibilityTag: 'Public',
|
||||||
|
nsfw: false,
|
||||||
|
place: false,
|
||||||
|
commentsDisabled: false,
|
||||||
|
pageTitle: '',
|
||||||
|
|
||||||
|
cropper: {
|
||||||
|
aspectRatio: 1,
|
||||||
|
viewMode: 1,
|
||||||
|
zoomable: true,
|
||||||
|
zoom: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
taggedUsernames: false,
|
||||||
|
namedPages: [
|
||||||
|
'tagPeople',
|
||||||
|
'addLocation',
|
||||||
|
'advancedSettings',
|
||||||
|
'visibility',
|
||||||
|
'altText',
|
||||||
|
'addToCollection',
|
||||||
|
'schedulePost',
|
||||||
|
'mediaMetadata',
|
||||||
|
'addToStory'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -294,9 +380,20 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
fetchConfig() {
|
||||||
|
axios.get('/api/v2/config').then(res => {
|
||||||
|
this.config = res.data;
|
||||||
|
window.pixelfed.config = window.pixelfed.config || res.data;
|
||||||
|
if(this.config.uploader.media_types.includes('video/mp4') == false) {
|
||||||
|
this.composeType = 'post'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
fetchProfile() {
|
fetchProfile() {
|
||||||
axios.get('/api/v1/accounts/verify_credentials').then(res => {
|
axios.get('/api/v1/accounts/verify_credentials').then(res => {
|
||||||
this.profile = res.data;
|
this.profile = res.data;
|
||||||
|
window.pixelfed.currentUser = res.data;
|
||||||
if(res.data.locked == true) {
|
if(res.data.locked == true) {
|
||||||
this.visibility = 'private';
|
this.visibility = 'private';
|
||||||
}
|
}
|
||||||
|
@ -315,10 +412,17 @@ export default {
|
||||||
|
|
||||||
mediaWatcher() {
|
mediaWatcher() {
|
||||||
let self = this;
|
let self = this;
|
||||||
$(document).on('change', '.file-input', function(e) {
|
self.mediaDragAndDrop();
|
||||||
let io = document.querySelector('.file-input');
|
$(document).on('change', '#pf-dz', function(e) {
|
||||||
Array.prototype.forEach.call(io.files, function(io, i) {
|
self.mediaUpload();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
mediaUpload() {
|
||||||
|
let self = this;
|
||||||
self.uploading = true;
|
self.uploading = true;
|
||||||
|
let io = document.querySelector('#pf-dz');
|
||||||
|
Array.prototype.forEach.call(io.files, function(io, i) {
|
||||||
if(self.media && self.media.length + i >= self.config.uploader.album_limit) {
|
if(self.media && self.media.length + i >= self.config.uploader.album_limit) {
|
||||||
swal('Error', 'You can only upload ' + self.config.uploader.album_limit + ' photos per album', 'error');
|
swal('Error', 'You can only upload ' + self.config.uploader.album_limit + ' photos per album', 'error');
|
||||||
return;
|
return;
|
||||||
|
@ -346,6 +450,7 @@ export default {
|
||||||
self.uploadProgress = 100;
|
self.uploadProgress = 100;
|
||||||
self.ids.push(e.data.id);
|
self.ids.push(e.data.id);
|
||||||
self.media.push(e.data);
|
self.media.push(e.data);
|
||||||
|
self.page = 2;
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
self.uploading = false;
|
self.uploading = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -357,7 +462,36 @@ export default {
|
||||||
io.value = null;
|
io.value = null;
|
||||||
self.uploadProgress = 0;
|
self.uploadProgress = 0;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
mediaDragAndDrop() {
|
||||||
|
let self = this;
|
||||||
|
let pdz = document.getElementById('content');
|
||||||
|
|
||||||
|
function allowDrag(e) {
|
||||||
|
e.dataTransfer.dropEffect = 'copy';
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDrop(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let dz = document.querySelector('#pf-dz');
|
||||||
|
dz.files = e.dataTransfer.files;
|
||||||
|
$('#composeModal').modal('show');
|
||||||
|
self.mediaUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('dragenter', function(e) {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pdz.addEventListener('dragenter', allowDrag);
|
||||||
|
pdz.addEventListener('dragover', allowDrag);
|
||||||
|
|
||||||
|
pdz.addEventListener('dragleave', function(e) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
|
||||||
|
pdz.addEventListener('drop', handleDrop);
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleFilter(e, filter) {
|
toggleFilter(e, filter) {
|
||||||
|
@ -446,18 +580,15 @@ export default {
|
||||||
media: this.media,
|
media: this.media,
|
||||||
caption: this.composeText,
|
caption: this.composeText,
|
||||||
visibility: this.visibility,
|
visibility: this.visibility,
|
||||||
cw: this.nsfw
|
cw: this.nsfw,
|
||||||
|
comments_disabled: this.commentsDisabled,
|
||||||
|
place: this.place
|
||||||
};
|
};
|
||||||
axios.post('/api/v2/status/compose', data)
|
axios.post('/api/local/status/compose', data)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
window.location.href = data;
|
window.location.href = data;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
let res = err.response.data;
|
|
||||||
if(res.message == 'Too Many Attempts.') {
|
|
||||||
swal('You\'re posting too much!', 'We only allow 50 posts per hour or 100 per day. If you\'ve reached that limit, please try again later. If you think this is an error, please contact an administrator.', 'error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
swal('Oops, something went wrong!', 'An unexpected error occurred.', 'error');
|
swal('Oops, something went wrong!', 'An unexpected error occurred.', 'error');
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -507,6 +638,45 @@ export default {
|
||||||
window.location.href = '/i/collections/create';
|
window.location.href = '/i/collections/create';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
nextPage() {
|
||||||
|
switch(this.page) {
|
||||||
|
case 1:
|
||||||
|
this.page = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
this.pageLoading = true;
|
||||||
|
let self = this;
|
||||||
|
this.$refs.cropper.getCroppedCanvas().toBlob(function(blob) {
|
||||||
|
let data = new FormData();
|
||||||
|
data.append('file', blob);
|
||||||
|
let url = '/api/local/compose/media/update/' + self.ids[self.carouselCursor];
|
||||||
|
|
||||||
|
axios.post(url, data).then(res => {
|
||||||
|
self.media[self.carouselCursor].url = res.data.url;
|
||||||
|
self.pageLoading = false;
|
||||||
|
self.page++;
|
||||||
|
}).catch(err => {
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
this.page++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
rotate() {
|
||||||
|
this.$refs.cropper.rotate(90);
|
||||||
|
},
|
||||||
|
|
||||||
|
changeAspect(ratio) {
|
||||||
|
this.cropper.aspectRatio = ratio;
|
||||||
|
this.$refs.cropper.setAspectRatio(ratio);
|
||||||
|
},
|
||||||
|
|
||||||
maxSize() {
|
maxSize() {
|
||||||
let limit = this.config.uploader.max_photo_size;
|
let limit = this.config.uploader.max_photo_size;
|
||||||
return limit / 1000 + ' MB';
|
return limit / 1000 + ' MB';
|
||||||
|
@ -517,6 +687,75 @@ export default {
|
||||||
return formats.split(',').map(f => {
|
return formats.split(',').map(f => {
|
||||||
return ' ' + f.split('/')[1];
|
return ' ' + f.split('/')[1];
|
||||||
}).toString();
|
}).toString();
|
||||||
|
},
|
||||||
|
|
||||||
|
showTagCard() {
|
||||||
|
this.pageTitle = 'Tag People';
|
||||||
|
this.page = 'tagPeople';
|
||||||
|
},
|
||||||
|
|
||||||
|
showLocationCard() {
|
||||||
|
this.pageTitle = 'Add Location';
|
||||||
|
this.page = 'addLocation';
|
||||||
|
},
|
||||||
|
|
||||||
|
showAdvancedSettingsCard() {
|
||||||
|
this.pageTitle = 'Advanced Settings';
|
||||||
|
this.page = 'advancedSettings';
|
||||||
|
},
|
||||||
|
|
||||||
|
locationSearch(input) {
|
||||||
|
if (input.length < 1) { return []; };
|
||||||
|
let results = [];
|
||||||
|
return axios.get('/api/local/compose/location/search', {
|
||||||
|
params: {
|
||||||
|
q: input
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
return res.data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getResultValue(result) {
|
||||||
|
return result.name + ', ' + result.country
|
||||||
|
},
|
||||||
|
|
||||||
|
onSubmitLocation(result) {
|
||||||
|
this.place = result;
|
||||||
|
this.pageTitle = '';
|
||||||
|
this.page = 4;
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
|
||||||
|
goBack() {
|
||||||
|
this.pageTitle = '';
|
||||||
|
if(this.page == 'addToStory') {
|
||||||
|
this.page = 1;
|
||||||
|
} else {
|
||||||
|
this.namedPages.indexOf(this.page) != -1 ? this.page = 4 : this.page--;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showVisibilityCard() {
|
||||||
|
this.pageTitle = 'Post Visibility';
|
||||||
|
this.page = 'visibility';
|
||||||
|
},
|
||||||
|
|
||||||
|
showAddToStoryCard() {
|
||||||
|
this.pageTitle = 'Add to Story';
|
||||||
|
this.page = 'addToStory';
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleVisibility(state) {
|
||||||
|
let tags = {
|
||||||
|
public: 'Public',
|
||||||
|
private: 'Followers Only',
|
||||||
|
unlisted: 'Unlisted'
|
||||||
|
}
|
||||||
|
this.visibility = state;
|
||||||
|
this.visibilityTag = tags[state];
|
||||||
|
this.pageTitle = '';
|
||||||
|
this.page = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue