mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Initial migration to Vue
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Ubuntu');
|
||||
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@@ -1,166 +1,98 @@
|
||||
$(function () {
|
||||
function err(msg) {
|
||||
alert(msg);
|
||||
}
|
||||
|
||||
function createFeed(data, done) {
|
||||
if (!data.url) {
|
||||
return;
|
||||
}
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
|
||||
$.ajax({
|
||||
dataType: 'text',
|
||||
url: '/api/create',
|
||||
method: 'POST',
|
||||
data: JSON.stringify(data),
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function (resp) {
|
||||
done(JSON.parse(resp));
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
var text = '';
|
||||
data: {
|
||||
link: '',
|
||||
format: 'video',
|
||||
quality: 'high',
|
||||
count: 50,
|
||||
|
||||
try {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
if (json['error']) {
|
||||
text = json['error'];
|
||||
}
|
||||
} catch (e) {
|
||||
text = xhr.responseText;
|
||||
}
|
||||
showModal: false,
|
||||
feedLink: '',
|
||||
|
||||
err(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Server variables
|
||||
featureLevel: 0
|
||||
},
|
||||
|
||||
function displayLink(obj) {
|
||||
var addr = location.protocol + '//' + location.hostname + '/' + obj.id;
|
||||
showModal(addr);
|
||||
}
|
||||
methods: {
|
||||
submit: function() {
|
||||
var vm = this;
|
||||
|
||||
/*
|
||||
Tooltips
|
||||
*/
|
||||
|
||||
if (!isMobile()) {
|
||||
$(document).on('mouseenter', 'i', function () {
|
||||
var title = $(this).attr('title');
|
||||
if (!title) {
|
||||
if (vm.link === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$(this).data('tipText', title).removeAttr('title');
|
||||
$('<p class="tooltip"></p>').text(title).appendTo('body').fadeIn('fast');
|
||||
axios.post('/api/create', {
|
||||
url: this.link,
|
||||
format: this.format,
|
||||
quality: this.quality,
|
||||
page_size: this.count,
|
||||
}).then(function(response) {
|
||||
vm.feedLink = vm.formatLink(response.data.id);
|
||||
vm.showModal = true;
|
||||
vm.link = '';
|
||||
}).catch(vm.httpError);
|
||||
},
|
||||
|
||||
httpError: function(error) {
|
||||
try {
|
||||
this.showError(error.response.data.error);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.showError(error.message);
|
||||
}
|
||||
},
|
||||
|
||||
showError: function(msg) {
|
||||
alert(msg);
|
||||
},
|
||||
|
||||
formatLink: function(id) {
|
||||
if (location.port === '80' || location.port === '443') {
|
||||
return location.protocol + '//' + location.hostname + '/' + id;
|
||||
} else {
|
||||
return location.protocol + '//' + location.host + '/' + id;
|
||||
}
|
||||
},
|
||||
|
||||
copyLink: function() {
|
||||
if (!this.showModal || !this.canCopy) {
|
||||
return
|
||||
}
|
||||
|
||||
this.$refs.output.select();
|
||||
|
||||
if (!document.execCommand('copy')) {
|
||||
self.showError('Can\'t copy... Something went wrong...');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
locked: function() {
|
||||
return this.featureLevel === 0;
|
||||
},
|
||||
|
||||
isMobile: function() {
|
||||
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
||||
},
|
||||
|
||||
canCopy: function() {
|
||||
try {
|
||||
return document.queryCommandSupported('copy') && !this.isMobile;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted: function() {
|
||||
var vm = this;
|
||||
window.addEventListener('keydown', function(event) {
|
||||
// ESC handler
|
||||
if (event.keyCode === 27 && vm.showModal) {
|
||||
vm.showModal = false;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('mouseleave', 'i', function () {
|
||||
var text = $(this).data('tipText');
|
||||
$(this).attr('title', text);
|
||||
$('.tooltip').remove();
|
||||
});
|
||||
|
||||
$(document).on('mousemove', 'i', function (e) {
|
||||
var x = e.pageX + 10;
|
||||
var y = e.pageY + 5;
|
||||
$('.tooltip').css({ top: y, left: x });
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Handlers
|
||||
*/
|
||||
|
||||
function getFormat() {
|
||||
return $('input[name=episode_format]:checked').val();
|
||||
}
|
||||
|
||||
function getQuality() {
|
||||
return $('input[name=episode_quality]:checked').val();
|
||||
}
|
||||
|
||||
function getPageCount() {
|
||||
try {
|
||||
var text = $('input[name=page_count]:checked').val();
|
||||
return parseInt(text);
|
||||
} catch (e) {
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
|
||||
function closeModal() {
|
||||
$('#modal').hide();
|
||||
$('#url-input').val('');
|
||||
$('.main').show();
|
||||
}
|
||||
|
||||
function showModal(url) {
|
||||
// Hide main block on screen
|
||||
$('.main').hide();
|
||||
|
||||
// Set input URL
|
||||
$('#output-input').val(url);
|
||||
|
||||
// Update 'Open' button link
|
||||
$('#modal-open').attr('href', url);
|
||||
|
||||
// Show dialog itself
|
||||
$('#modal').show();
|
||||
|
||||
// Select modal output text
|
||||
$('#output-input').select();
|
||||
}
|
||||
|
||||
function copyLink() {
|
||||
$('#output-input').select();
|
||||
if (!document.execCommand('copy')) {
|
||||
err('Can\'t copy... Something went wrong...');
|
||||
}
|
||||
}
|
||||
|
||||
function isMobile() {
|
||||
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
function canCopy() {
|
||||
try {
|
||||
return document.queryCommandSupported('copy') && !isMobile();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$('body').on('keydown', function (e) {
|
||||
// ESC
|
||||
if ($('#modal').is(':visible') && e.keyCode === 27) {
|
||||
$('#close-modal').click();
|
||||
}
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
/*
|
||||
Attach handlers
|
||||
*/
|
||||
|
||||
$('#get-link').click(function(e) {
|
||||
var url = $('#url-input').val();
|
||||
createFeed({ url: url, format: getFormat(), quality: getQuality(), page_size: getPageCount() }, displayLink);
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('#url-input').keyup(function (e) {
|
||||
// 'Enter' click
|
||||
if (e.keyCode === 13) {
|
||||
$('#get-link').click();
|
||||
}
|
||||
});
|
||||
|
||||
$('#close-modal').click(closeModal);
|
||||
$('#modal-copy').click(copyLink);
|
||||
|
||||
if (!canCopy()) {
|
||||
$('#modal-copy').hide();
|
||||
}
|
||||
});
|
@@ -20,7 +20,7 @@
|
||||
|
||||
<body>
|
||||
|
||||
<div class="background-image">
|
||||
<div class="background-image" id="app">
|
||||
<div class="title">
|
||||
<h1>Podsync</h1>
|
||||
|
||||
@@ -30,30 +30,37 @@
|
||||
</h2>
|
||||
|
||||
<div class="login-block">
|
||||
{{if .UserId }}
|
||||
<p>
|
||||
Yo, <i class="fa fa-user-circle" aria-hidden="true"></i> {{ .FullName }} ( <a href="/logout"><i
|
||||
class="fa fa-sign-out" aria-hidden="true"></i>logout</a>)
|
||||
</p>
|
||||
{{else}}
|
||||
<h5>
|
||||
<a href="/login">
|
||||
Login with Patreon to unlock features
|
||||
<i class="fa fa-question-circle master-tooltip" aria-hidden="true"
|
||||
title="We have added advanced features for those who supported development. Login with your Patreon account to unlock them.">
|
||||
</i>
|
||||
</a>
|
||||
</h5>
|
||||
{{end}}
|
||||
<template v-if="locked">
|
||||
<h5>
|
||||
<a href="/login">
|
||||
Login with Patreon to unlock features
|
||||
<i class="fa fa-question-circle master-tooltip" aria-hidden="true"
|
||||
title="We have added advanced features for those who supported development. Login with your Patreon account to unlock them.">
|
||||
</i>
|
||||
</a>
|
||||
</h5>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>
|
||||
Yo, <i class="fa fa-user-circle" aria-hidden="true"></i> {{ .FullName }} ( <a href="/logout"><i
|
||||
class="fa fa-sign-out" aria-hidden="true"></i>logout</a>)
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<div class="main" v-if="!showModal" v-cloak>
|
||||
<div class="main-border shadow">
|
||||
<div class="input-border">
|
||||
<input id="url-input" type="url" placeholder="paste your link here" spellcheck="false" autofocus/>
|
||||
<input v-model="link"
|
||||
@keyup.enter="submit"
|
||||
type="text"
|
||||
placeholder="paste your link here"
|
||||
spellcheck="false"
|
||||
autofocus />
|
||||
|
||||
<div class="arrow-button">
|
||||
<a href="#" id="get-link">
|
||||
<a href="#" id="get-link" @click="submit">
|
||||
<i class="fa fa-arrow-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
@@ -61,40 +68,41 @@
|
||||
|
||||
<div class="controls">
|
||||
<div class="controls-icon">
|
||||
{{if gt .FeatureLevel 0 }}
|
||||
<i class="fa fa-wrench" aria-hidden="true"></i>
|
||||
{{else}}
|
||||
<i class="fa fa-question-circle master-tooltip"
|
||||
aria-hidden="true"
|
||||
title="This features are available for patrons only. You may support us and unlock this features"></i>
|
||||
{{end}}
|
||||
<template v-if="locked">
|
||||
<i class="fa fa-question-circle master-tooltip"
|
||||
aria-hidden="true"
|
||||
title="This features are available for patrons only. You may support us and unlock this features"></i>
|
||||
</template>
|
||||
<template v-else>
|
||||
<i class="fa fa-wrench" aria-hidden="true"></i>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="{{if eq .FeatureLevel 0 }}locked{{end}}">
|
||||
<div :class="{ locked: locked }">
|
||||
|
||||
<div class="switch-field">
|
||||
<div class="switch-title">format </div>
|
||||
<input type="radio" id="type_video" value="video" name="episode_format" checked/>
|
||||
<input type="radio" id="type_video" value="video" name="episode_format" v-model="format" :disabled="locked" />
|
||||
<label for="type_video">video</label>
|
||||
<input type="radio" id="type_audio" value="audio" name="episode_format" />
|
||||
<input type="radio" id="type_audio" value="audio" name="episode_format" v-model="format" :disabled="locked" />
|
||||
<label for="type_audio">audio</label>
|
||||
</div>
|
||||
|
||||
<div class="switch-field">
|
||||
<div class="switch-title">quality </div>
|
||||
<input type="radio" id="quality_low" value="low" name="episode_quality" />
|
||||
<input type="radio" id="quality_low" value="low" name="episode_quality" v-model="quality" :disabled="locked" />
|
||||
<label for="quality_low">low</label>
|
||||
<input type="radio" id="quality_high" value="high" name="episode_quality" checked />
|
||||
<input type="radio" id="quality_high" value="high" name="episode_quality" v-model="quality" :disabled="locked" />
|
||||
<label for="quality_high">high</label>
|
||||
</div>
|
||||
|
||||
<div class="switch-field">
|
||||
<div class="switch-title">episode count </div>
|
||||
<input type="radio" id="page_50" value="50" name="page_count" checked />
|
||||
<input type="radio" id="page_50" value="50" name="page_count" v-model.number="count" :disabled="locked" />
|
||||
<label for="page_50">50</label>
|
||||
<input type="radio" id="page_100" value="100" name="page_count" />
|
||||
<input type="radio" id="page_100" value="100" name="page_count" v-model.number="count" :disabled="locked" />
|
||||
<label for="page_100">100</label>
|
||||
<input type="radio" id="page_150" value="150" name="page_count" />
|
||||
<input type="radio" id="page_150" value="150" name="page_count" v-model.number="count" :disabled="locked" />
|
||||
<label for="page_150">150</label>
|
||||
</div>
|
||||
|
||||
@@ -112,29 +120,30 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="modal" style="display: none">
|
||||
<input type="url" id="output-input" readonly/>
|
||||
<!-- Modal dialog -->
|
||||
<div v-cloak v-if="showModal" class="modal">
|
||||
<input type="url" v-model="feedLink" ref="output" readonly />
|
||||
<div class="modal-links">
|
||||
<span>
|
||||
<a id="modal-copy" href="#">
|
||||
<i class="fa fa-clone" aria-hidden="true"></i>
|
||||
Copy
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="canCopy">
|
||||
<a id="modal-copy" href="#" @click="copyLink">
|
||||
<i class="fa fa-clone" aria-hidden="true"></i>
|
||||
Copy
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<a id="modal-open" href="#" target="_blank">
|
||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||
Open
|
||||
</a>
|
||||
</span>
|
||||
<a id="modal-open" :href="feedLink" target="_blank">
|
||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||
Open
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<a id="close-modal" href="#">
|
||||
<i class="fa fa-thumbs-up" aria-hidden="true"></i>
|
||||
Close
|
||||
</a>
|
||||
</span>
|
||||
<a id="close-modal" href="#" @click="showModal=false">
|
||||
<i class="fa fa-thumbs-up" aria-hidden="true"></i>
|
||||
Close
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -145,9 +154,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
|
||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<script src="assets/js/site.js"></script>
|
||||
|
||||
<script type="application/javascript">app.featureLevel = {{.FeatureLevel}};</script>
|
||||
|
||||
<script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
|
Reference in New Issue
Block a user