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