working telegraph manager
This commit is contained in:
commit
7808a71e71
7 changed files with 537 additions and 0 deletions
BIN
g/ic_account.png
Normal file
BIN
g/ic_account.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
g/ic_add.png
Normal file
BIN
g/ic_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 B |
BIN
g/ic_edit.png
Normal file
BIN
g/ic_edit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 222 B |
BIN
g/ic_edit_white.png
Normal file
BIN
g/ic_edit_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
109
index.htm
Normal file
109
index.htm
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Telegraph Manager</title>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||||
|
<meta charset="utf8">
|
||||||
|
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
|
||||||
|
<link rel="icon" type="image/png" href="g/ic_edit.png">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="hero" class="screen">
|
||||||
|
<div class="card blank">
|
||||||
|
<h1>Telegraph Manager</h1>
|
||||||
|
<p>
|
||||||
|
An easy way to manage your articles, profile and views for <a href="http://telegra.ph/">telegra.ph</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screen-nosupport" class="screen">
|
||||||
|
<div class="card">
|
||||||
|
Your browser doesn't support JavaScript and/or HTML5 LocalStorage. Please update your browser and enable JavaScript.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screen-login" class="screen">
|
||||||
|
<div class="card">
|
||||||
|
<h1>create an account</h1>
|
||||||
|
<input type="text" name="author_name" placeholder="your name" required />
|
||||||
|
<input type="text" name="short_name" placeholder="short name (not published)" required />
|
||||||
|
<input type="url" name="author_url" placeholder="your website (optional)" />
|
||||||
|
<button onclick="createAccount()">create account</button>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h1>login with token</h1>
|
||||||
|
<input type="text" name="token" placeholder="your token (like this: b968da509bb768...)" required />
|
||||||
|
<button onclick="tokenLogin()">login</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screen-login-telegraph" class="screen">
|
||||||
|
<div class="card">
|
||||||
|
<p>
|
||||||
|
<a href="#" target="_blank" onclick="doneAuthorized()">click to login to telegra.ph</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You have to do this in order to publish articles. After you've clicked the link, come back to this website.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screen-main" class="screen">
|
||||||
|
<a id="fab" href="http://telegra.ph/" target="_blank" title="new page"><img src="g/ic_add.png" /></a>
|
||||||
|
|
||||||
|
<div id="user-info">
|
||||||
|
|
||||||
|
<div id="user-image-animator" title="edit profile" onclick="edit()">
|
||||||
|
<div id="user-image">
|
||||||
|
<img src="g/ic_account.png" />
|
||||||
|
</div>
|
||||||
|
<div id="user-edit">
|
||||||
|
<img src="g/ic_edit_white.png" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span id="user-name"></span>
|
||||||
|
<span id="user-short"></span>
|
||||||
|
<a id="user-url" href="#" target="_blank"></a>
|
||||||
|
<br>
|
||||||
|
<span>— <span id="user-page-count"></span> —</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="page-list">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screen-edit" class="screen">
|
||||||
|
<div class="card blank">
|
||||||
|
<a onclick="main()" href="#">back</a>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h1>change account information</h1>
|
||||||
|
<input type="text" name="author_name_edit" placeholder="your name" required />
|
||||||
|
<input type="text" name="short_name_edit" placeholder="short name (not published)" required />
|
||||||
|
<input type="url" name="author_url_edit" placeholder="your website (optional)" />
|
||||||
|
<button onclick="saveEdit()">save</button>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h1>logout</h1>
|
||||||
|
<p>
|
||||||
|
<strong>Warning!</strong> To be able log into this account again you <strong> will need</strong> this token:
|
||||||
|
</p>
|
||||||
|
<p id="logout-token"></p>
|
||||||
|
<button onclick="logout()">logout</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
272
main.js
Normal file
272
main.js
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
// Prevent multiple load events when scrolling
|
||||||
|
var canLoadMore = false;
|
||||||
|
|
||||||
|
// Load batches of pages of this size
|
||||||
|
var numberOfPagesToLoad = 10;
|
||||||
|
|
||||||
|
// How many pixels should there be space around the FAB
|
||||||
|
var fabSpace = 30;
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
// Check for localStorage
|
||||||
|
if (typeof(Storage) !== "undefined") {
|
||||||
|
// Storage support present, login
|
||||||
|
login();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window scroll for loading more pages
|
||||||
|
window.onscroll = function(){
|
||||||
|
// Trigger loading of more pages when there are still cards to scroll
|
||||||
|
var triggerElement = $(".card:nth-last-child("+numberOfPagesToLoad+")");
|
||||||
|
|
||||||
|
if(isScrolledIntoView(triggerElement)){
|
||||||
|
if(canLoadMore){
|
||||||
|
canLoadMore = false;
|
||||||
|
loadPages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window resize for positioning FAB
|
||||||
|
window.onresize = resize;
|
||||||
|
resize();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function resize(){
|
||||||
|
var fab = $("#fab");
|
||||||
|
var screenWidth = $(".screen:visible").width();
|
||||||
|
|
||||||
|
var left = ($(window).width() - screenWidth)/2 + screenWidth - fab.width() - fabSpace;
|
||||||
|
|
||||||
|
fab.css("bottom", fabSpace);
|
||||||
|
fab.css("left", left);
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/a/488073/1456971
|
||||||
|
function isScrolledIntoView(elem) {
|
||||||
|
var docViewTop = $(window).scrollTop();
|
||||||
|
var docViewBottom = docViewTop + $(window).height();
|
||||||
|
|
||||||
|
var elemTop = $(elem).offset().top;
|
||||||
|
var elemBottom = elemTop + $(elem).height();
|
||||||
|
|
||||||
|
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
|
||||||
|
}
|
||||||
|
|
||||||
|
function showScreen(name){
|
||||||
|
// Hide all other screens
|
||||||
|
$("[id^=screen-]").hide();
|
||||||
|
// Show desired screen
|
||||||
|
$("#screen-"+name).show();
|
||||||
|
|
||||||
|
// Show/hide hero for certain screen names
|
||||||
|
var heroVisible = name == "login" || name == "nosupport";
|
||||||
|
if(heroVisible){
|
||||||
|
$("#hero").show();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$("#hero").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for existing access token and login or show login screen
|
||||||
|
function login(){
|
||||||
|
if(localStorage.token){
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// Show login screen
|
||||||
|
showScreen("login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAccount(){
|
||||||
|
// Attributes
|
||||||
|
var author_name = $("input[name='author_name']").val();
|
||||||
|
var short_name = $("input[name='short_name']").val();
|
||||||
|
var author_url = $("input[name='author_url']").val();
|
||||||
|
|
||||||
|
// Request token
|
||||||
|
$.getJSON("https://api.telegra.ph/createAccount", {
|
||||||
|
"author_name": author_name,
|
||||||
|
"short_name": short_name,
|
||||||
|
"author_url": author_url
|
||||||
|
}, function(data){
|
||||||
|
|
||||||
|
// Check for valid data
|
||||||
|
if(!data.ok){
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store token
|
||||||
|
localStorage.token = data.result.access_token;
|
||||||
|
|
||||||
|
// handle login link
|
||||||
|
$("#screen-login-telegraph a").attr("href", data.result.auth_url);
|
||||||
|
showScreen("login-telegraph");
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login with provided token, this requires generating a new one
|
||||||
|
function tokenLogin(){
|
||||||
|
var token = $("input[name='token']").val();
|
||||||
|
|
||||||
|
$.getJSON("https://api.telegra.ph/revokeAccessToken", {
|
||||||
|
"access_token": token
|
||||||
|
}, function(data){
|
||||||
|
|
||||||
|
// Check for valid data
|
||||||
|
if(!data.ok){
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store new token
|
||||||
|
localStorage.token = data.result.access_token;
|
||||||
|
|
||||||
|
// handle login link
|
||||||
|
$("#screen-login-telegraph a").attr("href", data.result.auth_url);
|
||||||
|
showScreen("login-telegraph");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// User has clicked the telegraph authorization link
|
||||||
|
function doneAuthorized(){
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows the main screen
|
||||||
|
function main(){
|
||||||
|
showScreen("main");
|
||||||
|
|
||||||
|
// Load user info
|
||||||
|
$.getJSON("https://api.telegra.ph/getAccountInfo", {
|
||||||
|
"access_token": localStorage.token
|
||||||
|
}, function(data){
|
||||||
|
|
||||||
|
// Show login screen for errors
|
||||||
|
if(!data.ok){
|
||||||
|
showScreen("login");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Username might be empty
|
||||||
|
var username = data.result.author_name;
|
||||||
|
if(username == "") username = "<unkown>";
|
||||||
|
|
||||||
|
$("#user-name").text(username);
|
||||||
|
$("#user-short").text(data.result.short_name);
|
||||||
|
|
||||||
|
// Hide user url if it is not provided
|
||||||
|
$("#user-url").toggle(data.result.author_url != "");
|
||||||
|
$("#user-url").text(data.result.author_url);
|
||||||
|
$("#user-url").attr("href", data.result.author_url);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear old pages
|
||||||
|
$("#page-list").empty();
|
||||||
|
|
||||||
|
// Load pages
|
||||||
|
loadPages();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads more pages
|
||||||
|
function loadPages(){
|
||||||
|
|
||||||
|
var pageList = $("#page-list");
|
||||||
|
|
||||||
|
$.getJSON("https://api.telegra.ph/getPageList", {
|
||||||
|
"access_token": localStorage.token,
|
||||||
|
"offset" : pageList.children().length,
|
||||||
|
"limit" : numberOfPagesToLoad
|
||||||
|
}, function(data){
|
||||||
|
|
||||||
|
// Set page text
|
||||||
|
var s = data.result.total_count == 1 ? "" : "s";
|
||||||
|
$("#user-page-count").text(data.result.total_count + " page" + s);
|
||||||
|
|
||||||
|
// Check for valid data
|
||||||
|
if(!data.ok){
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append new pages
|
||||||
|
$.each(data.result.pages, function(){
|
||||||
|
|
||||||
|
// Should the text read 'view' or 'views'
|
||||||
|
var s = this.views == 1 ? "" : "s";
|
||||||
|
|
||||||
|
pageList.append("<a class='card' href='"+this.url+"' target='_blank'><h1>"+this.title+"</h1><p>"+this.views+" view"+s+"</p><p>"+this.description+"</p></a>");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// If we got many pages, we can load more
|
||||||
|
if(data.result.pages.length == numberOfPagesToLoad){
|
||||||
|
// We can now receive another load event
|
||||||
|
canLoadMore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show edit screen for user profile
|
||||||
|
function edit(){
|
||||||
|
|
||||||
|
// Populate edit fields
|
||||||
|
$("#logout-token").text(localStorage.token);
|
||||||
|
|
||||||
|
$.getJSON("https://api.telegra.ph/getAccountInfo", {
|
||||||
|
"access_token": localStorage.token
|
||||||
|
}, function(data){
|
||||||
|
|
||||||
|
// Check for valid data
|
||||||
|
if(!data.ok){
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("input[name='author_name_edit']").val(data.result.author_name);
|
||||||
|
$("input[name='short_name_edit']").val(data.result.short_name);
|
||||||
|
$("input[name='author_url_edit']").val(data.result.author_url);
|
||||||
|
|
||||||
|
showScreen("edit");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save edited profile
|
||||||
|
function saveEdit(){
|
||||||
|
|
||||||
|
$.getJSON("https://api.telegra.ph/editAccountInfo", {
|
||||||
|
"access_token": localStorage.token,
|
||||||
|
"author_name": $("input[name='author_name_edit']").val(),
|
||||||
|
"short_name": $("input[name='short_name_edit']").val(),
|
||||||
|
"author_url": $("input[name='author_url_edit']").val(),
|
||||||
|
}, function(data){
|
||||||
|
|
||||||
|
// Check for valid data
|
||||||
|
if(!data.ok){
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// logout
|
||||||
|
function logout(){
|
||||||
|
localStorage.removeItem("token");
|
||||||
|
window.location.reload(true);
|
||||||
|
}
|
156
style.css
Normal file
156
style.css
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:visited{
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
p{
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initially hide all screens, except for screen-nosupport */
|
||||||
|
#screen-login, #screen-login-telegraph, #screen-main, #screen-edit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card{
|
||||||
|
display: block;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0px 2px 4px #777;
|
||||||
|
padding: 1em;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
a.card{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.screen{
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 1em auto;
|
||||||
|
}
|
||||||
|
.card.blank{
|
||||||
|
background: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main Screen */
|
||||||
|
|
||||||
|
#user-info{
|
||||||
|
text-align: center;
|
||||||
|
margin: 3em;
|
||||||
|
}
|
||||||
|
#user-info > *{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user-name{
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user-short{
|
||||||
|
color: #555;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
#user-short:before{
|
||||||
|
content: "(";
|
||||||
|
}
|
||||||
|
#user-short:after{
|
||||||
|
content: ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-list a{
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: 300ms;
|
||||||
|
}
|
||||||
|
#page-list a:hover{
|
||||||
|
box-shadow: 0px 4px 8px #777;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
#page-list h1{
|
||||||
|
margin-bottom: 0.4em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
#page-list p{
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fab{
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
background-color: #000;
|
||||||
|
border-radius: 48px;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
box-shadow: 0 4px 8px #777;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 200ms;
|
||||||
|
}
|
||||||
|
#fab:hover{
|
||||||
|
box-shadow: 0 8px 16px #777;
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animating picture from silhouette to pencil */
|
||||||
|
#user-image-animator{
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 48px;
|
||||||
|
box-shadow: 0 2px 4px #777;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 200ms;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
#user-edit{
|
||||||
|
position: absolute;
|
||||||
|
height: 0;
|
||||||
|
overflow: visible;
|
||||||
|
transform: translateY(-52px);
|
||||||
|
opacity: 0;
|
||||||
|
transition: 200ms;
|
||||||
|
}
|
||||||
|
#user-image{
|
||||||
|
transition: 200ms;
|
||||||
|
}
|
||||||
|
#user-image-animator:hover{
|
||||||
|
box-shadow: 0px 4px 8px #777;
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
#user-image-animator:hover #user-edit{
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
#user-image-animator:hover #user-image{
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login screen */
|
||||||
|
input, button{
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
margin-left: 25%;
|
||||||
|
margin-top: 1em;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
button{
|
||||||
|
width: calc(50% + 0.6em);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Edit account screen */
|
||||||
|
#logout-token{
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue