Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
track library reading with custom projects

Reading Logs

function doGet() {
return HtmlService.createTemplateFromFile('ReadingLog').evaluate().setTitle('Reading Log');
}
function getUser() {
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
var activeUser = Session.getActiveUser().getEmail();
var studentInfo = ss.getSheetByName(STUDENT_INFO).getDataRange().getValues();
var readingLogs = ss.getSheetByName('READING LOG').getDataRange().getValues();
var userData = {};
for(var i = 0; i < studentInfo.length; i++) {
if(activeUser == studentInfo[i][2]) {
userData.avatar = studentInfo[i][3];
userData.studentName = studentInfo[i][1];
userData.books = [];
for(var j = 0; j < readingLogs.length; j++) {
if(activeUser == readingLogs[j][0]) {
userData.books.push({title: readingLogs[j][1], author: readingLogs[j][2], file: readingLogs[j][3], started: readingLogs[j][4], completed: readingLogs[j][5]});
}
}
}
}
return userData;
}
function newUser() {
var user = Session.getActiveUser().getEmail();
var folder = DriveApp.getFolderById(REPORTS_FOLDER).createFolder(user);
folder.addEditor(Session.getActiveUser());
SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(STUDENT_INFO).appendRow([0, user.toString().split('@')[0], user, 'https://pstatic.classdojo.com/img2/monsters/128/cute5.png', folder.getUrl()]);
}
function searchBooks(search) {
var payload = {
"q": search,
"key": GOODREADS_API
};
var params = {
"method": "GET",
"payload": payload
};
var response = UrlFetchApp.fetch('https://www.goodreads.com/search/index.xml', params).getContentText();
var xml = XmlService.parse(response);
var works = xml.getRootElement().getChildren('search')[0].getChild('results').getChildren();
var bookResponse = [];
for(var i = 0; i < works.length; i++) {
var books = works[i].getChildren('best_book');
for(var j = 0; j < books.length; j++) {
var title = books[j].getChild('title').getText(),
author = books[j].getChild('author').getChild('name').getText(),
imageURL = books[j].getChild('image_url').getText();
bookResponse.push([title, author, imageURL]);
}
}
return bookResponse;
}
function getTemplate(fileName) {
var templateFiles = DriveApp.getFolderById(TEMPLATES_FOLDER).getFilesByType(MimeType.GOOGLE_DOCS);
var templates = [];
while(templateFiles.hasNext()) {
templates.push(templateFiles.next());
}
var rand = Math.floor((Math.random() * templates.length) + 1);
var template = templates[rand];
return template.makeCopy(DriveApp.getFolderById(REPORTS_FOLDER).getFoldersByName(Session.getActiveUser()).next()).setName(fileName);
}
function startReport(book) {
try {
var user = Session.getActiveUser();
var file = getTemplate(user + ' - ' + book.title);
//add to spreadsheet
var row = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('READING LOG').appendRow([
Session.getActiveUser(),
book.title,
book.author,
file.getUrl(),
'FALSE',
'FALSE'
]);
return 'DONE';
} catch(err) {
return err;
}
}
//id of the spreadsheet where you will keep the logs of all the students
var SPREADSHEET_ID = '';
//name of the sheet where you keep your student information in the spreadsheet
var STUDENT_INFO = '';
//the api key from goodreads.com so that you can search book titles
var GOODREADS_API = '';
//id of the folder where you will save the student reports
var REPORTS_FOLDER = '';
//id of the folder where you keep the templates for the book reports
var TEMPLATES_FOLDER = '';
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
function getUser() {
google.script.run
.withSuccessHandler(showUser)
.withFailureHandler(showError)
.getUser();
}
function search(e) {
e.preventDefault();
$('#results').append('<h3>Loading...</h3><progress></progress>');
google.script.run
.withSuccessHandler(searchResults)
.withFailureHandler(showError)
.searchBooks($('#book-search').val());
}
function searchResults(response) {
var html = response.map(function(book) {
var img = $('<img>').attr('src', book[2]).data('info', {title: book[0], author: book[1], src: book[2]});
return img;
});
$('#results').empty().append(html);
}
function showUser(response) {
if(response.studentName) {
$('.avatar img').attr('src', response.avatar);
$('.user h3').text(response.studentName);
var userLevel = (response.books.length / 10) * 100;
$('.user progress').val(userLevel);
var books = response.books.map(function(book) {
return '<tr>\
<td><a href="' + book.file + '" target="_blank">' + book.title + '</a></td>\
<td>' + book.author + '</td>\
</tr>';
});
$('.reading-log table tbody').empty().append(books);
loadingToggle('.container', '.loading');
} else {
loadingToggle('.register', '.loading');
}
}
function selectBook(e) {
$('.selected').removeClass();
$(e.target).addClass('selected');
}
function startReport() {
loadingToggle('.loading', '.container');
console.log($('.selected').data().info);
google.script.run
.withSuccessHandler(getUser)
.withFailureHandler(showError)
.startReport($('.selected').data().info);
}
function showError(error) {
console.log(error);
}
function newBook() {
$('.reading-log').slideUp(function() {
$('.search-details').slideDown();
});
}
function showLog() {
$('.search-details').slideUp(function() {
$('.reading-log').slideDown();
});
}
function loadingToggle(coming, going) {
$(going).hide(function() {
$(coming).show();
});
showLog();
}
$('#new-book').click(newBook);
$('#show-log').click(showLog);
$('#search').submit(search);
$('#results').on('click', 'img', selectBook);
$('#start-report').click(startReport);
$(document).ready(getUser);
</script>
<?!= HtmlService.createHtmlOutputFromFile('Stylesheet').getContent() ?>
<div class="loading">
<h1>Loading info for <?!= Session.getActiveUser().getEmail() ?>...</h1>
<progress></progress>
</div>
<div class="register">
Not registered
</div>
<div class="container">
<div class="user-details">
<div class="avatar">
<img src="http://placehold.it/150x150">
</div>
<div class="user">
<h3>Username</h3>
<h5>Current Level</h5>
<progress max="100" value="45"></progress>
</div>
</div> <!-- end of the user-details div -->
<div class="reading-log">
<table>
<caption>Reading Log</caption>
<thead>
<tr>
<th>Title</th>
<th>Author</th>
</tr>
</thead>
<tfoot>
<tr>
<td>
<button id="new-book">Add a new book</button>
</td>
</tr>
</tfoot>
<tbody></tbody>
</table>
</div>
<div class="search-details">
<form id="search">
<input type="text" id="book-search">
<button type="submit">Search</button>
</form>
<div id="results"></div>
<button type="button" id="start-report">Start Project</button>
<button type="button" id="show-log">Back to log</button>
</div>
</div>
<?!= HtmlService.createHtmlOutputFromFile('Javascript').getContent() ?>
<style>
@import url("https://fonts.googleapis.com/css?family=Raleway");
* {
box-sizing: border-box;
font-family: "Raleway", sans-serif;
}
body {
background: linear-gradient(to right, darkgreen, lightgreen);
}
.container {
width: 90%;
margin: 0 auto;
display: none;
}
.user-details, .reading-log, .search-details {
height: 100%;
background: rgba(255, 255, 255, 0.95);
float: left;
padding: 5px;
border-radius: 3px;
margin: 3px;
box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.37);
}
.user-details, .search-details {
text-align: center;
}
.user-details img, .reading-log img {
width: 100%;
max-width: 150px;
}
.user-details progress {
width: 100%;
}
.user-details {
width: 25%;
}
.reading-log, .search-details {
width: 73%;
}
.search-details, .register {
display:none;
}
.reading-log table {
width: 100%;
}
.reading-log table caption {
font-size: 1.4em;
text-align: left;
}
#results img {
margin: 5px;
transition: all .2s;
}
#results img:hover {
transform: scale(1.1);
}
#results img.selected {
border: 3px solid blue;
}
.loading, .register {
text-align: center;
color: white;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment