Skip to content

Instantly share code, notes, and snippets.

@rheajt
Created October 26, 2016 18:31
Show Gist options
  • Select an option

  • Save rheajt/e3d801f263aa062d073b1feca9b44ecb to your computer and use it in GitHub Desktop.

Select an option

Save rheajt/e3d801f263aa062d073b1feca9b44ecb to your computer and use it in GitHub Desktop.
WeCreate

WeCreate Picture Citation Project for Joanne Schmutz

Idea by Joanne Schmutz

Coded by @rheajt

  1. Create a folder for the root of your project
  2. Create a script file and copy each of the below files into the project
  3. Create a spreadsheet in that directory and in the header row name each column as follows: uploadedOn user userFolder fileId embedUrl fileUrl type category title description tags allowAdaptations allowCommercial
  4. Create a folder that will house all of your users folders and their pictures
  5. Find the IDs of the spreadsheet and the folder
  6. Replace the global variables with the correct ID values
  7. Deploy the script as a Webapp and make sure you approve the requested permissions
  8. Test it out!

STILL TO COME:

Tags! Tag your photos and sort the gallery with those tags.

/**
# WeCreate Picture Citation Project for Joanne Schmutz
### Idea by Joanne Schmutz
### Coded by [@rheajt](http://jordanrhea.com)
1. Create a folder for the root of your project
2. Create a script file and copy each of the below files into the project
3. Create a spreadsheet in that directory and in the header row name each column as follows:
* uploadedOn
* user
* userFolder
* fileId
* embedUrl
* fileUrl type
* category
* title
* description tags
* allowAdaptations
* allowCommercial
4. Create a folder that will house all of your users folders and their pictures
5. Find the IDs of the spreadsheet and the folder
6. Replace the global variables with the correct ID values
7. Deploy the script as a Webapp and make sure you approve the requested permissions
8. Test it out!
### STILL TO COME:
Tags! Tag your photos and sort the gallery with those tags.
*/
var SPREADSHEET_ID = '',
FOLDER_ID = '';
function doGet() {
return HtmlService.createTemplateFromFile('WeCreate').evaluate().setTitle('WeCreate');
}
function getPictures() {
var pictureSheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('Pictures');
var data = _getObject(pictureSheet.getDataRange().getValues());
return JSON.stringify(data);
}
function _getObject(rows) {
// shift the first row from the data as the header row
var headers = rows.shift();
// create an empty array to hold the objects you create
return rows.map(function(pic) {
var picture = {};
for(var i = 0; i < pic.length; i++) {
picture[headers[i]] = pic[i];
}
return picture;
});
}
function postPicture(pic) {
var pictureSheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('Pictures');
var pictureFolder = DriveApp.getFolderById(FOLDER_ID);
var user = Session.getActiveUser();
var userFolder = (pictureFolder.getFoldersByName(user).hasNext()) ? pictureFolder.getFoldersByName(user).next() : pictureFolder.createFolder(user);
//create the picture in the user folder
try {
var contentType = pic.file.data.substring(5,pic.file.data.indexOf(';')),
bytes = Utilities.base64Decode(pic.file.data.substr(pic.file.data.indexOf('base64,')+7)),
blob = Utilities.newBlob(bytes, contentType, pic.file.name);
var pictureFile = userFolder.createFile(blob);
var appendData = [
new Date().toDateString(),
user,
userFolder.getUrl(),
pictureFile.getId(),
'https://drive.google.com/uc?export=view&id=' + pictureFile.getId(),
pictureFile.getUrl(),
pic.type || '',
pic.category || '',
pic.title || '',
pic.description || '',
pic.tags || '',
pic.allowAdaptations || '',
pic.allowCommercial || ''
];
//enter a new row in the spreadsheet
pictureSheet.appendRow(appendData);
var headers = pictureSheet.getDataRange().getValues().shift();
return {value: _getObject([headers, appendData])};
} catch (err) {
return err.toString();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.2.0/ui-bootstrap-tpls.min.js"></script>
<script>
angular.module('youcreate', ['ui.bootstrap'])
.factory('GallerySvc', ['$q', function($q) {
var Gallery = {};
Gallery.pictures = [];
Gallery.getPictures = function() {
var deferred = $q.defer();
google.script.run
.withSuccessHandler(function(response) {
Gallery.pictures = JSON.parse(response);
deferred.resolve(Gallery.pictures);
})
.withFailureHandler(function(err) {
deferred.reject(err);
})
.getPictures();
return deferred.promise;
}
Gallery.postPicture = function(pic) {
var deferred = $q.defer();
google.script.run
.withSuccessHandler(function(response) {
Gallery.pictures.push(response.value[0]);
deferred.resolve(response);
})
.withFailureHandler(function(err) {
deferred.reject(err);
})
.postPicture(pic);
return deferred.promise;
}
return Gallery;
}])
.factory('FileReader', ['$q', function($q) {
var onLoad = function(reader, deferred, scope) {
return function () {
scope.$apply(function () {
deferred.resolve(reader.result);
});
};
};
var onError = function (reader, deferred, scope) {
return function () {
scope.$apply(function () {
deferred.reject(reader.result);
});
};
};
var onProgress = function(reader, scope) {
return function (event) {
scope.$broadcast("fileProgress",
{
total: event.total,
loaded: event.loaded
});
};
};
var getReader = function(deferred, scope) {
var reader = new FileReader();
reader.onload = onLoad(reader, deferred, scope);
reader.onerror = onError(reader, deferred, scope);
reader.onprogress = onProgress(reader, scope);
return reader;
};
var readAsDataURL = function (file, scope) {
var deferred = $q.defer();
var reader = getReader(deferred, scope);
reader.readAsDataURL(file);
return deferred.promise;
};
return {
readAsDataUrl: readAsDataURL
};
}])
.directive('allowAdaptations', [function() {
return {
restrict: 'E',
scope: {sort: '='},
replace: true,
template: '<select ng-model="sort.allowAdaptations"> \
<option value="">ALLOW ADAPTATIONS?</option>\
<option value="true">Yes</option>\
<option value="false">No</option>\
</select>'
}
}])
.directive('allowCommercial', [function() {
return {
restrict: 'E',
scope: {sort: '='},
replace: true,
template: '<select ng-model="sort.allowCommercial">\
<option value="">ALLOW COMMERCIAL USE?</options>\
<option value="true">Yes</option>\
<option value="false">No</option>\
</select>'
}
}])
.directive('type', [function() {
return {
restrict: 'E',
scope: {sort: '='},
replace: true,
template: '<select ng-model="sort.type">\
<option value="">TYPE?</option>\
<option value="photograph">Photograph</option>\
<option value="artwork">Artwork</option>\
<option value="animation">Animation</option>\
</select>'
}
}])
.directive('category', [function() {
return {
restrict: 'E',
scope: {sort: '='},
replace: true,
template: '<select ng-model="sort.category">\
<option value="">CATEGORY?</option>\
<option value="abstract">Abstract</option>\
<option value="animals">Animals</option>\
<option value="art">Art</option>\
<option value="architecture">Architecture</option>\
<option value="illustrations">Illustrations</option>\
<option value="nature">Nature</option>\
<option value="objects">Objects</option>\
<option value="people">People</option>\
<option value="technology">Technology</option>\
<option value="travel">Travel</option>\
</select>'
}
}])
.directive('ngFileSelect', [function(){
return {
link: function($scope,el){
el.bind("change", function(e){
$scope.file = (e.srcElement || e.target).files[0];
$scope.getFile();
})
}
}
}])
//.controller('HeaderCtrl', ['$scope', '$uibModal', 'GallerySvc', 'SortSvc', function($scope, $uibModal, GallerySvc, SortSvc) {
//
// $scope.sort = SortSvc;
//
// $scope.openUpload = function() {
// var modal = $uibModal.open({
// animation: true,
// ariaLabelledBy: 'modal-title',
// ariaDescribedBy: 'modal-body',
// templateUrl: 'uploadModal.html',
// controller: 'UploadCtrl',
// size: 'lg'
// });
//
// }
//
//}])
.controller('GalleryCtrl', ['$scope', '$uibModal', 'GallerySvc', function($scope, $uibModal, GallerySvc) {
GallerySvc.getPictures().then(function(response) {
$scope.pictures = response;
});
$scope.$watch('pictures', function(update) {
$scope.pictures = update;
});
$scope.openShare = function(pic) {
$uibModal.open({
animation: true,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'shareModal.html',
controller: 'ShareCtrl',
size: 'lg',
resolve: {
picture: function() {
return pic;
}
}
});
}
$scope.openUpload = function() {
var modal = $uibModal.open({
animation: true,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'uploadModal.html',
controller: 'UploadCtrl',
size: 'lg'
});
}
}])
.controller('ShareCtrl', ['$scope', '$uibModalInstance', 'picture', function($scope, $uibModalInstance, picture) {
$scope.pic = picture;
$scope.ok = function() {
$uibModalInstance.close();
}
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
}
}])
.controller('UploadCtrl', ['$scope', '$uibModalInstance', 'GallerySvc', 'FileReader', function($scope, $uibModalInstance, GallerySvc, FileReader) {
$scope.upload = {
file: {
complete: false
}
};
$scope.getFile = function () {
FileReader.readAsDataUrl($scope.file, $scope)
.then(function(result) {
$scope.preview = result;
$scope.upload.file.name = $scope.file.name;
$scope.upload.file.data = result;
$scope.upload.file.complete = true;
});
};
$scope.submit = function() {
if($scope.upload.file.complete) {
GallerySvc.postPicture($scope.upload).then(function(response) {
$uibModalInstance.close(response);
});
}
}
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
}
}])
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<style>
.thumbnail img {
height: 150px;
}
</style>
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= HtmlService.createHtmlOutputFromFile('Stylesheet').getContent() ?>
</head>
<body class="container" ng-app="youcreate">
<div ng-controller="GalleryCtrl">
<section class="row">
<div class="col-sm-12">
<h2>WeCreate</h2>
</div>
<div class="col-sm-5">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search by title" ng-model="sort.title" />
</div>
</div>
<div class="col-sm-offset-2 col-sm-5">
<div class="form-group">
<button type="click" class="btn btn-primary form-control" ng-click="openUpload()">Upload File</button>
</div>
</div>
<div class="col-sm-3">
<allow-adaptations sort="sort" class="form-control"></allow-adaptations>
</div>
<div class="col-sm-3">
<allow-commercial sort="sort" class="form-control"></allow-commercial>
</div>
<div class="col-sm-3">
<type sort="sort" class="form-control"></type>
</div>
<div class="col-sm-3">
<category sort="sort" class="form-control"></category>
</div>
</section>
<hr>
<section class="row">
<div class="col-sm-3" ng-repeat="picture in pictures | filter:sort" ng-click="openShare(picture)">
<div class="thumbnail">
<img ng-src="{{ picture.embedUrl }}" class="img-responsive" />
</div>
</div>
</section>
</div>
<script type="text/ng-template" id="shareModal.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Respect the work of others!</h3>
</div>
<div class="modal-body" id="modal-body">
<div class="row">
<div class="col-sm-6">
<img ng-src="{{ pic.embedUrl }}" class="img-responsive" />
</div>
<div class="col-sm-6">
<h3>Citation</h3>
<pre><code>{{ pic | json }}</code></pre>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
<script type="text/ng-template" id="uploadModal.html">
<div class="modal-header">
<h3 class="modal-title">Upload</h3>
</div>
<div class="modal-body">
<div class="row" style="height:200px;max-height:200px;">
<div class="col-sm-6">
<label>UPLOAD</label>
<input type="file" accept="image/*" class="form-control" ng-model="upload.file" ng-file-select="onFileSelect($files)" />
</div>
<div class="col-sm-6">
<img class="img-responsive" ng-src="{{ preview }}" />
</div>
</div>
<div class="row">
<div class="col-sm-6">
<label for="title">Title</label>
<input type="text" class="form-control" ng-model="upload.title" required>
</div>
<div class="col-sm-3">
<label for="type">Type</label>
<type sort="upload" class="form-control"></type>
</div>
<div class="col-sm-3">
<label for="category" class="col-sm-2">Category</label>
<category sort="upload" class="form-control"></category>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<label for="description">Description (optional)</label>
<input type="text" class="form-control" ng-model="upload.description">
</div>
<div class="col-sm-6">
<label for="tags">Tags (optional)</label>
<input type="text" class="form-control" ng-model="upload.tags" />
</div>
</div>
<h3><b>Choose your license:</b></h3>
<h5>Attribution - Allow adaptations of your work to be shared?</h5>
<label class="radio-inline">
<input type="radio" ng-model="upload.allowAdaptations" value="true"> Yes
</label>
<label class="radio-inline">
<input type="radio" ng-model="upload.allowAdaptations" value="false"> No
</label>
<label class="radio-inline">
<input type="radio" ng-model="upload.allowAdaptations" value="maybe"> Yes, as long as others share alike
</label>
<h5>Allow commercial use of your work?</h5>
<label class="radio-inline">
<input type="radio" ng-model="upload.allowCommercial" value="true"> Yes
</label>
<label class="radio-inline">
<input type="radio" ng-model="upload.allowCommercial" value="false"> No
</label>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="submit" ng-click="submit()">Submit</button>
<button class="btn btn-default" type="click" ng-click="cancel()">Cancel</button>
</div>
</script>
<?!= HtmlService.createHtmlOutputFromFile('Javascript').getContent() ?>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment