Friday, 1 June 2012

Creating "Homework" Google Sites

Tom Stoneham came to us with an interesting problem... "Can I automatically create 80 or so HomeWork Google Sites from a template for students? And when the deadline has been reached can their access be revoked and links sent out to examiners". The students' task will be create a site about a particular philosopher. The prototype looks like this...



I'd had a stab at solving this earlier to see it was possible, and maybe too quickly I jumped for python. But in the spirit of making something that a. worked, b. was sharable, c. I wouldn't have to maintain ( hopefully ), I thought I'd have a go a re-doing it in AppScript.

Having met with Tom, there were a few addition requirements:

  • Can student sites have unique IDs that are mapped on to a marking sheet?
  • Can the URLs be kept in a list because, if you have 80 students then 8 markers may be given 10 students each?
  • What is the best way for the University of keep the snapshot but still give the student the ability to take their work with them? The student may even continue working on it.
  • Can an Editor of a site (i.e not the Owner) make a copy of a Site?
  • Just as an afterthought, can there be guidance about Copyright etc?
So, my early experiments were this.

1. Create the Spreadsheet



The siteurl column would be used to store the site created's URL for use later.


2. Create A Menu To Do Stuff

In the Script Editor I added:



function onOpen() {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var menuEntries = [ {name: "Create Sites...", functionName: "create_sites"},
                      {name: "Add Students To Sites", functionName: "add_students_to_sites"},
                      {name: "Email Examiners", functionName: "notify_examiners"} ];
  ss.addMenu("Administration", menuEntries);
}



After a while, I hit this wall...,  when creating a site, because it can take an elastic amount of time, but the code continues. That means if you try to create a site, then set up who the users are, the site might not be there yet. My workaround was to create separate functions... so the process, and indeed the Menu Items are...


  1. Create all the Google Sites based on the spreadsheet data, copying the chosen template site
  2. Add the students as Editors to the the sites 
  3. When the deadline is reached, remove the students as Editors ( making them Viewers ) and also make the Examiners Viewers ( sending them emails with the sites they have to mark in with each students unique ID.

So...



function create_a_site( template_site_name, student_unique_id ){
  var domain = "york.ac.uk" ;
  var template_site = SitesApp.getSite(domain, template_site_name );
  var name = "" + template_site.getName() + "-" + student_unique_id .toLowerCase() ;

  var title = name ;
  var summary = "Deadline 21st, December 2012" ;
  // See the warning in https://developers.google.com/apps-script/class_sitesapp about site creation speed
  var site = SitesApp.copySite(domain, name, title, summary, template_site);
  var sites_url = site.getUrl();
  return sites_url ;
}

function create_sites(){

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("students");
 
  var result = Browser.inputBox("Which Site is the template Site?", "project-template", Browser.Buttons.OK_CANCEL );
  if (result == "cancel"){
    //Browser.msgBox("CANCEL: " + result)
        }
   else{
     
     var range = ss.getDataRange().getValues();
     var students = rangeToObjects(range);
     var template_site_name = result
     
     try{
           
           for(var i = 0; i < students.length; i++){
             var student = students[i];          
             var site_name = template_site_name +"-" + student.uniquereference.toLowerCase();
             var domain = "york.ac.uk" ;
           
             var sites_url = create_a_site(template_site_name, student.uniquereference.toLowerCase() ); //Alter the values
             students[i].sites_url = sites_url;

             var x = i+2
             var cellnum = x.toString().replace("0", "");
             
             //Browser.msgBox(x);
             Logger.log( cellnum );

             var values = new Array();
             values[0] = sites_url
             var cellname = "D" + cellnum;
             var range = sheet.getRange( cellname )
             
             range.setValue( sites_url );
             
     }      
         
     }catch(e){
     Logger.log( e.message );
   }
     // Now write the URLs back to the spreadsheet. Or not.
     
   }
}

function add_students_to_sites(){
  //Browser.msgBox("Add Students To Sites!")
 
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("students");
  var range = ss.getDataRange().getValues();
  var students = rangeToObjects(range);
 
  for(var i = 0; i < students.length; i++){
    student = students[i];
    var url = student.siteurl;
    var email = student.email;
    var examiner = student.examiner;
    var site = SitesApp.getSiteByUrl(url);
    site.addEditor(email);
    site.addViewer(examiner);

   
  }
  Browser.msgBox("Added students to sites")
}





function test_create_a_site(){
 var x = create_a_site("project-template",  "Y63326039"  );
 Logger.log( "Done! " + x );
 //Browser.msgBox(x)
}

function add_people( site_name, student_email, examiner_email ) {
  var domain = "york.ac.uk" ;
  var site = SitesApp.getSite(domain, site_name );
  site.addEditor( student_email ).addViewer(examiner_email);
  the_url = site.getUrl();
 
  //email a link to the student
  /*MailApp.sendEmail(student_email,
                    "Your Philosophy Homework Site",
                    "A Google Site has been created for you to fill in. \n\n " +
                     the_url + "\n\n",                  
                    {name:"Philosophy Course"});*/
 

  Logger.log("Done!");
 
}

function notify_examiners ( ){
  // email a link to the examiner
  // https://developers.google.com/apps-script/class_mailapp
 
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("students");
  var range = ss.getDataRange().getValues();
  var students = rangeToObjects(range);
 
  for(var i = 0; i < students.length; i++){
    student = students[i];
    var url = student.siteurl;
    var email = student.email;
    var examiner = student.examiner;
    var site = SitesApp.getSiteByUrl(url);
   
    MailApp.sendEmail(examiner,
                      "TEST: A Philosophy Homework Site To Mark",
                      "A Google Site has been created for you to mark. \n\n " +
                     url + "\n\n",                    
                    {name:"Philosophy Course"});
    //At this point we might want to record that the mail has been sent...
     
  }
 
  Browser.msgBox("Done!");
}
 

Conclusions

There are still a few bugs to iron out. It really doesn't like creating a site if a site already exists with that name, and I've found that deleteSite() never runs smoothly.

The next step is maybe to add some UI to select which site you want to use as a template. And of course to start making it a bit more robust. Ahem.

I'm actually quite surprised that this was easier to achieve in AppScript than it was in Python... probably...






No comments:

Post a Comment