1*2abb3134SXin Li#!/bin/bash 2*2abb3134SXin Li# 3*2abb3134SXin Li# Build the user interface. 4*2abb3134SXin Li# 5*2abb3134SXin Li# Usage: 6*2abb3134SXin Li# ./ui.sh <function name> 7*2abb3134SXin Li 8*2abb3134SXin Liset -o nounset 9*2abb3134SXin Liset -o pipefail 10*2abb3134SXin Liset -o errexit 11*2abb3134SXin Li 12*2abb3134SXin Lireadonly THIS_DIR=$(dirname $0) 13*2abb3134SXin Lireadonly RAPPOR_SRC=$(cd $THIS_DIR/.. && pwd) 14*2abb3134SXin Li 15*2abb3134SXin Lisource $RAPPOR_SRC/pipeline/tools-lib.sh 16*2abb3134SXin Li 17*2abb3134SXin Li# Change the default location of this file by setting DEP_DYGRAPHS_JS 18*2abb3134SXin Lireadonly DYGRAPHS_JS=${DEP_DYGRAPHS_JS:-$RAPPOR_SRC/third_party/dygraph-combined.js} 19*2abb3134SXin Li 20*2abb3134SXin Li_link() { 21*2abb3134SXin Li ln --verbose -s -f "$@" 22*2abb3134SXin Li} 23*2abb3134SXin Li 24*2abb3134SXin Li_copy() { 25*2abb3134SXin Li cp --verbose -f "$@" 26*2abb3134SXin Li} 27*2abb3134SXin Li 28*2abb3134SXin Lidownload-dygraphs() { 29*2abb3134SXin Li local out=third_party 30*2abb3134SXin Li wget --directory $out \ 31*2abb3134SXin Li http://dygraphs.com/1.1.1/dygraph-combined.js 32*2abb3134SXin Li} 33*2abb3134SXin Li 34*2abb3134SXin Liimport-table() { 35*2abb3134SXin Li local src=~/git/scratch/ajax/ 36*2abb3134SXin Li cp --verbose $src/table-sort.{js,css} $src/url-hash.js ui 37*2abb3134SXin Li pushd ui 38*2abb3134SXin Li # TODO: Could minify it here 39*2abb3134SXin Li cat table-sort.js url-hash.js > table-lib.js 40*2abb3134SXin Li popd 41*2abb3134SXin Li} 42*2abb3134SXin Li 43*2abb3134SXin Li# Use symlinks so we can edit and reload during development. 44*2abb3134SXin Lisymlink-static() { 45*2abb3134SXin Li local kind=$1 46*2abb3134SXin Li local job_dir=$2 47*2abb3134SXin Li 48*2abb3134SXin Li local base=$RAPPOR_SRC/ui 49*2abb3134SXin Li 50*2abb3134SXin Li # HTML goes at the top level. 51*2abb3134SXin Li if test "$kind" = dist; then 52*2abb3134SXin Li _link \ 53*2abb3134SXin Li $base/overview.html $base/histograms.html $base/metric.html $base/day.html \ 54*2abb3134SXin Li $job_dir 55*2abb3134SXin Li elif test "$kind" = assoc; then 56*2abb3134SXin Li _link \ 57*2abb3134SXin Li $base/assoc-overview.html $base/assoc-metric.html $base/assoc-pair.html \ 58*2abb3134SXin Li $base/assoc-day.html \ 59*2abb3134SXin Li $job_dir 60*2abb3134SXin Li else 61*2abb3134SXin Li log "Invalid kind $kind" 62*2abb3134SXin Li exit 1 63*2abb3134SXin Li fi 64*2abb3134SXin Li 65*2abb3134SXin Li mkdir --verbose -p $job_dir/static 66*2abb3134SXin Li 67*2abb3134SXin Li # Static subdir. 68*2abb3134SXin Li _link \ 69*2abb3134SXin Li $base/ui.css $base/ui.js \ 70*2abb3134SXin Li $base/table-sort.css $base/table-lib.js \ 71*2abb3134SXin Li $DYGRAPHS_JS \ 72*2abb3134SXin Li $job_dir/static 73*2abb3134SXin Li} 74*2abb3134SXin Li 75*2abb3134SXin Li 76*2abb3134SXin Li# Write HTML fragment based on overview.csv. 77*2abb3134SXin Lioverview-part-html() { 78*2abb3134SXin Li local job_dir=${1:-_tmp/results-10} 79*2abb3134SXin Li local out=$job_dir/cooked/overview.part.html 80*2abb3134SXin Li # Sort by descending date! 81*2abb3134SXin Li TOOLS-csv-to-html \ 82*2abb3134SXin Li --col-format 'metric <a href="metric.html#metric={metric}">{metric}</a>' \ 83*2abb3134SXin Li < $job_dir/cooked/overview.csv \ 84*2abb3134SXin Li > $out 85*2abb3134SXin Li echo "Wrote $out" 86*2abb3134SXin Li} 87*2abb3134SXin Li 88*2abb3134SXin Limetric-part-html() { 89*2abb3134SXin Li local job_dir=${1:-_tmp/results-10} 90*2abb3134SXin Li # Testing it out. This should probably be a different dir. 91*2abb3134SXin Li 92*2abb3134SXin Li for entry in $job_dir/cooked/*; do 93*2abb3134SXin Li # Only do it for dirs 94*2abb3134SXin Li if ! test -d $entry; then 95*2abb3134SXin Li continue 96*2abb3134SXin Li fi 97*2abb3134SXin Li # Now it's a metric dir 98*2abb3134SXin Li echo $entry 99*2abb3134SXin Li 100*2abb3134SXin Li local metric_name=$(basename $entry) 101*2abb3134SXin Li 102*2abb3134SXin Li # Convert status.csv to status.part.html (a fragment) 103*2abb3134SXin Li 104*2abb3134SXin Li # NOTE: counts path could be useful. You need the input tree though. Hash 105*2abb3134SXin Li # it? Or point to the git link. 106*2abb3134SXin Li 107*2abb3134SXin Li # Link to raw CSV 108*2abb3134SXin Li #--col-format 'date <a href="../../raw/{metric}/{date}/results.csv">{date}</a>' \ 109*2abb3134SXin Li 110*2abb3134SXin Li # TODO: Link to ui/results_viewer.html#{metric}_{date} 111*2abb3134SXin Li # And that needs some JavaScript to load the correct fragment. 112*2abb3134SXin Li # I guess you could do the same with metric.html. Currently it uses a 113*2abb3134SXin Li # symlink. 114*2abb3134SXin Li 115*2abb3134SXin Li # Before job ID: 116*2abb3134SXin Li # --col-format 'date <a href="{date}.html">{date}</a>' \ 117*2abb3134SXin Li # --col-format 'status <a href="../../raw/{metric}/{date}/log.txt">{status}</a>' \ 118*2abb3134SXin Li 119*2abb3134SXin Li local fmt1='date <a href="day.html#jobId={job_id}&metric={metric}&date={date}">{date}</a>' 120*2abb3134SXin Li local fmt2='status <a href="../{job_id}/raw/{metric}/{date}/log.txt">{status}</a>' 121*2abb3134SXin Li 122*2abb3134SXin Li TOOLS-csv-to-html \ 123*2abb3134SXin Li --def "metric $metric_name" \ 124*2abb3134SXin Li --col-format "$fmt1" \ 125*2abb3134SXin Li --col-format "$fmt2" \ 126*2abb3134SXin Li < $entry/status.csv \ 127*2abb3134SXin Li > $entry/status.part.html 128*2abb3134SXin Li done 129*2abb3134SXin Li} 130*2abb3134SXin Li 131*2abb3134SXin Liresults-html-one() { 132*2abb3134SXin Li local csv_in=$1 133*2abb3134SXin Li echo "$csv_in -> HTML" 134*2abb3134SXin Li 135*2abb3134SXin Li # .../raw/Settings.HomePage2/2015-03-01/results.csv -> 136*2abb3134SXin Li # .../cooked/Settings.HomePage2/2015-03-01.part.html 137*2abb3134SXin Li # (This saves some directories) 138*2abb3134SXin Li local html_out=$(echo $csv_in | sed -e 's|/raw/|/cooked/|; s|/results.csv|.part.html|') 139*2abb3134SXin Li 140*2abb3134SXin Li TOOLS-csv-to-html < $csv_in > $html_out 141*2abb3134SXin Li} 142*2abb3134SXin Li 143*2abb3134SXin Liresults-html() { 144*2abb3134SXin Li local job_dir=${1:-_tmp/results-10} 145*2abb3134SXin Li 146*2abb3134SXin Li find $job_dir -name results.csv \ 147*2abb3134SXin Li | xargs -n 1 --verbose --no-run-if-empty -- $0 results-html-one 148*2abb3134SXin Li} 149*2abb3134SXin Li 150*2abb3134SXin Li# Build parts of the HTML 151*2abb3134SXin Libuild-html1() { 152*2abb3134SXin Li local job_dir=${1:-_tmp/results-10} 153*2abb3134SXin Li 154*2abb3134SXin Li symlink-static dist $job_dir 155*2abb3134SXin Li 156*2abb3134SXin Li # writes overview.part.html, which is loaded by overview.html 157*2abb3134SXin Li overview-part-html $job_dir 158*2abb3134SXin Li 159*2abb3134SXin Li # Writes status.part.html for each metric 160*2abb3134SXin Li metric-part-html $job_dir 161*2abb3134SXin Li} 162*2abb3134SXin Li 163*2abb3134SXin Li# 164*2abb3134SXin Li# Association Analysis 165*2abb3134SXin Li# 166*2abb3134SXin Li 167*2abb3134SXin Lireadonly ASSOC_TEST_JOB_DIR=~/rappor/chrome-assoc-smoke/smoke5-assoc 168*2abb3134SXin Li 169*2abb3134SXin Li# Write HTML fragment based on CSV. 170*2abb3134SXin Liassoc-overview-part-html() { 171*2abb3134SXin Li local job_dir=${1:-$ASSOC_TEST_JOB_DIR} 172*2abb3134SXin Li local html_path=$job_dir/cooked/assoc-overview.part.html 173*2abb3134SXin Li 174*2abb3134SXin Li # Sort by descending date! 175*2abb3134SXin Li 176*2abb3134SXin Li TOOLS-csv-to-html \ 177*2abb3134SXin Li --col-format 'metric <a href="assoc-metric.html#metric={metric}">{metric}</a>' \ 178*2abb3134SXin Li < $job_dir/cooked/assoc-overview.csv \ 179*2abb3134SXin Li > $html_path 180*2abb3134SXin Li echo "Wrote $html_path" 181*2abb3134SXin Li} 182*2abb3134SXin Li 183*2abb3134SXin Liassoc-metric-part-html-one() { 184*2abb3134SXin Li local csv_path=$1 185*2abb3134SXin Li local html_path=$(echo $csv_path | sed 's/.csv$/.part.html/') 186*2abb3134SXin Li 187*2abb3134SXin Li local metric_dir=$(dirname $csv_path) 188*2abb3134SXin Li local metric_name=$(basename $metric_dir) # e.g. interstitial.harmful 189*2abb3134SXin Li 190*2abb3134SXin Li local fmt='days <a href="assoc-pair.html#metric={metric}&var1={var1}&var2={var2}">{days}</a>' 191*2abb3134SXin Li 192*2abb3134SXin Li TOOLS-csv-to-html \ 193*2abb3134SXin Li --def "metric $metric_name" \ 194*2abb3134SXin Li --col-format "$fmt" \ 195*2abb3134SXin Li < $csv_path \ 196*2abb3134SXin Li > $html_path 197*2abb3134SXin Li 198*2abb3134SXin Li echo "Wrote $html_path" 199*2abb3134SXin Li} 200*2abb3134SXin Li 201*2abb3134SXin Liassoc-metric-part-html() { 202*2abb3134SXin Li local job_dir=${1:-$ASSOC_TEST_JOB_DIR} 203*2abb3134SXin Li # Testing it out. This should probably be a different dir. 204*2abb3134SXin Li 205*2abb3134SXin Li find $job_dir/cooked -name metric-status.csv \ 206*2abb3134SXin Li | xargs -n 1 --verbose --no-run-if-empty -- $0 assoc-metric-part-html-one 207*2abb3134SXin Li} 208*2abb3134SXin Li 209*2abb3134SXin Li# TODO: 210*2abb3134SXin Li# - Construct link in JavaScript instead? It has more information. The 211*2abb3134SXin Li# pair-metadata.txt file is a hack. 212*2abb3134SXin Li 213*2abb3134SXin Liassoc-pair-part-html-one() { 214*2abb3134SXin Li local csv_path=$1 215*2abb3134SXin Li local html_path=$(echo $csv_path | sed 's/.csv$/.part.html/') 216*2abb3134SXin Li 217*2abb3134SXin Li local pair_dir_path=$(dirname $csv_path) 218*2abb3134SXin Li local pair_dir_name=$(basename $pair_dir_path) # e.g. domain_X_flags_IS_REPEAT_VISIT 219*2abb3134SXin Li 220*2abb3134SXin Li # This file is generated by metric_status.R for each pair of variables. 221*2abb3134SXin Li local metadata="$pair_dir_path/pair-metadata.txt" 222*2abb3134SXin Li # Read one variable per line. 223*2abb3134SXin Li { read metric_name; read var1; read var2; } < $metadata 224*2abb3134SXin Li 225*2abb3134SXin Li local fmt1='date <a href="assoc-day.html#jobId={job_id}&metric={metric}&var1={var1}&var2={var2}&date={date}">{date}</a>' 226*2abb3134SXin Li local fmt2="status <a href=\"../{job_id}/raw/{metric}/$pair_dir_name/{date}/assoc-log.txt\">{status}</a>" 227*2abb3134SXin Li 228*2abb3134SXin Li TOOLS-csv-to-html \ 229*2abb3134SXin Li --def "metric $metric_name" \ 230*2abb3134SXin Li --def "var1 $var1" \ 231*2abb3134SXin Li --def "var2 $var2" \ 232*2abb3134SXin Li --col-format "$fmt1" \ 233*2abb3134SXin Li --col-format "$fmt2" \ 234*2abb3134SXin Li < $csv_path \ 235*2abb3134SXin Li > $html_path 236*2abb3134SXin Li} 237*2abb3134SXin Li 238*2abb3134SXin Liassoc-pair-part-html() { 239*2abb3134SXin Li local job_dir=${1:-~/rappor/chrome-assoc-smoke/smoke3} 240*2abb3134SXin Li # Testing it out. This should probably be a different dir. 241*2abb3134SXin Li 242*2abb3134SXin Li find $job_dir/cooked -name pair-status.csv \ 243*2abb3134SXin Li | xargs -n 1 --verbose -- $0 assoc-pair-part-html-one 244*2abb3134SXin Li 245*2abb3134SXin Li return 246*2abb3134SXin Li 247*2abb3134SXin Li # OLD STUFF 248*2abb3134SXin Li for entry in $job_dir/cooked/*; do 249*2abb3134SXin Li # Only do it for dirs 250*2abb3134SXin Li if ! test -d $entry; then 251*2abb3134SXin Li continue 252*2abb3134SXin Li fi 253*2abb3134SXin Li # Now it's a metric dir 254*2abb3134SXin Li echo $entry 255*2abb3134SXin Li 256*2abb3134SXin Li local metric_name=$(basename $entry) 257*2abb3134SXin Li 258*2abb3134SXin Li # Convert status.csv to status.part.html (a fragment) 259*2abb3134SXin Li 260*2abb3134SXin Li # NOTE: counts path could be useful. You need the input tree though. Hash 261*2abb3134SXin Li # it? Or point to the git link. 262*2abb3134SXin Li 263*2abb3134SXin Li # Link to raw CSV 264*2abb3134SXin Li #--col-format 'date <a href="../../raw/{metric}/{date}/results.csv">{date}</a>' \ 265*2abb3134SXin Li 266*2abb3134SXin Li # TODO: Link to ui/results_viewer.html#{metric}_{date} 267*2abb3134SXin Li # And that needs some JavaScript to load the correct fragment. 268*2abb3134SXin Li # I guess you could do the same with metric.html. Currently it uses a 269*2abb3134SXin Li # symlink. 270*2abb3134SXin Li 271*2abb3134SXin Li # Before job ID: 272*2abb3134SXin Li # --col-format 'date <a href="{date}.html">{date}</a>' \ 273*2abb3134SXin Li # --col-format 'status <a href="../../raw/{metric}/{date}/log.txt">{status}</a>' \ 274*2abb3134SXin Li 275*2abb3134SXin Li local fmt1='date <a href="day.html#jobId={job_id}&metric={metric}&date={date}">{date}</a>' 276*2abb3134SXin Li local fmt2='status <a href="../{job_id}/raw/{metric}/{date}/log.txt">{status}</a>' 277*2abb3134SXin Li 278*2abb3134SXin Li TOOLS-csv-to-html \ 279*2abb3134SXin Li --def "metric $metric_name" \ 280*2abb3134SXin Li --col-format "$fmt1" \ 281*2abb3134SXin Li --col-format "$fmt2" \ 282*2abb3134SXin Li < $entry/status.csv \ 283*2abb3134SXin Li > $entry/status.part.html 284*2abb3134SXin Li done 285*2abb3134SXin Li} 286*2abb3134SXin Li 287*2abb3134SXin Liassoc-day-part-html-one() { 288*2abb3134SXin Li local csv_in=$1 289*2abb3134SXin Li echo "$csv_in -> HTML" 290*2abb3134SXin Li 291*2abb3134SXin Li # .../raw/interstitial.harmful/a_X_b/2015-03-01/assoc-results.csv -> 292*2abb3134SXin Li # .../cooked/interstitial.harmful/a_X_b/2015-03-01.part.html 293*2abb3134SXin Li # (This saves some directories) 294*2abb3134SXin Li local html_out=$(echo $csv_in | sed -e 's|/raw/|/cooked/|; s|/assoc-results.csv|.part.html|') 295*2abb3134SXin Li 296*2abb3134SXin Li TOOLS-csv-to-html --as-percent proportion < $csv_in > $html_out 297*2abb3134SXin Li} 298*2abb3134SXin Li 299*2abb3134SXin Liassoc-day-part-html() { 300*2abb3134SXin Li local job_dir=${1:-_tmp/results-10} 301*2abb3134SXin Li 302*2abb3134SXin Li find $job_dir -name assoc-results.csv \ 303*2abb3134SXin Li | xargs -n 1 --verbose --no-run-if-empty -- $0 assoc-day-part-html-one 304*2abb3134SXin Li} 305*2abb3134SXin Li 306*2abb3134SXin Lilint-html() { 307*2abb3134SXin Li set -o xtrace 308*2abb3134SXin Li set +o errexit # don't fail fast 309*2abb3134SXin Li tidy -errors -quiet ui/metric.html 310*2abb3134SXin Li tidy -errors -quiet ui/overview.html 311*2abb3134SXin Li tidy -errors -quiet ui/histograms.html 312*2abb3134SXin Li} 313*2abb3134SXin Li 314*2abb3134SXin Li# Directory we should serve from 315*2abb3134SXin Lireadonly WWW_DIR=_tmp 316*2abb3134SXin Li 317*2abb3134SXin Liserve() { 318*2abb3134SXin Li local port=${1:-7999} 319*2abb3134SXin Li cd $WWW_DIR && python -m SimpleHTTPServer $port 320*2abb3134SXin Li} 321*2abb3134SXin Li 322*2abb3134SXin Li"$@" 323