zeppelin angular-tricks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%angular | |
<input id="textbox" class="hide" ng-model="someAngularVar"></input> | |
<button id="btn" type="submit" onclick="update()">UpperCase It!</button> | |
<script type="text/javascript"> | |
function update(){ | |
var element = $('#textbox'); | |
var currentVal = element.val(); | |
//Update the value | |
element.val(currentVal.toUpperCase()); | |
//Give Angular a few ms to mark 'textbox' as dirty & get ready to catch change event | |
window.setTimeout(function(){ | |
//Triggers Angular to do its thing with changed model values | |
element.trigger('input'); | |
}, 500); | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%sh | |
# It's a good idea to wrap and parameterize download steps | |
# You never know how many times users will "Run All" a notebook, constantly re-downloading files | |
URL=ftp://ita.ee.lbl.gov/traces/NASA_access_log_Jul95.gz | |
TARGET=logs.gz | |
if [ ! -f $TARGET ]; then | |
echo "Downloading logs.." | |
wget -nv $URL -O $TARGET | |
fi | |
echo "Logs saved to $TARGET.." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%angular | |
<!-- To avoid editing JS, I put the downstream paragraph IDs in a comma separated attribute "refresh" --> | |
<div id="chart" data="data" yAxes="Requests" title="Web Activity" | |
refresh="20160914-221415_1942638313,20160914-225103_297917127,20160914-221501_1892040487,20160912-040402_885019782"></div> | |
<input id="bounds" type="text" class="hide" ng-model="bounds"></input> | |
<center> | |
<h5 id="t1">Left Bound: </h5><h5 id="t2">Right Bound: </h5> | |
<button id="btnRefresh" type="submit" class="btn btn-primary" ng-click="">Run Queries</button> | |
</center> | |
<script type="text/javascript"> | |
var div = $('#chart'); | |
var bounds = $('#bounds'); | |
//Get list of paragraphs to refresh on button click | |
$.each(div.attr('refresh').split(','), function(i, v){ | |
$('#btnRefresh').attr('ng-click', $('#btnRefresh').attr('ng-click') + "z.runParagraph('"+v+"');"); | |
}); | |
var data = window.angularVars[div.attr('data')]; | |
var schema = window.angularVars[div.attr('data')+'Schema']; | |
//Convert query results into Plotly traces: https://plot.ly/javascript/multiple-axes/#multiple-yaxes | |
var traces = []; | |
$.each(schema.fields.slice(1), function(i, field){ //Setup trace metadata | |
var trace = {x: [], y: [], name: field.name, type: 'scatter', yaxis: 'y'}; | |
traces.push(trace); | |
}); | |
//Load query results into trace arrays | |
$.each(data, function(i,row){ | |
//First value is a date | |
var date = new Date(row.values[0]); | |
$.each(row.values.slice(1), function(v, cell){ | |
traces[v].x.push(date); | |
traces[v].y.push(cell); | |
}); | |
}); | |
//Setup axis labels | |
var layout = { title: div.attr('title'), legend: {orientation: 'h'}}; | |
$.each(div.attr('yAxes').split(','), function(i, v){ | |
var axis = {title: v}; | |
var key = 'yaxis'; | |
if (i > 0){ | |
key += i+1; | |
axis.side = 'right'; | |
axis.overlaying = 'y'; | |
axis.position = 1-.04*(i-1); | |
} | |
layout[key] = axis; | |
}); | |
//Hide some of Plotly's external web-links | |
var config = {displaylogo: div.attr('showLinks'), showLinks: div.attr('showLinks'), modeBarButtonsToRemove: ['sendDataToCloud']}; | |
//Draw the chart | |
Plotly.newPlot('chart', traces, layout, config); | |
//Execute this function when user zooms in/out | |
div.bind('plotly_relayout', function(event,meta){ | |
var t1 = new Date(meta['xaxis.range[0]']); | |
var t2 = new Date(meta['xaxis.range[1]']); | |
$('#t1').text('Left Bound: ' + t1); | |
$('#t2').text('Right Bound: ' + t2); | |
var text = Math.floor(t1.getTime()/1000) + "|" + Math.floor(t2.getTime()/1000); | |
bounds.val(text); | |
//Give Angular a few ms to mark 'bounds' as dirty/get ready to catch change event | |
window.setTimeout(function(){bounds.trigger('input');}, 500); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%angular | |
<!-- Avoid constantly editing JS and list the Angular vars you want exposed in an HTML attribute: --> | |
<div id="dummy" vars="someScopeVar1,someScopeVar2"></div> | |
<script type="text/javascript"> | |
//Given an element in the note & list of values to fetch from Spark | |
//window.angularVars.myVal will be current value of backend Spark val of same name | |
function hoist(element){ | |
var varNames = element.attr('vars').split(','); | |
window.angularVars = {}; | |
var scope = angular.element(element.parent('.ng-scope')).scope().compiledScope; | |
$.each(varNames, function(i, v){ | |
window[v+'-watcher'] = scope.$watch(v, function(newVal, oldVal){ | |
window.angularVars[v] = newVal; | |
}); | |
}); | |
} | |
hoist($('#dummy')); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%angular | |
<div id="myAppDiv"></div> | |
<script type="text/javascript"> | |
var element = $('#myAppDiv'); | |
element.append(window.angularVars.someScopeVar1 + window.angularVars.someScopeVar2); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%spark | |
case class Log(Source: String, ts: String, Verb: String, URL: String, Protocol: String, Code: String, Size: Int) | |
/* | |
Sample Data: | |
199.72.81.55 - - [01/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245 | |
199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085 | |
burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0 | |
knuth.mtsu.edu - - [22/Jul/1995:01:49:32 -0400] "GET /images/">index of /images HTTP/1.0" 404 - | |
*/ | |
sc.textFile("logs.gz").filter(_.split("\\s").size >= 10).map(x => { | |
val req = x.split("\"").slice(1, x.split("\"").size-1).mkString("\"").split("\\s") | |
val ts = x.split("\\[")(1).split("\\]")(0).split(" ")(0) | |
val postReq = x.split("\"").last.trim.split("\\s") | |
Log(x.split(" ")(0), ts, req.head, req.slice(1, req.size-1).mkString(" "), req.last, postReq(0), if (postReq.size > 1) postReq(1).replace("-", "0").toInt else 0) | |
}).toDF().createOrReplaceTempView("weblogs_raw") | |
sqlContext.sql(""" | |
create table if not exists weblogs stored as parquet as | |
select source, from_unixtime(unix_timestamp(ts, 'dd/MMMM/yyyy:HH:mm:ss')) as datetime, verb, url, protocol, code, size from weblogs_raw | |
""") | |
sqlContext.cacheTable("weblogs") | |
sqlContext.sql("select count(*) from weblogs").collect() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%spark | |
//Query for populating Plotly graph | |
val query = """ | |
select | |
concat(date_format(datetime, 'yyyy-MM-dd HH'), ':00:00') as time, | |
count(*) as activity | |
from weblogs | |
group by concat(date_format(datetime, 'yyyy-MM-dd HH'), ':00:00') | |
order by time asc | |
""" | |
val data = sqlContext.sql(query) | |
z.angularBind("data", data.collect()) | |
z.angularBind("dataSchema", data.schema) | |
z.run("20160912-040323_647948317") | |
//Convenient wrapper around table display syntax: https://zeppelin.apache.org/docs/0.7.0-SNAPSHOT/displaysystem/basicdisplaysystem.html#table | |
def printQueryResultsAsTable(query: String) : Unit = { | |
val df = sqlContext.sql(query.replace("?", "")) | |
println("%table " + df.columns.mkString("\t")) | |
println(df.map(x => x.mkString("\t")).collect().mkString("\n")) | |
} | |
//Create variables to hold query texts | |
var logQuery = "" | |
var sourceQuery = "" | |
var areaQuery = "" | |
var codeQuery = "" | |
//Helper for resetting query texts to default | |
def resetQueries() : Unit = { | |
logQuery = "select * from weblogs ?WHERE limit 50" | |
sourceQuery = "select source, count(*) as count from weblogs ?WHERE group by source order by count desc limit 50" | |
codeQuery = "select code, count(*) as count from weblogs ?WHERE group by code" | |
areaQuery = """ | |
select | |
split(regexp_replace(url, 'http\:\/\/', ''), '/')[1] as area, | |
count(*) as count | |
from weblogs | |
?WHERE | |
group by split(regexp_replace(url, 'http\:\/\/', ''), '/')[1] | |
order by count desc limit 50 | |
""" | |
} | |
resetQueries() | |
//Init the Angular variable "bounds" | |
z.angularBind("bounds", "") | |
//Init the callback listening for changes to "bounds" | |
z.angularWatch("bounds", (oldVal, newVal) => { | |
val t1 = newVal.asInstanceOf[String].split("\\|")(0) | |
val t2 = newVal.asInstanceOf[String].split("\\|")(1) | |
resetQueries() | |
//If bounds are valid dates, add set the where filter.. otherwise remove it | |
val where = if (t1.equals("NaN") || t2.equals("NaN")) "" else "where unix_timestamp(datetime) >= " + t1 + " and unix_timestamp(datetime) <= " + t2 | |
logQuery = logQuery.replace("?WHERE", where) | |
sourceQuery = sourceQuery.replace("?WHERE", where) | |
areaQuery = areaQuery.replace("?WHERE", where) | |
codeQuery = codeQuery.replace("?WHERE", where) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%spark | |
var value = "abc" | |
z.angularBind("someAngularVar", value) | |
z.angularWatch("someAngularVar", (before, after) => { | |
value = after.asInstanceOf[String] | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%spark | |
z.angularBind("someScopeVar1", 1) | |
z.angularBind("someScopeVar2", 2) | |
z.run("20160911-191805_2145183823") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%angular | |
<div id="someId"></div> | |
<script type="text/javascript"> | |
var element = $('#someId'); | |
var angularVar = 'someScopeVar'; | |
var scope = angular.element(element.parent('.ng-scope')).scope().compiledScope; | |
//Annoying callback setup here | |
window.watcher = scope.$watch(angularVar, function(newVal, oldVal){ | |
element.text(angularVar + ': ' + oldVal + ' to: ' + newVal); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment