1
0
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:
Maksym Pavlenko
2017-10-23 16:13:16 -07:00
parent 8736340a40
commit e90553f66c
3 changed files with 156 additions and 208 deletions

View File

@@ -1,5 +1,9 @@
@import url('https://fonts.googleapis.com/css?family=Ubuntu');
[v-cloak] {
display: none;
}
body {
margin: 0;
padding: 0;

View File

@@ -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();
}
});

View File

@@ -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;