forked from mirror/pixelfed
Add CollectionCompose.vue component
This commit is contained in:
parent
e6d5dcd96b
commit
0d7a0f2381
2 changed files with 263 additions and 0 deletions
4
resources/assets/js/collectioncompose.js
vendored
Normal file
4
resources/assets/js/collectioncompose.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
Vue.component(
|
||||
'collection-compose',
|
||||
require('./components/CollectionCompose.vue').default
|
||||
);
|
259
resources/assets/js/components/CollectionCompose.vue
Normal file
259
resources/assets/js/components/CollectionCompose.vue
Normal file
|
@ -0,0 +1,259 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div v-if="loaded" class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 pt-5">
|
||||
<div class="text-center pb-4">
|
||||
<h1>Create Collection</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 pt-3">
|
||||
<div class="card rounded-0 shadow-none border " style="min-height: 440px;">
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="title" class="font-weight-bold text-muted">Title</label>
|
||||
<input type="text" class="form-control" id="title" placeholder="Collection Title" v-model="collection.title">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description" class="font-weight-bold text-muted">Description</label>
|
||||
<textarea class="form-control" id="description" placeholder="Example description here" v-model="collection.description" rows="3">
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="visibility" class="font-weight-bold text-muted">Visibility</label>
|
||||
<select class="custom-select" v-model="collection.visibility">
|
||||
<option value="public">Public</option>
|
||||
<option value="private">Followers Only</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<p>
|
||||
<button type="button" class="btn btn-primary font-weight-bold btn-block" @click="publish">Publish</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-outline-primary font-weight-bold btn-block" @click="save">Save</button>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<button type="button" class="btn btn-outline-secondary font-weight-bold btn-block" @click="deleteCollection">Delete</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-8 pt-3">
|
||||
<div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a :class="[tab == 'add' ? 'nav-link font-weight-bold bg-white active' : 'nav-link font-weight-bold text-muted']" href="#" @click.prevent="tab = 'add'">Add Post URL</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a :class="[tab == 'add' ? 'nav-link font-weight-bold bg-white active' : 'nav-link font-weight-bold text-muted']" href="#" @click.prevent="tab = 'add'">Add My Posts</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a :class="[tab == 'add' ? 'nav-link font-weight-bold bg-white active' : 'nav-link font-weight-bold text-muted']" href="#" @click.prevent="tab = 'add'">Search</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a :class="[tab == 'all' ? 'nav-link font-weight-bold bg-white active' : 'nav-link font-weight-bold text-muted']" href="#" @click.prevent="tab = 'all'">Preview</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card rounded-0 shadow-none border border-top-0">
|
||||
<div class="card-body" style="height: 460px; overflow-y: auto">
|
||||
<div v-if="tab == 'all'" class="row">
|
||||
<div class="col-4 p-1" v-for="(s, index) in posts">
|
||||
<a class="card info-overlay card-md-border-0" :href="s.url">
|
||||
<div class="square">
|
||||
<span v-if="s.pf_type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
|
||||
<span v-if="s.pf_type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
|
||||
<span v-if="s.pf_type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
|
||||
<div class="square-content" v-bind:style="previewBackground(s)">
|
||||
</div>
|
||||
<div class="info-overlay-text">
|
||||
<h5 class="text-white m-auto font-weight-bold">
|
||||
<span>
|
||||
<span class="far fa-heart fa-lg p-2 d-flex-inline"></span>
|
||||
<span class="d-flex-inline">{{s.favourites_count}}</span>
|
||||
</span>
|
||||
<span>
|
||||
<span class="fas fa-retweet fa-lg p-2 d-flex-inline"></span>
|
||||
<span class="d-flex-inline">{{s.reblogs_count}}</span>
|
||||
</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tab == 'add'">
|
||||
<div class="form-group">
|
||||
<label for="title" class="font-weight-bold text-muted">Add Post by URL</label>
|
||||
<input type="text" class="form-control" placeholder="https://pixelfed.dev/p/admin/1" v-model="id">
|
||||
<p class="help-text small text-muted">Only local, public posts can be added</p>
|
||||
</div>
|
||||
<div class="form-group pt-4">
|
||||
<label for="title" class="font-weight-bold text-muted">Add Recent Post</label>
|
||||
<div>
|
||||
<div v-for="(s, index) in recentPosts" :class="[selectedPost == s.id ? 'box-shadow border border-warning d-inline-block m-1':'d-inline-block m-1']" @click="selectPost(s)">
|
||||
<div class="cursor-pointer" :style="'width: 175px; height: 175px; ' + previewBackground(s)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" class="btn btn-primary font-weight-bold btn-block" @click="addId">Add Post</button>
|
||||
</div>
|
||||
<div v-if="tab == 'order'">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: ['collection-id', 'profile-id'],
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
limit: 8,
|
||||
step: 1,
|
||||
title: '',
|
||||
description: '',
|
||||
visibility: 'private',
|
||||
collection: {
|
||||
title: '',
|
||||
description: '',
|
||||
visibility: 'public'
|
||||
},
|
||||
id: '',
|
||||
posts: [],
|
||||
tab: 'add',
|
||||
tabs: [
|
||||
'all',
|
||||
'add',
|
||||
'order'
|
||||
],
|
||||
recentPosts: [],
|
||||
selectedPost: '',
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
axios.get('/api/local/collection/' + this.collectionId)
|
||||
.then(res => {
|
||||
this.collection = res.data;
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
this.fetchRecentPosts();
|
||||
this.fetchItems();
|
||||
},
|
||||
methods: {
|
||||
addToIds(id) {
|
||||
axios.post('/api/local/collection/item', {
|
||||
collection_id: this.collectionId,
|
||||
post_id: id
|
||||
}).then(res => {
|
||||
this.fetchItems();
|
||||
this.fetchRecentPosts();
|
||||
this.tab = 'all';
|
||||
this.id = '';
|
||||
}).catch(err => {
|
||||
swal('Invalid URL', 'The post you entered was invalid', 'error');
|
||||
this.id = '';
|
||||
})
|
||||
},
|
||||
|
||||
fetchItems() {
|
||||
axios.get('/api/local/collection/items/' + this.collectionId)
|
||||
.then(res => {
|
||||
this.posts = res.data;
|
||||
this.loaded = true;
|
||||
});
|
||||
},
|
||||
|
||||
addId() {
|
||||
let max = 18;
|
||||
if(this.posts.length >= max) {
|
||||
swal('Error', 'You can only add ' + max + ' posts per collection', 'error');
|
||||
return;
|
||||
}
|
||||
let url = this.id;
|
||||
let origin = window.location.origin;
|
||||
let split = url.split('/');
|
||||
if(url.slice(0, origin.length) !== origin) {
|
||||
swal('Invalid URL', 'You can only add posts from this instance', 'error');
|
||||
this.id = '';
|
||||
}
|
||||
if(url.slice(0, origin.length + 3) !== origin + '/p/' || split.length !== 6) {
|
||||
swal('Invalid URL', 'Invalid URL', 'error');
|
||||
this.id = '';
|
||||
}
|
||||
this.addToIds(split[5]);
|
||||
return;
|
||||
},
|
||||
|
||||
previewUrl(status) {
|
||||
return status.sensitive ? '/storage/no-preview.png?v=' + new Date().getTime() : status.media_attachments[0].preview_url;
|
||||
},
|
||||
|
||||
previewBackground(status) {
|
||||
let preview = this.previewUrl(status);
|
||||
return 'background-image: url(' + preview + ');background-size:cover;';
|
||||
},
|
||||
|
||||
fetchRecentPosts() {
|
||||
axios.get('/api/v1/accounts/' + this.profileId + '/statuses', {
|
||||
params: {
|
||||
only_media: true,
|
||||
min_id: 1,
|
||||
}
|
||||
}).then(res => {
|
||||
this.recentPosts = res.data.filter(s => {
|
||||
let ids = this.posts.map(s => {
|
||||
return s.id;
|
||||
});
|
||||
return s.visibility == 'public' && s.sensitive == false && ids.indexOf(s.id) == -1;
|
||||
}).slice(0,3);
|
||||
});
|
||||
},
|
||||
|
||||
selectPost(status) {
|
||||
this.selectedPost = status.id;
|
||||
this.id = status.url;
|
||||
},
|
||||
|
||||
publish() {
|
||||
axios.post('/api/local/collection/' + this.collectionId + '/publish')
|
||||
.then(res => {
|
||||
window.location.href = res.data;
|
||||
});
|
||||
},
|
||||
|
||||
save() {
|
||||
axios.post('/api/local/collection/' + this.collectionId, {
|
||||
title: this.collection.title,
|
||||
description: this.collection.description,
|
||||
visibility: this.collection.visibility
|
||||
})
|
||||
.then(res => {
|
||||
swal('Saved!', 'You have successfully saved this collection.', 'success');
|
||||
});
|
||||
},
|
||||
|
||||
deleteCollection() {
|
||||
let confirm = window.confirm('Are you sure you want to delete this collection?');
|
||||
if(!confirm) {
|
||||
return;
|
||||
}
|
||||
axios.delete('/api/local/collection/' + this.collectionId)
|
||||
.then(res => {
|
||||
window.location.href = '/';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue