{"version":3,"file":"app-2500ebb2.47e839c4edc29ae0ca22.bundle.js","mappings":";;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACPA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;ACHA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;ACHA;AACA;AAGA;AACA;AAAA;AAAA;AAKA;AACA;AACA;AAEA;AACA;AACA;AARA;AAAA;;AAAA;AAJA;AADA;AAEA;AADA;AAaA;AAAA;AAbA;;;;;;;;;;;;;;;;;;;;;;;;;;ACJA;AAEA;AAGA;AACA;AAMA;AACA;AACA;AACA;AAEA;AAIA;AACA;AAGA;AACA;AAGA;AAtBA;AACA;AACA;AACA;AAuBA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAEA;AACA;AAEA;AACA;AACA;AACA;;;AALA;AAQA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAAA;AACA;AACA;AACA;AACA;AA9CA;AAAA;;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAcA;AAAA;AAKA;AAAA;AAFA;AAvCA;AADA;;AACA;AA8DA;AAAA;AA9DA;AAgEA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AAKA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1FA;AACA;AAGA;AAGA;AACA;AAAA;AAAA;AAAA;AAMA;AAEA;AACA;AAGA;AAEA;AACA;AACA;AAGA;AACA;AAEA;AACA;AAQA;AAeA;AA4MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAEA;AACA;AA5QA;AACA;AACA;AACA;AAqBA;AACA;AACA;AAKA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAGA;AACA;AAEA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AAEA;AAAA;;AACA;AAEA;AAEA;AAYA;AACA;AACA;AAIA;AACA;AAGA;AAEA;AACA;AAEA;AACA;AAGA;AAEA;AAEA;AACA;AAAA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AALA;AASA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAuBA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAAA;AACA;AACA;AAEA;AACA;AAAA;AACA;AAAA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AAEA;AAAA;AACA;AACA;;;AAAA;AAEA;AACA;AAAA;AACA;AACA;AArSA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AADA;AACA;AAAA;AACA;AAAA;;AAAA;AAEA;AADA;;AACA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AADA;;AACA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;;AAAA;AA6QA;AAAA;;;AAIA;AAzSA;AADA;AAEA;AADA;AA+SA;AAAA;AA/SA;;;;;;;;;;;;;;;;;;;;;;;;;ACRA;AAMA;AAAA;AAEA;AADA;AAAA;;AAAA;AADA;AAHA;AACA;AACA;AACA;AAEA;AAAA;AAFA;;;;;;;;;;;;;;;;;;;;;;;;;ACNA;AAKA;AAAA;AACA;AACA;AASA;AALA;AACA;AACA;AACA;AACA;AATA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAJA;AAHA;AACA;AACA;AACA;AAWA;AAAA;AAXA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAIA;AAAA;AACA;AACA;AADA;AASA;AAEA;AACA;AAIA;AAGA;AAOA;;AAxBA;AA8BA;AACA;AACA;AACA;AACA;AAEA;;;;;AACA;;AAAA;AACA;AACA;;;;AAEA;;AAAA;AACA;;;;AAEA;;;AAEA;AACA;;;;AAIA;AACA;AACA;;;;;;AAEA;AAEA;;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AAGA;;;;;AACA;AACA;AACA;AACA;AACA;;AAAA;AACA;;;;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAvHA;AADA;AACA;AAAA;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAkBA;AAFA;AACA;AACA;;AAAA;AA/BA;AAFA;AACA;AAEA;AADA;AA8HA;AAAA;AA9HA;AAgIA;AAAA;AAEA;AAmBA;AAoCA;AAlCA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAtDA;AADA;;AACA;AAGA;AADA;;AACA;AAGA;AADA;;AACA;AAGA;AADA;;AACA;AAGA;AADA;;AACA;AAIA;AAFA;AACA;;AACA;AAGA;AADA;;AACA;AAoCA;AAAA;AAzDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7IA;AACA;AAIA;AAAA;AAAA;;AACA;;AACA;AADA;AAAA;;AAAA;AADA;AAFA;AACA;AACA;AAEA;AAAA;AAFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAAA;AACA;AACA;AADA;AAAA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;AAxBA;AA2BA;AAAA;AACA;AACA;;AAAA;;AAAA;;;AAAA;AACA;;AAAA;;AAAA;;;AAAA;AACA;;AAAA;;AAAA;;;AAAA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA/CA;AAFA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AApBA;AAFA;AACA;AAEA;AADA;AAuDA;AAAA;AAvDA;AAyDA;AACA;AAAA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAgCA;AAqCA;AAGA;AArFA;AACA;AAcA;AAAA;AAGA;AACA;;;AAAA;AAoEA;AAAA;AAGA;AACA;AACA;AAEA;AACA;;;AAAA;AAEA;AAAA;AAGA;AACA;AACA;AAEA;AACA;;;AAAA;AAEA;AAAA;AAGA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;;;AAAA;AAEA;AAAA;AAAA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlKA;AAAA;AACA;;;AAGA;AAGA;AADA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAGA;AADA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAIA;AAFA;AACA;;AACA;AAKA;AAHA;AACA;AACA;AACA;AAAA;AAGA;AADA;;AACA;AAEA;AAAA;AACA;;;AAOA;AAEA;AAAA;AACA;;;AAOA;AAEA;AAAA;AACA;;;AAWA;AA2DA;AAAA;AApLA;AAsLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjRA;AACA;AAEA;AACA;AAIA;AAAA;AAAA;;AACA;AAEA;;AAcA;AAZA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAfA;AAAA;;AAAA;AADA;AAFA;AACA;AACA;AAiBA;AAAA;AAjBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACRA;AACA;AACA;AACA;AAIA;AAAA;AAAA;;AACA;AAKA;AAEA;AACA;AACA;;AAuEA;AArEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AA/EA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AANA;AAFA;AACA;AACA;AAiFA;AAAA;AAjFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAAA;AAEA;AAOA;AANA;AACA;AACA;AACA;AACA;AACA;AAOA;AAGA;AACA;AAEA;AAEA;AACA;;AAdA;AAgBA;AAAA;AACA;AAGA;AACA;AACA;AAEA;;;;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;AACA;AAEA;;AA+CA;AAAA;AAEA;;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;;;;;AAxDA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAGA;AACA;AAEA;;AAAA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAcA;;AAAA;;;;;AACA;AAEA;;;;;;;;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;;;AACA;AACA;AACA;AACA;AACA;;AACA;AACA;;AACA;AACA;AACA;AACA;AAEA;;AACA;AACA;;AACA;;AACA;AACA;AACA;;AAxBA;AA0BA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;;;AAGA;;;;;AAEA;AAEA;AACA;AACA;AAEA;;;;;AACA;AACA;AACA;AACA;;AAAA;;;;;AACA;AAEA;AAAA;;AAAA;;;;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;;AAAA;;;;;AACA;AAEA;;;AACA;AAEA;AACA;AACA;;;;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AAAA;AAAA;AAEA;AACA;;;AAAA;AAEA;AAAA;AAAA;AAEA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AArPA;AAAA;;AAAA;AASA;AAAA;;AAAA;AAsNA;AAAA;;;AAGA;AAEA;AAAA;;;AAGA;AAnPA;AAFA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AARA;AAkQA;AAAA;AAlQA;AAoQA;AAAA;AAMA;AALA;AACA;AACA;AAAA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxRA;AACA;AACA;AAIA;AAAA;AAUA;AAEA;AADA;AATA;AACA;AACA;AAIA;;AAKA;AAEA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;;;AAZA;AAAA;AAaA;AACA;AAEA;AACA;AACA;AACA;AACA;AA3CA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;;AAAA;AAJA;AAFA;AACA;AAYA;AAXA;AA6CA;AAAA;AA7CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACNA;AACA;AACA;AAIA;AAAA;AAAA;;AAEA;AACA;AACA;;AAaA;AATA;AACA;AACA;AACA;AACA;AAEA;AAAA;AACA;AACA;AAfA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;;AAAA;AAJA;AAFA;AACA;AACA;AAiBA;AAAA;AAjBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACNA;AACA;AAIA;AAAA;AAAA;;AACA;;AACA;AADA;AAAA;;AAAA;AADA;AAFA;AACA;AACA;AAEA;AAAA;AAFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLA;AACA;AACA;AACA;AACA;AAIA;AAAA;AAAA;;AACA;AACA;AAEA;AAEA;;AAcA;AAZA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAlBA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AAJA;AAFA;AACA;AACA;AAoBA;AAAA;AApBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACRA;AACA;AACA;AAIA;AAAA;AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;;AAoCA;AAlCA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AAAA;AAEA;AACA;;;AAAA;AAxCA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAgCA;AAAA;;;AAGA;AAzCA;AAFA;AACA;AACA;AA0CA;AAAA;AA1CA;;;;;;;;;;;;;;;;ACNA;AACA;AAOA;AAmBA;AAFA;AAGA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AACA;AAEA;AAGA;AAEA;AAEA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AAGA;AAEA;AACA;AAGA;AACA;AAKA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AAEA;AACA;AAEA;AACA;AAGA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AAGA;AACA;AAGA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AACA;AACA;AAAA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;ACpMA;AAAA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAGA;AAWA;AAgBA;AAVA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvCA;AAGA;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;;AACA;AAEA;AAAA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;ACjGA;AAAA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACdA;AAGA;AAAA;AASA;AACA;AATA;AACA;AACA;AAQA;AACA;AACA;AACA;;AACA;AAEA;AAAA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAAA;AACA;AAGA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAAA;AAGA;AAEA;AACA;AAGA;AACA;AAGA;AAEA;AAEA;AAEA;AAEA;AACA;AAIA;AAAA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAGA;AAEA;AAGA;AACA;AACA;AACA;AAAA;AAEA;AACA;;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAEA;AAEA;AACA;AAKA;AAAA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACpMA;AAMA;AA0BA;AArBA;AAGA;AACA;AACA;AACA;AAGA;AAEA;AACA;AAEA;AACA;AAEA;AAEA;AAGA;AAEA;AACA;AACA;AAIA;AAIA;AAGA;AAGA;AACA;AAIA;AAIA;AACA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAAA;AAEA;AAEA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AAUA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAhIA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAGA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AAmHA;AAAA;AAzIA;;;;;;;;;;;;;;;;;;;ACNA;AACA;AACA;AACA;AASA;AAAA;AAuGA;AAtGA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAIA;AACA;AAEA;AACA;AAGA;AACA;AAGA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AAAA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;AClHA;AAAA;AACA;AAAA;AAAA;;;;;;;;;;;;;;;;ACAA;AAEA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;ACwCA;AAiBA;AAhBA;AACA;AACA;AAEA;AAIA;AAEA;AAEA;AAKA;AACA;AAGA;AACA;AAEA;AACA;;AAEA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAGA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAGA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzJA;AACA;AAIA;AACA;AACA;AAGA;AACA;AACA;AACA;AAcA;AA+CA;AApCA;AACA;AACA;AAaA;AAMA;AAIA;AACA;AACA;AAGA;AAqBA;AA8DA;AA5EA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AAGA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAGA;AACA;AAEA;AACA;AAIA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAIA;AAAA;AACA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;AACA;AACA;;;AAAA;AAEA;AAAA;AACA;AACA;AACA;AACA;;;AAAA;AA1IA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAGA;AAAA;;AAAA;AACA;AAAA;AAAA;AAAA;AAGA;AAAA;;AAAA;AAKA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAEA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAIA;AAAA;;AAAA;AACA;AAAA;;AAAA;AACA;AAAA;;AAAA;AAGA;AAAA;;AAAA;AAmFA;AAAA;;AAAA;AA5HA;AAZA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAgDA;AA/CA;AAsJA;AAAA;AAtJA;AAuJA;AACA;AACA;AACA","sources":["webpack://client-app/./src/resources/elements/form-button/form-button.scss","webpack://client-app/./src/resources/elements/form-input-address/form-input-address.scss","webpack://client-app/./src/resources/elements/form-input-bool/form-input-bool.scss","webpack://client-app/./src/resources/elements/form-input-file/form-input-file.scss","webpack://client-app/./src/resources/elements/form-input-multiple/form-input-multiple.scss","webpack://client-app/./src/resources/elements/form-input-radio/form-input-radio.scss","webpack://client-app/./src/resources/elements/form-input-telephone/form-input-telephone.scss","webpack://client-app/./src/resources/elements/grid/grid.scss","webpack://client-app/./src/resources/dialogs/prompt.html","webpack://client-app/./src/resources/elements/crisp-input-radio/crisp-input-radio.html","webpack://client-app/./src/resources/elements/crisp-picker/crisp-picker.html","webpack://client-app/./src/resources/elements/ex-icon/control.html","webpack://client-app/./src/resources/elements/form-button/control.html","webpack://client-app/./src/resources/elements/form-input-address/form-input-address.html","webpack://client-app/./src/resources/elements/form-input-bool/form-input-bool.html","webpack://client-app/./src/resources/elements/form-input-contact/form-input-contact.html","webpack://client-app/./src/resources/elements/form-input-country/form-input-country.html","webpack://client-app/./src/resources/elements/form-input-date/form-input-date.html","webpack://client-app/./src/resources/elements/form-input-file/form-input-file.html","webpack://client-app/./src/resources/elements/form-input-multiple/form-input-multiple.html","webpack://client-app/./src/resources/elements/form-input-radio/form-input-radio.html","webpack://client-app/./src/resources/elements/form-input-readonly/form-input-readonly.html","webpack://client-app/./src/resources/elements/form-input-telephone/form-input-telephone.html","webpack://client-app/./src/resources/elements/form-input-text/form-input-text.html","webpack://client-app/./src/resources/elements/grid/grid.html","webpack://client-app/./src/resources/dialogs/prompt.ts","webpack://client-app/./src/resources/elements/crisp-input-radio/crisp-input-radio.ts","webpack://client-app/./src/resources/elements/crisp-picker/crisp-picker.ts","webpack://client-app/./src/resources/elements/ex-icon/control.ts","webpack://client-app/./src/resources/elements/form-button/control.ts","webpack://client-app/./src/resources/elements/form-input-address/form-input-address.ts","webpack://client-app/./src/resources/elements/form-input-bool/form-input-bool.ts","webpack://client-app/./src/resources/elements/form-input-contact/form-input-contact.ts","webpack://client-app/./src/resources/elements/form-input-country/form-input-country.ts","webpack://client-app/./src/resources/elements/form-input-date/form-input-date.ts","webpack://client-app/./src/resources/elements/form-input-file/form-input-file.ts","webpack://client-app/./src/resources/elements/form-input-multiple/form-input-multiple.ts","webpack://client-app/./src/resources/elements/form-input-radio/form-input-radio.ts","webpack://client-app/./src/resources/elements/form-input-readonly/form-input-readonly.ts","webpack://client-app/./src/resources/elements/form-input-telephone/form-input-telephone.ts","webpack://client-app/./src/resources/elements/form-input-text/form-input-text.ts","webpack://client-app/./src/resources/elements/grid/grid-builder.ts","webpack://client-app/./src/resources/elements/grid/grid-column.ts","webpack://client-app/./src/resources/elements/grid/grid-delegate-source.ts","webpack://client-app/./src/resources/elements/grid/grid-icons.ts","webpack://client-app/./src/resources/elements/grid/grid-local-source.ts","webpack://client-app/./src/resources/elements/grid/grid-pager.ts","webpack://client-app/./src/resources/elements/grid/grid-parser.ts","webpack://client-app/./src/resources/elements/grid/grid-row.ts","webpack://client-app/./src/resources/elements/grid/grid-selection.ts","webpack://client-app/./src/resources/elements/grid/grid-source.ts","webpack://client-app/./src/resources/elements/grid/grid.ts"],"sourcesContent":["// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `form-button button.with-icon {\n  padding: 14px 40px 14px 24px;\n}\nform-button button:disabled {\n  cursor: not-allowed;\n}\nform-button .icon-ctr {\n  position: relative;\n  display: inline-block;\n  width: 28px;\n  height: 10px;\n}\nform-button .icon-ctr ex-icon {\n  position: absolute;\n  font-size: 1.6em;\n  color: #666;\n  top: -8px;\n  left: 0;\n}\nform-button.red {\n  margin-left: 10px;\n}\nform-button.red button:hover {\n  background-color: rgb(255, 110, 110);\n  color: #fff;\n}\nform-button.red button:hover ex-icon {\n  color: #fff;\n}\nform-button.small {\n  font-size: 0.85em;\n}\nform-button.small button {\n  padding: 14px 25px;\n  border-radius: 6px;\n}\nform-button.small button.with-icon {\n  padding: 14px 20px 14px 5px;\n}\nform-button.small ex-icon {\n  top: -4px;\n  left: 7px;\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-button/form-button.scss\"],\"names\":[],\"mappings\":\"AAEI;EACE,4BAAA;AADN;AAKE;EACE,mBAAA;AAHJ;AAME;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,YAAA;AAJJ;AAMI;EACE,kBAAA;EACA,gBAAA;EACA,WAAA;EACA,SAAA;EACA,OAAA;AAJN;AAQE;EACE,iBAAA;AANJ;AASM;EACE,oCAAA;EACA,WAAA;AAPR;AASQ;EACE,WAAA;AAPV;AAaE;EACE,iBAAA;AAXJ;AAaI;EACE,kBAAA;EACA,kBAAA;AAXN;AAaM;EACE,2BAAA;AAXR;AAeI;EACE,SAAA;EACA,SAAA;AAbN\",\"sourcesContent\":[\"form-button {\\r\\n  button {\\r\\n    &.with-icon {\\r\\n      padding: 14px 40px 14px 24px;\\r\\n    }\\r\\n  }\\r\\n\\r\\n  button:disabled{\\r\\n    cursor: not-allowed;\\r\\n  }\\r\\n\\r\\n  .icon-ctr {\\r\\n    position: relative;\\r\\n    display: inline-block;\\r\\n    width: 28px;\\r\\n    height:10px;\\r\\n\\r\\n    ex-icon {\\r\\n      position: absolute;\\r\\n      font-size: 1.6em;\\r\\n      color: #666;\\r\\n      top:-8px;\\r\\n      left:0;\\r\\n    }\\r\\n  }\\r\\n\\r\\n  &.red {\\r\\n    margin-left: 10px;\\r\\n\\r\\n    button {\\r\\n      &:hover {\\r\\n        background-color: rgb(255, 110, 110);\\r\\n        color: #fff;\\r\\n\\r\\n        ex-icon {\\r\\n          color: #fff;\\r\\n        }\\r\\n      }\\r\\n    }\\r\\n  }\\r\\n\\r\\n  &.small {\\r\\n    font-size: 0.85em;\\r\\n\\r\\n    button {\\r\\n      padding: 14px 25px;\\r\\n      border-radius: 6px;\\r\\n\\r\\n      &.with-icon {\\r\\n        padding: 14px 20px 14px 5px;\\r\\n      }\\r\\n    }\\r\\n\\r\\n    ex-icon {\\r\\n      top:-4px;\\r\\n      left:7px;\\r\\n    }\\r\\n  }\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.search-results {\n  margin: 0 0 10px 0;\n  max-height: 320px;\n  overflow: auto;\n  overflow-x: hidden;\n  overflow-y: auto;\n  -webkit-overflow-scrolling: touch;\n}\n.search-results div {\n  background: #fff;\n  padding: 15px;\n  margin: 3px;\n  cursor: pointer;\n}\n.search-results div:hover {\n  background: #fefefe;\n}\n\nh4 span {\n  font-weight: normal;\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-input-address/form-input-address.scss\"],\"names\":[],\"mappings\":\"AAAA;EACI,kBAAA;EACA,iBAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,iCAAA;AACJ;AACI;EACI,gBAAA;EACA,aAAA;EACA,WAAA;EACA,eAAA;AACR;AACQ;EACI,mBAAA;AACZ;;AAIA;EACE,mBAAA;AADF\",\"sourcesContent\":[\".search-results {\\r\\n    margin: 0 0 10px 0;\\r\\n    max-height: 320px;\\r\\n    overflow: auto;\\r\\n    overflow-x: hidden;\\r\\n    overflow-y: auto;\\r\\n    -webkit-overflow-scrolling: touch;\\r\\n\\r\\n    div {\\r\\n        background: #fff;\\r\\n        padding: 15px;\\r\\n        margin: 3px;\\r\\n        cursor: pointer;\\r\\n\\r\\n        &:hover {\\r\\n            background: #fefefe;\\r\\n        }\\r\\n    }\\r\\n}\\r\\n\\r\\nh4 span {\\r\\n  font-weight: normal;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `form-input-bool .answer-val {\n  padding-right: 70px;\n}\nform-input-bool .answer-disabled {\n  background-color: rgb(235, 235, 228);\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-input-bool/form-input-bool.scss\"],\"names\":[],\"mappings\":\"AACE;EACE,mBAAA;AAAJ;AAGE;EACE,oCAAA;AADJ\",\"sourcesContent\":[\"form-input-bool {\\r\\n  .answer-val {\\r\\n    padding-right: 70px;\\r\\n  }\\r\\n\\r\\n  .answer-disabled {\\r\\n    background-color: rgb(235, 235, 228)\\r\\n  }\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `input[type=file] {\n  width: 0;\n  height: 1px;\n}\n\n.existing-files {\n  overflow: auto;\n  overflow-y: hidden;\n  overflow-x: auto;\n  white-space: nowrap;\n  -webkit-overflow-scrolling: touch;\n}\n.existing-files .no-results {\n  font-size: 0.9em;\n  margin-top: 10px;\n}\n\n.filebox {\n  cursor: pointer;\n  display: inline-block;\n  position: relative;\n  width: 90px;\n  height: 90px;\n  background: #fff;\n  border: solid 1px #ccc;\n  border-radius: 5px;\n  margin: 5px 5px 5px 0;\n}\n.filebox .file-icon {\n  font-size: 2em;\n  color: #eee;\n  position: absolute;\n  top: 25px;\n  left: 0;\n  right: 0;\n  text-align: center;\n}\n.filebox .download-icon, .filebox .remove-icon, .filebox .select-icon {\n  font-size: 1.3em;\n  color: #fff;\n  position: absolute;\n  top: 5px;\n  right: 5px;\n}\n.filebox .download-icon {\n  left: 5px;\n  right: auto;\n}\n.filebox .filename {\n  position: absolute;\n  font-size: 0.8em;\n  line-height: 1.1em;\n  bottom: 5px;\n  left: 5px;\n  right: 5px;\n  max-height: 56px;\n  overflow: hidden;\n  white-space: pre-wrap; /* CSS3 */\n  white-space: -moz-pre-wrap; /* Firefox */\n  white-space: -pre-wrap; /* Opera <7 */\n  white-space: -o-pre-wrap; /* Opera 7 */\n  word-wrap: break-word; /* IE */\n}\n.filebox:hover {\n  background: #ddd;\n}\n\n.upload-indicator {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  background: rgba(0, 255, 0, 0.2);\n}\n\n.dropzone {\n  background: #fff;\n  border: dotted 2px #ccc;\n  border-radius: 5px;\n  text-align: center;\n  padding: 30px 0;\n  margin: 15px 0;\n}\n.dropzone small {\n  pointer-events: none;\n}\n.dropzone form-button.secondary button {\n  margin-top: 8px;\n  padding-left: 0;\n  padding-right: 0;\n}\n.dropzone form-button.secondary button label {\n  padding: 14px 25px 14px 15px;\n  cursor: pointer;\n}\n.dropzone label form-button span {\n  padding: 14px 25px 14px 15px;\n}\n.dropzone.dragover {\n  background: #efefef;\n}\n.dropzone.dragover form-button {\n  pointer-events: none;\n}\n.dropzone.dragover form-button button {\n  background: #efefef;\n  opacity: 0.5;\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-input-file/form-input-file.scss\"],\"names\":[],\"mappings\":\"AAAA;EACI,QAAA;EACA,WAAA;AACJ;;AAEA;EACI,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,mBAAA;EACA,iCAAA;AACJ;AACI;EACI,gBAAA;EACA,gBAAA;AACR;;AAGA;EACI,eAAA;EACA,qBAAA;EACA,kBAAA;EACA,WAAA;EACA,YAAA;EACA,gBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;AAAJ;AAEI;EACI,cAAA;EACA,WAAA;EACA,kBAAA;EACA,SAAA;EACA,OAAA;EACA,QAAA;EACA,kBAAA;AAAR;AAGI;EACI,gBAAA;EACA,WAAA;EACA,kBAAA;EACA,QAAA;EACA,UAAA;AADR;AAII;EACI,SAAA;EACA,WAAA;AAFR;AAKI;EACI,kBAAA;EACA,gBAAA;EACA,kBAAA;EACA,WAAA;EACA,SAAA;EACA,UAAA;EACA,gBAAA;EACA,gBAAA;EACA,qBAAA,EAAA,SAAA;EACA,0BAAA,EAAA,YAAA;EACA,sBAAA,EAAA,aAAA;EACA,wBAAA,EAAA,YAAA;EACA,qBAAA,EAAA,OAAA;AAHR;AAMI;EACI,gBAAA;AAJR;;AAQA;EACI,kBAAA;EACA,MAAA;EACA,SAAA;EACA,OAAA;EACA,gCAAA;AALJ;;AAQA;EACI,gBAAA;EACA,uBAAA;EACA,kBAAA;EACA,kBAAA;EACA,eAAA;EACA,cAAA;AALJ;AAOI;EACI,oBAAA;AALR;AAQI;EACI,eAAA;EACA,eAAA;EACA,gBAAA;AANR;AAQQ;EACI,4BAAA;EACA,eAAA;AANZ;AAYY;EACI,4BAAA;AAVhB;AAeI;EACI,mBAAA;AAbR;AAeQ;EACI,oBAAA;AAbZ;AAeY;EACI,mBAAA;EACA,YAAA;AAbhB\",\"sourcesContent\":[\"input[type=\\\"file\\\"] {\\r\\n    width: 0;\\r\\n    height: 1px;\\r\\n}\\r\\n\\r\\n.existing-files {\\r\\n    overflow: auto;\\r\\n    overflow-y: hidden;\\r\\n    overflow-x: auto;\\r\\n    white-space: nowrap;\\r\\n    -webkit-overflow-scrolling: touch;\\r\\n\\r\\n    .no-results {\\r\\n        font-size: 0.9em;\\r\\n        margin-top: 10px;\\r\\n    }\\r\\n}\\r\\n\\r\\n.filebox {\\r\\n    cursor: pointer;\\r\\n    display: inline-block;\\r\\n    position: relative;\\r\\n    width: 90px;\\r\\n    height: 90px;\\r\\n    background: #fff;\\r\\n    border: solid 1px #ccc;\\r\\n    border-radius: 5px;\\r\\n    margin: 5px 5px 5px 0;\\r\\n\\r\\n    .file-icon {\\r\\n        font-size: 2em;\\r\\n        color: #eee;\\r\\n        position: absolute;\\r\\n        top: 25px;\\r\\n        left: 0;\\r\\n        right: 0;\\r\\n        text-align: center;\\r\\n    }\\r\\n\\r\\n    .download-icon, .remove-icon, .select-icon {\\r\\n        font-size: 1.3em;\\r\\n        color: #fff;\\r\\n        position: absolute;\\r\\n        top: 5px;\\r\\n        right: 5px;\\r\\n    }\\r\\n\\r\\n    .download-icon {\\r\\n        left: 5px;\\r\\n        right: auto;\\r\\n    }\\r\\n\\r\\n    .filename {\\r\\n        position: absolute;\\r\\n        font-size: 0.8em;\\r\\n        line-height: 1.1em;\\r\\n        bottom: 5px;\\r\\n        left: 5px;\\r\\n        right: 5px;\\r\\n        max-height: 56px;\\r\\n        overflow: hidden;\\r\\n        white-space: pre-wrap;      /* CSS3 */\\r\\n        white-space: -moz-pre-wrap; /* Firefox */\\r\\n        white-space: -pre-wrap;     /* Opera <7 */\\r\\n        white-space: -o-pre-wrap;   /* Opera 7 */\\r\\n        word-wrap: break-word;      /* IE */\\r\\n    }\\r\\n\\r\\n    &:hover {\\r\\n        background: #ddd;\\r\\n    }\\r\\n}\\r\\n\\r\\n.upload-indicator {\\r\\n    position: absolute;\\r\\n    top:0;\\r\\n    bottom:0;\\r\\n    left:0;\\r\\n    background: rgba(0,255,0,0.2);\\r\\n}\\r\\n\\r\\n.dropzone {\\r\\n    background: #fff;\\r\\n    border: dotted 2px #ccc;\\r\\n    border-radius: 5px;\\r\\n    text-align: center;\\r\\n    padding: 30px 0;\\r\\n    margin: 15px 0;\\r\\n\\r\\n    small {\\r\\n        pointer-events: none;\\r\\n    }\\r\\n\\r\\n    form-button.secondary button {\\r\\n        margin-top: 8px;\\r\\n        padding-left: 0;\\r\\n        padding-right: 0;\\r\\n        \\r\\n        label {\\r\\n            padding: 14px 25px 14px 15px;\\r\\n            cursor: pointer;\\r\\n        }\\r\\n    }\\r\\n\\r\\n    label {\\r\\n        form-button {\\r\\n            span {\\r\\n                padding: 14px 25px 14px 15px;\\r\\n            }\\r\\n        }\\r\\n    }\\r\\n\\r\\n    &.dragover {\\r\\n        background: #efefef;\\r\\n\\r\\n        form-button {\\r\\n            pointer-events: none;\\r\\n\\r\\n            button {\\r\\n                background: #efefef;\\r\\n                opacity: 0.5;\\r\\n            }\\r\\n        }\\r\\n    }\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `form-input-multiple .answer-val {\n  padding-right: 70px;\n}\nform-input-multiple .answer-val a.change {\n  margin-right: -55px;\n}\nform-input-multiple .answer-disabled {\n  background-color: rgb(235, 235, 228);\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-input-multiple/form-input-multiple.scss\"],\"names\":[],\"mappings\":\"AACE;EACE,mBAAA;AAAJ;AAEI;EACE,mBAAA;AAAN;AAME;EACE,oCAH6B;AADjC\",\"sourcesContent\":[\"form-input-multiple {\\r\\n  .answer-val {\\r\\n    padding-right: 70px;\\r\\n\\r\\n    a.change {\\r\\n      margin-right: -55px;\\r\\n    }\\r\\n  }\\r\\n\\r\\n  $form-input-multiple-bg-color: rgb(235, 235, 228);\\r\\n\\r\\n  .answer-disabled {\\r\\n    background-color: $form-input-multiple-bg-color\\r\\n  }\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `form-input-radio .answer-val {\n  padding-right: 70px;\n}\nform-input-radio .answer-val a.change {\n  margin-right: -55px;\n}\nform-input-radio .answer-disabled {\n  background-color: rgb(235, 235, 228);\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-input-radio/form-input-radio.scss\"],\"names\":[],\"mappings\":\"AACE;EACE,mBAAA;AAAJ;AAEI;EACE,mBAAA;AAAN;AAIE;EACE,oCAAA;AAFJ\",\"sourcesContent\":[\"form-input-radio {\\r\\n  .answer-val {\\r\\n    padding-right: 70px;\\r\\n\\r\\n    a.change {\\r\\n      margin-right: -55px;\\r\\n    }\\r\\n  }\\r\\n\\r\\n  .answer-disabled {\\r\\n    background-color: rgb(235, 235, 228)\\r\\n  }\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `input[type=text].tel {\n  display: inline-block;\n  width: calc(50% - 14px);\n}\n\nselect.tel {\n  display: inline-block;\n  width: 50%;\n  margin-right: 9px;\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/resources/elements/form-input-telephone/form-input-telephone.scss\"],\"names\":[],\"mappings\":\"AAAA;EACI,qBAAA;EACA,uBAAA;AACJ;;AACA;EACI,qBAAA;EACA,UAAA;EACA,iBAAA;AAEJ\",\"sourcesContent\":[\"input[type=\\\"text\\\"].tel {\\r\\n    display: inline-block;\\r\\n    width:calc(50% - 14px);\\r\\n}\\r\\nselect.tel {\\r\\n    display: inline-block;\\r\\n    width:50%;\\r\\n    margin-right: 9px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, ``, \"\",{\"version\":3,\"sources\":[],\"names\":[],\"mappings\":\"\",\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Module\nvar code = \"<template>\\r\\n    <ux-dialog>\\r\\n      <ux-dialog-body>\\r\\n        <h3>${title}</h3>\\r\\n        <crisp-input-radio yes-no-items.bind=\\\"true\\\" class=\\\"form-bool\\\" value.bind=\\\"sharedComputer\\\"></crisp-input-radio>\\r\\n      </ux-dialog-body>\\r\\n    </ux-dialog>\\r\\n  </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <div class=\\\"${enabled ? '' : 'disabled'}\\\">\\r\\n        <label if.bind=\\\"label\\\">${label}</label>\\r\\n        <ul>\\r\\n            <li name.bind=\\\"id\\\" repeat.for=\\\"option of radioOptions\\\">\\r\\n                <input class=\\\"with-gap\\\" name.bind=\\\"id\\\" type=\\\"radio\\\" id.bind=\\\"option.id\\\" model.bind=\\\"option\\\" checked.bind=\\\"$parent.selected\\\" disabled.bind=\\\"!enabled\\\" />\\r\\n                <label for.bind=\\\"option.id\\\" class=\\\"answer\\\">${option.label}</label>\\r\\n            </li>\\r\\n        </ul>\\r\\n        <span class=\\\"error\\\">${error}</span>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template class=\\\"${!!enabled ? '' : 'disabled'}\\\">\\r\\n    <div id.bind=\\\"id\\\" class=\\\"input-field ${!error ? '' : 'invalid'}\\\">\\r\\n      <select ref=\\\"select\\\" multiple.bind=\\\"multiple\\\" disabled.bind=\\\"!enabled\\\" >\\r\\n        <option repeat.for=\\\"item of items\\\" value.bind=\\\"getId(item)\\\">${getDescription(item)}</option>  \\r\\n      </select>\\r\\n      <label>${label}</label>\\r\\n      <i if.bind=\\\"showClear\\\" class=\\\"fa fa-times action clear\\\" click.delegate=\\\"clear()\\\"></i>\\r\\n      <i class=\\\"fa fa-angle-down down\\\"></i>\\r\\n      <span class=\\\"error\\\">${error}</span>\\r\\n    </div>\\r\\n</template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n <i class=\\\"icon-${icon}\\\"></i>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n  <require from=\\\"./form-button.scss\\\"></require>\\r\\n  <button disabled.bind=\\\"disabled\\\" click.delegate=\\\"clicked()\\\" class=\\\"${icon ? 'with-icon' : ''}\\\">\\r\\n    <div if.bind=\\\"icon\\\" class=\\\"icon-ctr\\\">\\r\\n      <ex-icon icon.bind=\\\"icon\\\"></ex-icon>\\r\\n    </div>\\r\\n    <span>${label}</span>\\r\\n    <slot></slot>\\r\\n  </button>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <require from=\\\"./form-input-address.scss\\\"></require>\\r\\n\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <h4>${label}<span if.bind=\\\"!addressRequired\\\"> (optional)</span></h4>\\r\\n        </div>\\r\\n        <div if.bind=\\\"addressConfirmed\\\" class=\\\"form-col\\\">\\r\\n            <p>\\r\\n                <span if.bind=\\\"value.address1\\\">${value.address1}<br/></span>\\r\\n                <span if.bind=\\\"value.address2\\\">${value.address2}<br/></span>\\r\\n                <span if.bind=\\\"value.address3\\\">${value.address3}<br/></span>\\r\\n                <span if.bind=\\\"value.town\\\">${value.town}<br/></span>\\r\\n                <span if.bind=\\\"value.postcode\\\">${value.postcode}<br/></span>\\r\\n                <span if.bind=\\\"value.country\\\">${getCountryCodeDescription(value.country)}</span>\\r\\n            </p>\\r\\n            <p if.bind=\\\"!disabled\\\"><a class=\\\"help-link\\\" tabindex=\\\"0\\\" click.delegate=\\\"addressConfirmed = false\\\" keydown.delegate=\\\"changeAddressKeydown($event)\\\">Change address</a></p>\\r\\n        </div>\\r\\n        <div if.bind=\\\"!addressConfirmed && disabled\\\">\\r\\n          <p>Not Set</p>\\r\\n        </div>\\r\\n        <div if.bind=\\\"!addressConfirmed && !!sameAs\\\" class=\\\"form-col\\\">\\r\\n            <form-button if.bind=\\\"!!sameAs.postcode && !addressConfirmed\\\" label.bind=\\\"sameAsText\\\" class=\\\"secondary\\\" click.delegate=\\\"setAddressToSameAs()\\\"></form-button>\\r\\n        </div>\\r\\n    </div>\\r\\n\\r\\n    <div if.bind=\\\"!addressConfirmed && !disabled\\\">\\r\\n        <div if.bind=\\\"!manual\\\">\\r\\n            <form-input-text label=\\\"Postcode\\\" value.bind=\\\"lookupPostcode & validate\\\" delay-validation.bind=\\\"true\\\"></form-input-text>\\r\\n            <div class=\\\"form-row\\\">\\r\\n                <div class=\\\"form-col\\\">\\r\\n                    <p if.bind=\\\"searchResults.length && !noResults\\\">Select an address below</p>\\r\\n                    <div class=\\\"validation-msg\\\" if.bind=\\\"noResults\\\">No addresses found</div>\\r\\n                </div>\\r\\n                <div class=\\\"form-col\\\">\\r\\n                    <a class=\\\"help-link\\\" tabindex=\\\"0\\\" click.delegate=\\\"reset(true)\\\" keydown.delegate=\\\"enterManuallyKeydown($event)\\\">Enter address manually</a>\\r\\n                </div>\\r\\n            </div>\\r\\n            <div class=\\\"centre\\\">\\r\\n                <ex-loader if.bind=\\\"searching\\\"></ex-loader>\\r\\n            </div>\\r\\n            <div if.bind=\\\"searchResults.length\\\" class=\\\"search-results\\\">\\r\\n                <div repeat.for=\\\"address of searchResults\\\" tabindex=\\\"0\\\" click.delegate=\\\"selectAddress(address)\\\" keyup.trigger=\\\"searchResultKeyup($event, address)\\\">\\r\\n                    ${getAddressString(address)}\\r\\n                </div>\\r\\n            </div>\\r\\n        </div>\\r\\n\\r\\n        <div if.bind=\\\"manual\\\">\\r\\n            <div class=\\\"form-row\\\">\\r\\n                <div class=\\\"form-col\\\">\\r\\n                    <a class=\\\"help-link\\\" tabindex=\\\"0\\\" click.delegate=\\\"manual = false\\\" keydown.delegate=\\\"searchByPostcodeKeydown($event)\\\">Search by postcode</a>\\r\\n                </div>\\r\\n                <div class=\\\"form-col\\\">\\r\\n                </div>\\r\\n            </div>\\r\\n\\r\\n            <form-input-text view-model.ref=\\\"address1VM\\\" label=\\\"Address line 1\\\" value.bind=\\\"value.address1 & validate\\\"></form-input-text>\\r\\n            <form-input-text label=\\\"Address line 2\\\" value.bind=\\\"value.address2 & validate\\\"></form-input-text>\\r\\n            <form-input-text label=\\\"Address line 3\\\" value.bind=\\\"value.address3 & validate\\\"></form-input-text>\\r\\n            <form-input-text view-model.ref=\\\"townVM\\\" label=\\\"Town\\\" value.bind=\\\"value.town & validate\\\"></form-input-text>\\r\\n            <form-input-text view-model.ref=\\\"postcodeVM\\\" label=\\\"Postcode\\\" value.bind=\\\"value.postcode & validate\\\" delay-validation.bind=\\\"true\\\"></form-input-text>\\r\\n            <form-input-country view-model.ref=\\\"countryVM\\\" label=\\\"Country\\\" value.bind=\\\"value.country & validate\\\" delay-validation.bind=\\\"true\\\"></form-input-country>\\r\\n\\r\\n            <div class=\\\"form-row\\\">\\r\\n                <div class=\\\"form-col\\\">\\r\\n                </div>\\r\\n                <div class=\\\"form-col\\\">\\r\\n                    <form-button label=\\\"Confirm Address\\\" icon=\\\"check\\\" click.delegate=\\\"confirmAddress()\\\" class=\\\"small\\\"></form-button>\\r\\n                </div>\\r\\n            </div>\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n  <require from=\\\"./form-input-bool.scss\\\"></require>\\r\\n  <div class=\\\"form-row\\\">\\r\\n    <div class=\\\"form-col ${!!showValidationErrors ? 'invalid' : ''}\\\">\\r\\n      <p>${label}</p>\\r\\n      <p if.bind=\\\"subtitle\\\" class=\\\"subtitle\\\">${subtitle}</p>\\r\\n      <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n      <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n    </div>\\r\\n    <div class=\\\"form-col\\\">\\r\\n      <crisp-input-radio if.bind=\\\"!disabled\\\" yes-no-items.bind=\\\"true\\\" class=\\\"form-bool\\\" value.bind=\\\"value\\\"></crisp-input-radio>\\r\\n      <div if.bind=\\\"disabled\\\" class=\\\"answer-val answer-disabled\\\">\\r\\n        <span>${value === true ? 'Yes' : value === false ? 'No' : 'Not Set'}</span>\\r\\n      </div>\\r\\n      <p if.bind=\\\"showNote\\\" class=\\\"note small bold\\\">${note}</p>\\r\\n    </div>\\r\\n  </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <form-input-radio label.bind=\\\"contactTypeLabel\\\" value.bind=\\\"value.contactType & validate\\\" options.bind=\\\"['Company','Private Individual']\\\" disabled.bind=\\\"disabled\\\"></form-input-radio>\\r\\n    \\r\\n    <form-input-text if.bind=\\\"value.contactType === 'Company'\\\" label=\\\"Company Name\\\" value.bind=\\\"value.companyName & validate\\\" placeholder=\\\"e.g. My Company Ltd\\\" disabled.bind=\\\"disabled\\\"></form-input-text>\\r\\n    <form-input-radio if.bind=\\\"reporter || (representative && !!value.contactType) || value.contactType === 'Private Individual'\\\" label=\\\"Title\\\" value.bind=\\\"value.title & validate\\\" options.bind=\\\"titles\\\" dual.bind=\\\"true\\\" disabled.bind=\\\"disabled\\\"></form-input-radio>\\r\\n    <form-input-text if.bind=\\\"(reporter || (representative && !!value.contactType) || value.contactType === 'Private Individual') && value.title === 'Other'\\\" label=\\\"Title (other)\\\" value.bind=\\\"value.titleOther & validate\\\" placeholder=\\\"e.g. Capt\\\" disabled.bind=\\\"disabled\\\"></form-input-text>\\r\\n    <form-input-text if.bind=\\\"reporter || (representative && !!value.contactType) || value.contactType === 'Private Individual'\\\" label=\\\"First name\\\" value.bind=\\\"value.firstname & validate\\\" placeholder=\\\"e.g. John\\\" disabled.bind=\\\"disabled\\\"></form-input-text>\\r\\n    <form-input-text if.bind=\\\"reporter || (representative && !!value.contactType) || value.contactType === 'Private Individual'\\\" label=\\\"Surname\\\" value.bind=\\\"value.surname & validate\\\" placeholder=\\\"e.g. Smith\\\" disabled.bind=\\\"disabled\\\"></form-input-text>\\r\\n    \\r\\n    <form-input-telephone if.bind=\\\"reporter || !!value.contactType\\\" label=\\\"${contactNumberLabel}${ value.telephoneRequired ? '' : ' (optional)'}\\\"\\r\\n        value.bind=\\\"value.telephone & validate\\\" country-code.bind=\\\"value.telephoneCountryCode & validate\\\" delay-validation.bind=\\\"true\\\" disabled.bind=\\\"disabled\\\"></form-input-telephone>\\r\\n\\r\\n    <form-input-radio if.bind=\\\"reporter && user.isAdmin\\\" label=\\\"How do you want us to send the written documentation to you?\\\" value.bind=\\\"value.correspondenceMethod & validate\\\" options.bind=\\\"['Email','Post']\\\" disabled.bind=\\\"disabled\\\"></form-input-radio>\\r\\n    <div if.bind=\\\"reporter && user.isAdmin && value.correspondenceMethod === 'Post'\\\" class=\\\"sub-section\\\">\\r\\n        <form-input-address label=\\\"Postal address\\\" value.bind=\\\"value.address & validate\\\" disabled.bind=\\\"disabled\\\"></form-input-address>\\r\\n    </div>\\r\\n\\r\\n    <form-input-text if.bind=\\\"(reporter || !!value.contactType) && value.correspondenceMethod !== 'Post'\\\" label=\\\"Email address${ value.emailRequired ? '' : ' (optional)'}\\\" value.bind=\\\"value.email & validate\\\"\\r\\n        delay-validation.bind=\\\"true\\\" placeholder=\\\"e.g. my@email.com\\\" prevent-space.bind=\\\"true\\\" disabled.bind=\\\"(reporter && saved) || disabled\\\"></form-input-text>\\r\\n\\r\\n    <form-input-text if.bind=\\\"reporter && value.correspondenceMethod !== 'Post'\\\" label=\\\"Confirm Email address\\\" value.bind=\\\"value.emailConfirmation & validate\\\"\\r\\n        delay-validation.bind=\\\"true\\\" placeholder=\\\"e.g. my@email.com\\\" disable-paste.bind=\\\"true\\\" prevent-space.bind=\\\"true\\\" disabled.bind=\\\"(reporter && saved) || disabled\\\"></form-input-text>\\r\\n\\r\\n    <form-input-bool if.bind=\\\"reporter\\\" label=\\\"Are you the owner of the insured property?\\\" value.bind=\\\"value.isLeadClaimant & validate\\\" disabled.bind=\\\"disabled\\\"\\r\\n        help-text=\\\"Owner refers to Policyholder. Please refer to your policy for the full definition of Policyholder\\\"></form-input-bool>\\r\\n\\r\\n    <div if.bind=\\\"captureRelationship && (!reporter || value.isLeadClaimant === false)\\\" class=\\\"au-animate slide-down\\\">\\r\\n        <form-input-radio if.bind=\\\"reporter || !!value.contactType\\\" label=\\\"What is ${ reporter ? 'your' : 'their' } relationship to the policyholder?\\\"\\r\\n            value.bind=\\\"value.relationshipToLeadClaimant & validate\\\" options.bind=\\\"additionalPolicyholder ? additionalPolicyholderRelationships : representative ? representativeRelationships : relationships\\\" disabled.bind=\\\"disabled\\\"></form-input-radio>\\r\\n\\r\\n        <form-input-radio if.bind=\\\"value.relationshipToLeadClaimant === 'Family Member'\\\"\\r\\n            label=\\\"Family member relationship\\\" value.bind=\\\"value.relationshipToLeadClaimantFamilyMember & validate\\\" options.bind=\\\"familyRelationships\\\" disabled.bind=\\\"disabled\\\"></form-input-radio>\\r\\n\\r\\n        <form-input-text if.bind=\\\"(value.relationshipToLeadClaimant === 'Family Member' && value.relationshipToLeadClaimantFamilyMember === 'Other') || value.relationshipToLeadClaimant === 'Other family member'\\\"\\r\\n            label=\\\"Other\\\" value.bind=\\\"value.relationshipToLeadClaimantFamilyMemberOther & validate\\\" placeholder=\\\"e.g. Cousin\\\" disabled.bind=\\\"disabled\\\"></form-input-text>\\r\\n\\r\\n        <form-input-text if.bind=\\\"value.relationshipToLeadClaimant === 'Other'\\\"\\r\\n            label=\\\"Other relationship\\\" value.bind=\\\"value.relationshipToLeadClaimantOther & validate\\\" placeholder=\\\"e.g. Landlord\\\" disabled.bind=\\\"disabled\\\"></form-input-text>\\r\\n    </div>\\r\\n\\r\\n    <form-input-address view-model.ref=\\\"addressVM\\\" if.bind=\\\"captureAddress && !!value.contactType\\\"\\r\\n        label=\\\"Correspondence address\\\" value.bind=\\\"value.address & validate\\\" disabled.bind=\\\"disabled\\\"\\r\\n        address-required.bind=\\\"value.addressRequired\\\"></form-input-address>\\r\\n\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col ${!!showValidationErrors ? 'invalid' : ''}\\\">\\r\\n            <p><label for=\\\"${fieldName}\\\">${label}</label></p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <label for=\\\"${fieldName}_cp\\\" class=\\\"hidden-label\\\">Country</label>\\r\\n            <select id=\\\"${fieldName}_cp\\\" ref=\\\"select\\\" class=\\\"answer ${disabled ? 'inactive' : ''}\\\" value.bind=\\\"value\\\" disabled.bind=\\\"disabled\\\">\\r\\n                <option repeat.for=\\\"item of countryCodes\\\" model.bind=\\\"item.id\\\">${item.description}</option>\\r\\n            </select>\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col ${!!showValidationErrors ? 'invalid' : ''}\\\">\\r\\n            <p>${label}</p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <label if.bind=\\\"showDay\\\" for=\\\"${fieldName}_d\\\" class=\\\"hidden-label\\\">Day</label>\\r\\n            <input if.bind=\\\"showDay\\\" type=\\\"text\\\" id=\\\"${fieldName}_d\\\" name=\\\"${fieldName}_d\\\" value.bind=\\\"day\\\" placeholder=\\\"day\\\" class=\\\"date-input day ${!!showValidationErrors ? 'invalid' : ''}\\\" maxlength=\\\"2\\\" keydown.delegate=\\\"onKeydown($event)\\\" disabled.bind=\\\"disabled\\\" />\\r\\n            <span if.bind=\\\"showDay\\\">/</span if.bind=\\\"showDay\\\">\\r\\n            <label for=\\\"${fieldName}_m\\\" class=\\\"hidden-label\\\">Month</label>\\r\\n            <input type=\\\"text\\\" id=\\\"${fieldName}_m\\\" name=\\\"${fieldName}_m\\\" value.bind=\\\"month\\\" placeholder=\\\"month\\\" class=\\\"date-input month ${!!showValidationErrors ? 'invalid' : ''}\\\" maxlength=\\\"2\\\" focus.bind=\\\"focusMonth\\\" keydown.delegate=\\\"onKeydown($event)\\\" disabled.bind=\\\"disabled\\\" />\\r\\n            <span>/</span>\\r\\n            <label for=\\\"${fieldName}_y\\\" class=\\\"hidden-label\\\">Year</label>\\r\\n            <input element.ref=\\\"yearElement\\\" type=\\\"text\\\" id=\\\"${fieldName}_y\\\" name=\\\"${fieldName}_y\\\" value.bind=\\\"year\\\" placeholder=\\\"year\\\" class=\\\"date-input year ${!!showValidationErrors ? 'invalid' : ''}\\\" maxlength=\\\"4\\\" focus.bind=\\\"focusYear\\\" blur.trigger=\\\"markVisited()\\\" keydown.delegate=\\\"onKeydown($event)\\\" disabled.bind=\\\"disabled\\\" />\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <require from=\\\"./form-input-file.scss\\\"></require>\\r\\n\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col ${showValidationErrors ? 'invalid' : ''}\\\">\\r\\n            <p>${label}</p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <div class=\\\"selected-files\\\">\\r\\n                <div repeat.for=\\\"doc of value\\\" class=\\\"filebox\\\" click.delegate=\\\"download(doc)\\\">\\r\\n                    <ex-icon if.bind=\\\"doc.fileId\\\" class=\\\"download-icon\\\" icon=\\\"download\\\"></ex-icon>\\r\\n                    <ex-icon if.bind=\\\"doc.fileId && !disabled\\\" class=\\\"remove-icon\\\" icon=\\\"delete_forever\\\" click.delegate=\\\"remove($event, doc)\\\"></ex-icon>\\r\\n                    <ex-icon class=\\\"file-icon\\\" icon.bind=\\\"getFileIcon(doc)\\\"></ex-icon>\\r\\n                    <span class=\\\"filename\\\">${doc.fileName}</span>\\r\\n                    <div if.bind=\\\"!doc.fileId\\\" class=\\\"upload-indicator\\\" style.bind=\\\"`width: ${doc.percentUploaded}%;`\\\"></div>\\r\\n                </div>\\r\\n            </div>\\r\\n            <div if.bind=\\\"!disabled\\\">\\r\\n              <div class=\\\"dropzone ${dragOver ? 'dragover' : ''}\\\" dragenter.trigger=\\\"onDragOver($event)\\\" dragover.trigger=\\\"onDragOver($event)\\\" dragleave.trigger=\\\"onDragLeave($event)\\\" drop.trigger=\\\"onDrop($event)\\\">\\r\\n                <small>Drag and drop files here or</small><br />\\r\\n                <input id=\\\"${fieldName}\\\" name=\\\"${fieldName}\\\" type=\\\"file\\\" multiple files.bind=\\\"fileInputFiles\\\" value.bind=\\\"fileInputValue\\\" accept.bind=\\\"acceptedFileTypes\\\" change.delegate=\\\"fileInputFilesChanged()\\\" />\\r\\n                \\r\\n                <form-button class=\\\"small secondary\\\" icon=\\\"upload\\\" click-action.call=\\\"callUploadDialog()\\\">\\r\\n                  <label for=\\\"${fieldName}\\\">Upload a file</label>\\r\\n                </form-button>\\r\\n\\r\\n              </div>\\r\\n              <div if.bind=\\\"!!fileSelectionError\\\" class=\\\"validation-msg\\\">${fileSelectionError}</div>\\r\\n              <div if.bind=\\\"anyExistingFiles\\\" class=\\\"right\\\">\\r\\n                <a class=\\\"help-link\\\" tabindex=\\\"0\\\" click.delegate=\\\"showExisting = !showExisting\\\" keydown.delegate=\\\"toggleExistingKeydown($event)\\\">${showExisting ? 'Hide existing files' : 'Select an existing file'}</a>\\r\\n              </div>\\r\\n              <div if.bind=\\\"anyExistingFiles && showExisting\\\" class=\\\"au-animate slide-down\\\">\\r\\n                <p>Select an existing file...</p>\\r\\n                <input type=\\\"text\\\" value.bind=\\\"searchText\\\" placeholder=\\\"Search\\\" />\\r\\n                <div class=\\\"existing-files\\\">\\r\\n                  <div if.bind=\\\"showNoSearchResults\\\" class=\\\"no-results\\\">No results...</div>\\r\\n                  <div repeat.for=\\\"doc of existingFiles | filter: { selectedItems: value, search: searchText} & signal:'refresh-existing'\\\" class=\\\"filebox\\\" click.delegate=\\\"selectExisting(doc)\\\">\\r\\n                    <ex-icon class=\\\"select-icon\\\" icon=\\\"check_circle\\\"></ex-icon>\\r\\n                    <ex-icon class=\\\"file-icon\\\" icon.bind=\\\"getFileIcon(doc)\\\"></ex-icon>\\r\\n                    <span class=\\\"filename\\\">${doc.fileName}</span>\\r\\n                  </div>\\r\\n                </div>\\r\\n              </div>\\r\\n            </div>\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n  <require from=\\\"./form-input-multiple.scss\\\"></require>\\r\\n\\r\\n  <div class=\\\"form-row\\\" element.ref=\\\"elem\\\">\\r\\n    <div class=\\\"form-col ${showValidationErrors ? 'invalid' : ''}\\\">\\r\\n      <p>${label}</p>\\r\\n      <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n      <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n    </div>\\r\\n    <div class=\\\"form-col\\\">\\r\\n      <div class=\\\"${enabled ? '' : 'disabled'}\\\">\\r\\n        <div name.bind=\\\"id\\\" repeat.for=\\\"option of options\\\">\\r\\n          <input-checkbox \\r\\n                          disabled.bind=\\\"disabled\\\"\\r\\n                          label.bind=\\\"option\\\"\\r\\n                          value.bind=\\\"values[option]\\\"></input-checkbox>\\r\\n        </div>\\r\\n        <span class=\\\"error\\\">${error}</span>\\r\\n      </div>\\r\\n    </div>\\r\\n  </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <require from=\\\"./form-input-radio.scss\\\"></require>\\r\\n\\r\\n    <div class=\\\"form-row\\\" element.ref=\\\"elem\\\">\\r\\n        <div class=\\\"form-col ${showValidationErrors ? 'invalid' : ''}\\\">\\r\\n            <p>${label}</p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <crisp-input-radio \\r\\n                               if.bind=\\\"!value && !disabled\\\" \\r\\n                               class=\\\"au-animate slide-down ${dual ? 'form-bool' : ''}\\\" \\r\\n                               value.bind=\\\"value\\\" \\r\\n                               items.bind=\\\"options\\\"\\r\\n                               enabled.bind=\\\"!disabled\\\"></crisp-input-radio>\\r\\n            <div if.bind=\\\"!!value || disabled\\\" class=\\\"answer-val ${disabled ? 'answer-disabled' : ''}\\\">\\r\\n                <span>${value || 'Not Set'}</span>\\r\\n                <a tabindex=\\\"0\\\" if.bind=\\\"!disabled\\\" class=\\\"change\\\" click.delegate=\\\"value = ''\\\" keydown.delegate=\\\"changeKeydown($event)\\\">change</a>\\r\\n            </div>\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <p>${label}</p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <div class=\\\"answer-val ${disabled ? 'inactive' : ''}\\\">\\r\\n                <span>${value}</span>\\r\\n            </div>\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <require from=\\\"./form-input-telephone.scss\\\"></require>\\r\\n\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col ${!!showValidationErrors ? 'invalid' : ''}\\\">\\r\\n            <p><label for=\\\"${fieldName}\\\">${label}</label></p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <label for=\\\"${fieldName}_cp\\\" class=\\\"hidden-label\\\">Telephone Country</label>\\r\\n            <select id=\\\"${fieldName}_cp\\\" ref=\\\"select\\\" class=\\\"tel answer ${disabled ? 'inactive' : ''}\\\" value.bind=\\\"countryCode\\\" disabled.bind=\\\"disabled\\\">\\r\\n                <option repeat.for=\\\"item of countryCodes\\\" model.bind=\\\"item.id\\\">${item.description}</option>\\r\\n            </select>\\r\\n\\r\\n            <input id=\\\"${fieldName}\\\" class=\\\"tel\\\" type=\\\"text\\\" name=\\\"${fieldName}\\\" blur.trigger=\\\"markVisited()\\\" value.bind=\\\"value\\\" placeholder.bind=\\\"placeholder\\\"\\r\\n                class=\\\"${!!showValidationErrors ? 'invalid' : ''}\\\" keydown.delegate=\\\"onKeydown($event)\\\" disabled.bind=\\\"disabled\\\" />\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n    <div class=\\\"form-row\\\">\\r\\n        <div class=\\\"form-col ${!!showValidationErrors ? 'invalid' : ''}\\\">\\r\\n            <p><label for=\\\"${fieldName}\\\">${label}</label></p>\\r\\n            <help-text help-text.bind=\\\"helpText\\\" help-title.bind=\\\"helpTitle\\\" hide-help-title.bind=\\\"hideHelpTitle\\\"></help-text>\\r\\n            <div if.bind=\\\"showValidationErrors\\\" repeat.for=\\\"msg of validationMessages\\\" class=\\\"validation-msg\\\">${msg}</div>\\r\\n        </div>\\r\\n        <div class=\\\"form-col\\\">\\r\\n            <input if.bind=\\\"!multiline\\\" type=\\\"text\\\" id=\\\"${fieldName}\\\" name=\\\"${fieldName}\\\" blur.trigger=\\\"markVisited()\\\" value.bind=\\\"value\\\" placeholder.bind=\\\"placeholderText\\\" paste.delegate=\\\"onPaste($event)\\\"\\r\\n                class=\\\"${!!showValidationErrors ? 'invalid' : ''}\\\" disabled.bind=\\\"disabled\\\" keydown.delegate=\\\"onKeydown($event)\\\" />\\r\\n\\r\\n            <textarea if.bind=\\\"multiline\\\" rows=\\\"4\\\" id=\\\"${fieldName}\\\" name=\\\"${fieldName}\\\" blur.trigger=\\\"markVisited()\\\" value.bind=\\\"value\\\" paste.delegate=\\\"onPaste($event)\\\" class=\\\"answer ${!!showValidationErrors ? 'invalid' : ''} ${disabled ? 'inactive' : ''}\\\" disabled.bind=\\\"disabled\\\"></textarea>\\r\\n        </div>\\r\\n    </div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","// Module\nvar code = \"<template>\\r\\n\\t<require from=\\\"./grid.scss\\\"></require>\\r\\n\\t<div class=\\\"aurelia-grid grid-container\\\">\\r\\n\\t\\t<table class=\\\"table table-hover table-striped table-responsive grid-header-table\\\">\\r\\n\\t\\t\\t<thead>\\r\\n\\t\\t\\t\\t<tr class=\\\"grid-headings\\\">\\r\\n\\t\\t\\t\\t</tr>\\r\\n\\t\\t\\t</thead>\\r\\n\\t\\t</table>\\r\\n\\r\\n\\t\\t<!-- Content table -->\\r\\n\\t\\t<div class=\\\"grid-content-container\\\">\\r\\n\\t\\t\\t<table class=\\\"table table-hover table-striped table-responsive selectable\\\" show.bind=\\\"!noDataMessage || (noDataMessage && source.count > 0)\\\">\\r\\n\\t\\t\\t\\t<tbody>\\r\\n\\t\\t\\t\\t\\t<tr click.delegate=\\\"$grid.selection.select($item, $event)\\\">\\r\\n\\t\\t\\t\\t\\t</tr>\\r\\n\\t\\t\\t\\t</tbody>\\r\\n\\t\\t\\t</table>\\r\\n\\t\\t\\t<div show.bind=\\\"!source.loading && noDataMessage && source.count === 0\\\" class=\\\"alert alert-warning grid-no-data-message\\\">${ noDataMessage }</div>\\r\\n\\t\\t</div>\\r\\n\\t\\t<div class=\\\"grid-overlay\\\" if.bind=\\\"source.loading\\\"></div>\\r\\n\\r\\n\\t\\t<div if.bind=\\\"source.loading\\\" class=\\\"progress grid-progress-indicator\\\">\\r\\n\\t\\t\\t<div class=\\\"progress-bar progress-bar-striped active\\\" role=\\\"progressbar\\\">\\r\\n\\t\\t\\t\\t<span>${ sourceLoadingMessage }</span>\\r\\n\\t\\t\\t</div>\\r\\n\\t\\t</div>\\r\\n\\r\\n\\t\\t<!-- Footer div -->\\r\\n\\t\\t<div class=\\\"grid-footer-container\\\" if.bind=\\\"(!pager.autoHide || source.pageCount > 1) && !pager.template\\\">\\r\\n\\t\\t\\t<div class=\\\"pager\\\">\\r\\n\\t\\t\\t\\t<ul class=\\\"pagination\\\">\\r\\n\\t\\t\\t\\t\\t<li>\\r\\n\\t\\t\\t\\t\\t\\t<a class=\\\"mar-right\\\" href=\\\"\\\" title=\\\"Refresh\\\" click.delegate=\\\"refresh()\\\"><span class.bind=\\\"icons.refresh\\\"></span></a>\\r\\n\\t\\t\\t\\t\\t</li>\\r\\n\\r\\n\\t\\t\\t\\t\\t<li if.bind=\\\"pager.showFirstLast\\\" class=\\\"${ pager.prevDisabled ? 'disabled' : '' }\\\">\\r\\n\\t\\t\\t\\t\\t\\t<a href=\\\"\\\"  title.bind=\\\"icons.firstPageTitle\\\" click.delegate=\\\"pager.first()\\\" aria-label=\\\"First\\\"><span class.bind=\\\"icons.firstPage\\\"></span></a>\\r\\n\\t\\t\\t\\t\\t</li>\\r\\n\\r\\n\\t\\t\\t\\t\\t<li class=\\\"${ pager.prevDisabled ? 'disabled' : '' }\\\">\\r\\n\\t\\t\\t\\t\\t\\t<a href=\\\"\\\" title.bind=\\\"icons.prevPageTitle\\\" click.delegate=\\\"pager.prev()\\\" aria-label=\\\"Previous\\\"><span class.bind=\\\"icons.prevPage\\\"></span></a>\\r\\n\\t\\t\\t\\t\\t</li>\\r\\n\\t\\t\\t\\t\\t<li repeat.for=\\\"curPage of pager.pages\\\" class=\\\"${ curPage == source.page ? 'active' : '' }\\\">\\r\\n\\t\\t\\t\\t\\t\\t<!-- This span is an IE bug fix - if a &raquo; or many other chars are used before an interpolation for some reason that interpolation fails, following ones are fine (this is for the same property). Adding an invisible span with an interpolate in it fixes the issue  -->\\r\\n\\t\\t\\t\\t\\t\\t<span style=\\\"display:none\\\">${curPage}</span>\\r\\n\\t\\t\\t\\t\\t\\t<a href=\\\"\\\" click.delegate=\\\"pager.changePage(curPage)\\\">${curPage}</a>\\r\\n\\t\\t\\t\\t\\t</li>\\r\\n\\t\\t\\t\\t\\t<li class=\\\"${ pager.nextDisabled ? 'disabled' : '' }\\\">\\r\\n\\t\\t\\t\\t\\t\\t<a href=\\\"\\\" title.bind=\\\"icons.nextPageTitle\\\" click.delegate=\\\"pager.next()\\\" aria-label=\\\"Next\\\"><span class.bind=\\\"icons.nextPage\\\"></span></a>\\r\\n\\t\\t\\t\\t\\t</li>\\r\\n\\r\\n\\t\\t\\t\\t\\t<li if.bind=\\\"pager.showFirstLast\\\" class=\\\"${ pager.nextDisabled ? 'disabled' : '' }\\\">\\r\\n\\t\\t\\t\\t\\t\\t<a href=\\\"\\\" title.bind=\\\"icons.lastPageTitle\\\" click.delegate=\\\"pager.last()\\\" aria-label=\\\"Last\\\"><span class.bind=\\\"icons.lastPage\\\"></span></a>\\r\\n\\t\\t\\t\\t\\t</li>\\r\\n\\t\\t\\t\\t</ul>\\r\\n\\t\\t\\t</div>\\r\\n\\t\\t\\t\\r\\n\\t\\t\\t<div class=\\\"form-inline\\\" if.bind=\\\"true\\\">\\r\\n\\t\\t\\t\\t<div class=\\\"form-control-group\\\">\\r\\n\\t\\t\\t\\t\\t<select class=\\\"form-control\\\" value.bind=\\\"pageSize\\\">\\r\\n\\t\\t\\t\\t\\t\\t<option value.bind=\\\"size\\\" repeat.for=\\\"size of pager.pageSizes\\\">${ size === '*' ? 'All' : size }</option>\\r\\n\\t\\t\\t\\t\\t</select>\\r\\n\\t\\t\\t\\t\\t<span> items per page</span>\\r\\n\\t\\t\\t\\t</div>\\r\\n\\t\\t\\t</div>\\r\\n\\t\\t\\t<span class=\\\"grid-summary\\\" if.bind=\\\"pager.showPagingSummary\\\">Showing ${pager.firstVisibleItem} - ${pager.lastVisibleItem} of ${source.count} items</span>\\r\\n\\t\\t</div>\\r\\n\\t\\t<div class=\\\"grid-footer-custom-container\\\"></div>\\r\\n\\t</div>\\r\\n</template>\\r\\n\";\n// Exports\nexport default code;","import { DialogController } from 'aurelia-dialog';\r\nimport { autoinject, observable } from 'aurelia-framework';\r\n  \r\n@autoinject()\r\nexport class PromptDialog {\r\n    constructor(private controller: DialogController) { }\r\n\r\n    title: string;\r\n    @observable sharedComputer: boolean;\r\n\r\n    activate(title: string) {\r\n        this.title = title;\r\n    }\r\n\r\n    sharedComputerChanged(newValue: boolean) {\r\n        this.controller.ok(newValue);\r\n    }\r\n}\r\n","import { bindable, bindingMode, customElement, computedFrom } from \"aurelia-framework\";\r\n\r\nlet _counter: number = 0;\r\n\r\n@customElement('crisp-input-radio')\r\nexport class CrispInputRadio {\r\n    constructor() {\r\n        _counter += 1;\r\n        this.counter = _counter;\r\n        this.id = \"crisp-input-radio-group-\" + this.counter;\r\n    }\r\n\r\n    yesNoOptions = [\r\n        { id: true, description: 'Yes', },\r\n        { id: false, description: 'No', }\r\n    ];\r\n\r\n    counter: number = 0;\r\n    id: string;\r\n\r\n    @bindable label: string;\r\n    @bindable items: Array<any> = null;\r\n    @bindable descriptionField: string = 'description';\r\n    @bindable valueField;\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay }) value: any;\r\n    @bindable enabled = true;\r\n    @bindable yesNoItems: boolean = false;\r\n    @bindable error: string;\r\n\r\n    radioOptions: Array<RadioOption> = null;\r\n\r\n    private _selected: RadioOption;\r\n\r\n    yesNoItemsChanged() {\r\n        if (this.yesNoItems == true && !this.items) {\r\n            this.items = this.yesNoOptions;\r\n            this.valueField = \"id\";\r\n            this.itemsChanged(this.items, null)\r\n        }\r\n    }\r\n\r\n    @computedFrom('_selected')\r\n    get selected(): RadioOption {\r\n        return this._selected;\r\n    }\r\n\r\n    set selected(selectedOption: RadioOption) {\r\n        this._selected = selectedOption;\r\n        this.value = selectedOption.value;\r\n    }\r\n\r\n\r\n    itemsChanged(n, o) {\r\n        if (this.items) {\r\n            this.radioOptions = this.items.map(x => {\r\n                return new RadioOption(x, this.descriptionField, this.valueField);\r\n            });\r\n            this._selected = this.radioOptions.find(x => x.value === this.value);\r\n        }\r\n    }\r\n\r\n    /// if the bound value changes we need to update _selected so it's reflected in the radio buttons\r\n    valueChanged(n, o) {\r\n        if (this.radioOptions) {\r\n            this._selected = this.radioOptions.find(x => x.value === this.value);\r\n        }\r\n    }\r\n}\r\n\r\nlet _optionCounter: number = 0;\r\nexport class RadioOption {\r\n    constructor(choice: any, labelProperty: string, valueProperty: string) {\r\n        if (typeof choice === \"object\") {\r\n            this.label = choice[labelProperty];\r\n        } else {\r\n            this.label = choice;\r\n        }\r\n\r\n        if (typeof choice === \"object\" && valueProperty) {\r\n            this.value = choice[valueProperty];\r\n        } else {\r\n            this.value = choice;\r\n        }\r\n\r\n        _optionCounter += 1;\r\n        this.id = \"crisp-input-radio-group-\" + _counter + \"-option-\" + _optionCounter;\r\n    }\r\n\r\n    id: string;\r\n    label: string;\r\n    value: any;\r\n}\r\n","import { children } from 'aurelia-framework';\r\nimport { bindable, observable, bindingMode, inject, TaskQueue, autoinject } from 'aurelia-framework';\r\nimport { BindingEngine, computedFrom } from 'aurelia-binding';\r\n\r\ndeclare var $;\r\nlet _counter: number = 0;\r\n\r\n@autoinject\r\nexport class CrispPicker {\r\n    constructor(private bindingEngine: BindingEngine, private taskQueue: TaskQueue) {\r\n        _counter += 1;\r\n        this.counter = _counter;\r\n        this.id = 'crisp-picker-' + this.counter;\r\n    }\r\n\r\n    counter: number = 0;\r\n    id: string;\r\n    @bindable label = '';\r\n    @bindable items = [];\r\n    @observable({ changeHandler: 'createSelect' })\r\n    private select: Element;\r\n    @bindable multiple = false;\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay })\r\n    selected = null;\r\n    @bindable idField = 'id';\r\n    @bindable descriptionField = 'description';\r\n    @bindable valueField;\r\n    @bindable({ changeHandler: 'createSelect' })\r\n    enabled = true;\r\n    @bindable canClear: boolean = false;\r\n\r\n    @bindable valid = true;\r\n    @bindable error = '';\r\n\r\n    attached() {\r\n        this.createSelect();\r\n    }\r\n\r\n    // when we bind in a new array from outside the change event stops working, so instead here\r\n    // when we detect an array change (a new array) we setup an observer of our own\r\n    _itemsSubscription = null;\r\n    itemsChanged(n, o) {\r\n        if (this._itemsSubscription) {\r\n            this._itemsSubscription.dispose();\r\n        }\r\n        if (n !== undefined && n !== null) {\r\n            this._itemsSubscription = this.bindingEngine.collectionObserver(n).subscribe(_ => {\r\n                this.createSelect();\r\n            });\r\n        }\r\n        this.createSelect();\r\n    }\r\n\r\n    // we need to watch the selected aray using the observer\r\n    // to catch any changes made, so we can update the text label\r\n    _selectionSubscription = null;\r\n    selectedChanged(n, o) {\r\n        if (n === undefined || n === null) {\r\n            $(this.select).val(null);\r\n            this.getInnerInput().val(null);\r\n            return;\r\n        }\r\n        if (this._selectionSubscription) {\r\n            this._selectionSubscription.dispose();\r\n        }\r\n        if (n instanceof Array) {\r\n            this._selectionSubscription = this.bindingEngine.collectionObserver(n).subscribe(_ => {\r\n                this.updateMulti(this.selected);\r\n            });\r\n            this.updateMulti(this.selected);\r\n        } else {\r\n            // if somehow no items - clear the selected text\r\n            if (this.items === undefined || this.items === null) {\r\n                console.warn(`there are no items in the collection - label = ${this.label}`);\r\n                this.getInnerInput().val('');\r\n                return;\r\n            }\r\n            const value = this.valueField ? n : this.getId(n) || '';\r\n            $(this.select).val(value.toString());\r\n            let description = '';\r\n            if (this.valueField) {\r\n                const item = this.items.find(i => i[this.valueField] === n);\r\n                if (item) description = item[this.descriptionField].toString();\r\n            } else {\r\n                description = n.description;\r\n            }\r\n            this.getInnerInput().val(description);\r\n        }\r\n    }\r\n\r\n    private updateMulti(newVals: any[]) {\r\n        let valsAndDescs: any[];\r\n        if (this.items === undefined || this.items === null) {\r\n            console.warn(`there are no items in the collection - label = ${this.label}`);\r\n            valsAndDescs = [];\r\n        } else {\r\n            if (this.valueField) {\r\n                valsAndDescs = newVals.map(x => {\r\n                    const itemIndex = this.items.findIndex(item => item[this.valueField] === x);\r\n                    const item = this.items[itemIndex];\r\n                    return {\r\n                        index: itemIndex,\r\n                        val: x.toString(),\r\n                        desc: item ? item[this.descriptionField] : ''\r\n                    };\r\n                });\r\n            } else {\r\n                valsAndDescs = newVals\r\n                    .map(x => {\r\n                        const id = this.getId(x);\r\n                        const itemIndex = this.items.findIndex(item => this.getId(item) === id);\r\n                        const item = this.items[itemIndex];\r\n                        return {\r\n                            index: itemIndex,\r\n                            val: id,\r\n                            desc: item ? item[this.descriptionField] : '-unrecognised-'\r\n                        };\r\n                    })\r\n                    .filter(x => x != null);\r\n            }\r\n        }\r\n\r\n        const innerInput = this.getInnerInput();\r\n\r\n        // update the select so the listed value are correct\r\n        $(this.select).val(valsAndDescs.map(x => x.val));\r\n        innerInput.val(\r\n            valsAndDescs\r\n                .map(x => x.desc)\r\n                .join(', ')\r\n                .trim()\r\n        );\r\n\r\n        // update the checkboxes internal to th ul so the checked reflect the selected correctly\r\n        const lis = innerInput.siblings('ul').children();\r\n        innerInput\r\n            .siblings('ul')\r\n            .find(\"input[type='checkbox']\")\r\n            .prop('checked', function(i, val) {\r\n                return valsAndDescs.findIndex(m => m.index === i) !== -1;\r\n            });\r\n    }\r\n\r\n    detached() {\r\n        if (this._itemsSubscription) {\r\n            this._itemsSubscription.dispose();\r\n        }\r\n        if (this._selectionSubscription) {\r\n            this._selectionSubscription.dispose();\r\n        }\r\n    }\r\n\r\n    createSelect() {\r\n        this.taskQueue.queueTask({\r\n            call: () => {\r\n                const $select = $(this.select);\r\n                $select.material_select('destroy');\r\n\r\n                if (this.enabled) $select.removeClass('disabled').removeAttr('disabled');\r\n                else $select.addClass('disabled').prop('disabled', true);\r\n\r\n                $select.material_select();\r\n\r\n                const innerInput = this.getInnerInput();\r\n\r\n                // HACK: This only affects single selection. The event below in materialize closes the dropdown before the 'click' event\r\n                // when we position the drop down list. So here we remove the event, then in itemsSelected() we manually call the 'close' event\r\n                // when a single item is selected.\r\n                //\r\n                // $newSelect.on('blur', function() {\r\n                //    if (!multiple) {\r\n                //      $(this).trigger('close');\r\n                //    }\r\n                //    ...\r\n                // });\r\n                if (!this.multiple) {\r\n                    innerInput.off('blur');\r\n                }\r\n\r\n                // so that the popup window that displays the list does not show inside it's parent container and cause that container to overflow\r\n                // we instead move the popup to the body for display.\r\n                innerInput.on('open', () => {\r\n                    const popupList = innerInput.siblings('ul');\r\n                    // store the current instance id against the popup list so we can\r\n                    // match it back later when trying to move it back\r\n                    popupList.data('id', this.id);\r\n\r\n                    const currentPosition = innerInput.offset();\r\n                    const body = $('body');\r\n\r\n                    const dropdownHeight = 300;\r\n                    const bottomEdge = body.innerHeight();\r\n\r\n                    // detect if we will go offscreen at the bottom - in which case make the options appear above\r\n                    if (currentPosition.top + dropdownHeight > bottomEdge) {\r\n                        // going offscreen at bottom;\r\n                        if (currentPosition.top - dropdownHeight < 0) {\r\n                            // still going offscreen if we flow up - so resize instead;\r\n                            popupList.css('max-height', bottomEdge - currentPosition.top);\r\n                        } else {\r\n                            // flow upwards;\r\n                            currentPosition.top = currentPosition.top - dropdownHeight + innerInput.height();\r\n                        }\r\n                    }\r\n\r\n                    popupList.css('display', 'none');\r\n                    body.append(popupList);\r\n\r\n                    setTimeout(\r\n                        () =>\r\n                            popupList.css({\r\n                                position: 'absolute',\r\n                                left: currentPosition.left,\r\n                                top: currentPosition.top,\r\n                                display: 'block'\r\n                            }),\r\n                        200\r\n                    );\r\n\r\n                    $select.on('change.crisp-picker-' + this.id, () => {\r\n                        this.itemsSelected($select.val());\r\n                    });\r\n                    $select.on('blur.crisp-picker-' + this.id, () => {\r\n                        this.itemsSelected($select.val());\r\n                    });\r\n\r\n                    // we need to move the popup back to its original position in the tree when user clicks away\r\n                    $(document).on('click.crisp-picker-' + this.id, x => {\r\n                        this.tryMovePopupListFromBodyBackToInput();\r\n                    });\r\n                });\r\n\r\n                innerInput.on('close', () => {\r\n                    // we need to move the popup back to it's original position in the tree when user makes a selection\r\n                    this.tryMovePopupListFromBodyBackToInput();\r\n                    $select.off('.crisp-picker-' + this.id);\r\n                });\r\n\r\n                this.selectedChanged(this.selected, null);\r\n            }\r\n        });\r\n    }\r\n\r\n    tryMovePopupListFromBodyBackToInput() {\r\n        // if the dropdown for this instance is currently open\r\n        // get it and move it back. if a different ul is there leave it alone\r\n        const existing = $('body>ul.select-dropdown')\r\n            .toArray()\r\n            .map(f => $(f))\r\n            .find(f => f.data('id') === this.id);\r\n        if (!!existing) {\r\n            this.getInnerInput()\r\n                .parent()\r\n                .append(existing.css({ position: 'absolute', display: 'none' }));\r\n            // once we have moved it back we aren't going to need the event watcher so remove it\r\n            $(document).off('click.crisp-picker-' + this.id);\r\n        }\r\n    }\r\n\r\n    itemsSelected = (selected: string | string[]) => {\r\n        if (!selected) {\r\n            this.selected = this.multiple ? [] : null;\r\n            return;\r\n        }\r\n        if (typeof selected === 'string') {\r\n            this.selected = this.getValue(this.items.find(x => this.getId(x).toString() === selected));\r\n        } else {\r\n            this.selected = this.items\r\n                .filter(x => selected.indexOf(this.getId(x).toString()) >= 0)\r\n                .map(x => this.getValue(x));\r\n        }\r\n\r\n        // HACK: see comment in createSelect() to see why we need this\r\n        if (!this.multiple) {\r\n            this.getInnerInput().trigger('close');\r\n        }\r\n\r\n        this.select.dispatchEvent(new CustomEvent('selected', { bubbles: true, detail: this.selected }));\r\n    };\r\n\r\n    getId(item) {\r\n        if (!item) return item;\r\n        if (this.idField) return item[this.idField];\r\n        return item;\r\n    }\r\n\r\n    getDescription(item) {\r\n        if (!item) return item;\r\n        return item[this.descriptionField];\r\n    }\r\n\r\n    getValue(item) {\r\n        if (!item) return item;\r\n        if (this.valueField) return item[this.valueField];\r\n        return item;\r\n    }\r\n\r\n    private getInnerInput() {\r\n        return $(this.select).siblings('input.select-dropdown');\r\n    }\r\n\r\n    @computedFrom('selected', 'multiple', 'canClear')\r\n    get showClear() {\r\n        if ((this.selected !== 0 && !!this.selected === false) || this.multiple === true) return false;\r\n        return this.canClear === true;\r\n    }\r\n\r\n    clear() {\r\n        if (this.multiple === true) return;\r\n        this.selected = null;\r\n    }\r\n}\r\n","import { customElement, bindable, useView, bindingMode, autoinject, containerless, PLATFORM } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\n\r\n@customElement('ex-icon')\r\n@useView(PLATFORM.moduleName('./control.html'))\r\n@autoinject()\r\nexport class Icon{\r\n  @bindable public icon: string;\r\n}\r\n","import { customElement, useView, autoinject, PLATFORM, bindable } from 'aurelia-framework';\r\n\r\n@customElement('form-button')\r\n@useView(PLATFORM.moduleName('./control.html'))\r\n@autoinject()\r\nexport class FormButton {\r\n    @bindable public label: string = \"\";\r\n    @bindable disabled = false;\r\n    @bindable icon: string;\r\n    @bindable clickAction: any;\r\n\r\n    clicked() {\r\n        if (this.clickAction && !this.disabled) {\r\n            this.clickAction();\r\n        }\r\n    }\r\n}\r\n","import { customElement, bindable, bindingMode, autoinject, observable } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { PostcodeLookupClient, AddressDtoResult } from 'application/gql/postcodeLookup.tsgql';\r\nimport { validate, ValidateNested, IsNotEmpty, IsOptional, IsPostcode, ValidateIf } from \"validation\";\r\nimport { FormInputText } from '../form-input-text/form-input-text';\r\nimport { AddressDtoInput, CountryCodeType } from 'application/gql/createUpdateApplication.tsgql';\r\nimport { Update } from '../../../updateService';\r\nimport { Helpers } from 'application/helpers';\r\nimport { FormInputCountry } from '../form-input-country/form-input-country';\r\nimport { Enums } from '../../../application/enums';\r\n\r\n@customElement('form-input-address')\r\n@autoinject()\r\nexport class FormInputAddress extends InputBase<Address> {\r\n    constructor(private postcodeLookupClient: PostcodeLookupClient) {\r\n        super();\r\n    }\r\n\r\n    @ValidateNested()\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay })  public value: Address;\r\n\r\n    @bindable label: string;\r\n    @bindable sameAs: Address;\r\n    @bindable sameAsText = \"Same as the property address\";\r\n\r\n    @bindable disabled: boolean = false;\r\n    @bindable addressRequired: boolean = true;\r\n\r\n    manual: boolean;\r\n    addressConfirmed: boolean;\r\n    searchResults: AddressDtoResult[] = [];\r\n    noResults: boolean;\r\n\r\n    countryCodes = Enums.countryCodes;\r\n\r\n    address1VM: FormInputText;\r\n    townVM: FormInputText;\r\n    postcodeVM: FormInputText;\r\n    countryVM: FormInputCountry;\r\n\r\n    searching = false;\r\n\r\n    @IsPostcode({ message: \"Please enter a valid postcode\" })\r\n    @ValidateIf((o: FormInputAddress) => o.addressRequired || !!o.lookupPostcode)\r\n    @observable lookupPostcode: string;\r\n\r\n    bind() {\r\n        if (!!this.value && this.value.address1 && this.value.town && this.value.postcode && this.value.country) {\r\n            this.addressConfirmed = true;\r\n        }\r\n    }\r\n\r\n    async lookupPostcodeChanged() {\r\n        const errors = await validate(this);\r\n        if (this.lookupPostcode && !errors.some(x => x.property === 'lookupPostcode')) {\r\n            this.searching = true;\r\n            try {\r\n                const result = await this.postcodeLookupClient.postcodeLookup(this.lookupPostcode);\r\n                this.searchResults = result.postcodeLookup;\r\n            } catch {\r\n                this.searchResults = [];\r\n            } finally {\r\n                this.noResults = !this.searchResults || this.searchResults.length === 0;\r\n                this.searching = false;\r\n            }\r\n        }\r\n        else {\r\n            this.searching = false;\r\n            this.searchResults = [];\r\n            this.noResults = false;\r\n        }\r\n    }\r\n\r\n    getCountryCodeDescription(countryCode: CountryCodeType) {\r\n        return countryCode && this.countryCodes.find(c => c.id === countryCode)?.description;\r\n    }\r\n\r\n    getAddressString(address: AddressDtoResult) {\r\n        return [address.address1, address.address2, address.address3, address.town, address.postcode, this.getCountryCodeDescription(address.country)].filter(x => !!x).join(', ');\r\n    }\r\n\r\n    selectAddress(address: AddressDtoResult) {\r\n        this.value.address1 = address.address1;\r\n        this.value.address2 = address.address2;\r\n        this.value.address3 = address.address3;\r\n        this.value.town = address.town;\r\n        this.value.postcode = address.postcode;\r\n        this.value.country = address.country;\r\n        this.addressConfirmed = true;\r\n    }\r\n\r\n    public confirmAddress() {\r\n        this.manual = true;\r\n\r\n        // timeout ensures vm's are available\r\n        setTimeout(async () => {\r\n            this.address1VM.markVisited();\r\n            this.townVM.markVisited();\r\n            this.postcodeVM.markVisited();\r\n            this.countryVM.markVisited();\r\n            const errors = await validate(this.value);\r\n            this.addressConfirmed = errors.length === 0;    \r\n        }, 0);\r\n    }\r\n\r\n    reset(manualMode: boolean) {\r\n        this.searchResults = [];\r\n        this.manual = manualMode;\r\n    }\r\n\r\n    searchResultKeyup(event: KeyboardEvent, address: AddressDtoResult) {\r\n        return Helpers.keypressEnterOrSpace(event, () => this.selectAddress(address));\r\n    }\r\n\r\n    changeAddressKeydown(event: KeyboardEvent) {\r\n        return Helpers.keypressEnterOrSpace(event, () => this.addressConfirmed = false);\r\n    }\r\n\r\n    enterManuallyKeydown(event: KeyboardEvent) {\r\n        return Helpers.keypressEnterOrSpace(event, () => this.reset(true));\r\n    }\r\n\r\n    searchByPostcodeKeydown(event: KeyboardEvent) {\r\n        return Helpers.keypressEnterOrSpace(event, () => this.manual = false);\r\n    }\r\n\r\n    setAddressToSameAs() {\r\n        if (!this.value) {\r\n            this.value = new Address();\r\n        }\r\n        \r\n        this.value.address1 = this.sameAs.address1;\r\n        this.value.address2 = this.sameAs.address2;\r\n        this.value.address3 = this.sameAs.address3;\r\n        this.value.town = this.sameAs.town;\r\n        this.value.postcode = this.sameAs.postcode;\r\n        this.value.country = this.sameAs.country;\r\n        this.confirmAddress();\r\n    }\r\n}\r\n\r\nexport class Address {\r\n    @Update.IgnoreUpdates()\r\n    sameAsPropertyAddress = false;\r\n\r\n    @IsNotEmpty({ message: \"Please enter address line 1\" })\r\n    address1: string;\r\n    \r\n    @IsOptional()\r\n    address2: string;\r\n    \r\n    @IsOptional()\r\n    address3: string;\r\n    \r\n    @IsNotEmpty({ message: \"Please enter a town\" })\r\n    town: string;\r\n    \r\n    @IsPostcode({ message: \"Please enter a valid postcode\" })\r\n    @ValidateIf((a: Address) => a.country === CountryCodeType.UNITEDKINGDOM)\r\n    postcode: string;\r\n    \r\n    @IsNotEmpty({ message: \"Please select a country\" })\r\n    country: CountryCodeType = CountryCodeType.UNITEDKINGDOM;\r\n\r\n    static fromDto(address: AddressDtoResult) {\r\n        const result = new Address();\r\n\r\n        if (address) {\r\n            result.address1 = address.address1;\r\n            result.address2 = address.address2;\r\n            result.address3 = address.address3;\r\n            result.town = address.town;\r\n            result.postcode = address.postcode;\r\n            result.country = address.country;\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    toDto() {\r\n        const result = new AddressDtoInput();\r\n        result.address1 = this.address1;\r\n        result.address2 = this.address2;\r\n        result.address3 = this.address3;\r\n        result.town = this.town;\r\n        result.postcode = this.postcode;\r\n        result.country = this.country;\r\n        return result;\r\n    }\r\n\r\n    equals(address: Address) {\r\n        return this.address1 === address.address1 &&\r\n            this.address2 === address.address2 &&\r\n            this.address3 === address.address3 &&\r\n            this.town === address.town &&\r\n            this.postcode === address.postcode &&\r\n            this.country === address.country;\r\n    }\r\n}\r\n","import { customElement, bindable, useView, bindingMode, autoinject, containerless, PLATFORM, observable } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\n\r\n@customElement('form-input-bool')\r\n@autoinject()\r\nexport class FormInputBool extends InputBase<string> {\r\n    @bindable disabled: boolean = false;\r\n}\r\n","import { customElement, bindable, bindingMode, autoinject, computedFrom, Disposable, BindingEngine } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { IsNotEmpty, ValidateIf, IsEmail, ValidateNested, IsOptional, ValidationArguments, Validate, IsNotBlank, ValidationOptions, registerDecorator, Validator, EqualsPropertyConstraint, validate, isPhoneNumber } from 'validation';\r\nimport { Address, FormInputAddress } from '../form-input-address/form-input-address';\r\nimport { Update } from 'updateService';\r\nimport { CountryCodeType } from 'application/gql/retrieveApplication.tsgql';\r\nimport { Lists } from 'application/lists';\r\nimport { Helpers } from 'application/helpers';\r\nimport { ContactDtoInput } from 'application/gql/createUpdateApplication.tsgql';\r\nimport { CurrentUser } from 'user';\r\n\r\n@customElement('form-input-contact')\r\n@autoinject()\r\nexport class FormInputContact extends InputBase<Contact> {\r\n    constructor(private user: CurrentUser, private bindingEngine: BindingEngine) {\r\n        super();\r\n    }\r\n\r\n    @Update.UpdateNested()\r\n    @ValidateNested()\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay })  public value: Contact;\r\n    \r\n    @bindable contactTypeLabel = 'Company or a private individual?';\r\n    @bindable contactNumberLabel = 'Contact number';\r\n    @bindable reporter: boolean = false;\r\n    @bindable policyholder: boolean = false;\r\n    @bindable additionalPolicyholder: boolean = false;\r\n    @bindable captureRelationship: boolean = false;\r\n    @bindable captureAddress: boolean = false;\r\n    @bindable saved: boolean = false;\r\n    @bindable representative: boolean = false;\r\n    @bindable isFreeholder: boolean = false;\r\n    @bindable isManagingAgent: boolean = false;\r\n    @bindable disabled: boolean = false;\r\n\r\n    titles = Lists.titles;\r\n    relationships = Lists.relationships;\r\n    additionalPolicyholderRelationships = Lists.additionalPolicyholderRelationships;\r\n    representativeRelationships = Lists.representativeRelationships;\r\n    familyRelationships = Lists.familyRelationships;\r\n    subscriptions: Disposable[] = [];\r\n    addressVM: FormInputAddress;\r\n\r\n    attached() {\r\n        if (this.isManagingAgent) {\r\n            this.subscriptions.push(this.bindingEngine.propertyObserver(this.value, 'telephone').subscribe(async () => { await validate(this.addressVM); }));\r\n            this.subscriptions.push(this.bindingEngine.propertyObserver(this.value, 'email').subscribe(async () => { await validate(this.addressVM); }));\r\n            this.subscriptions.push(this.bindingEngine.propertyObserver(this.value.address, 'postcode').subscribe(async () => { await validate(this); }));\r\n        }\r\n    }\r\n\r\n    detached() {\r\n        this.subscriptions.forEach(x => x.dispose());\r\n    }\r\n\r\n    bind() {\r\n        if (this.value) {\r\n            this.value.reporter = this.reporter;\r\n            this.value.policyholder = this.policyholder;\r\n            this.value.additionalPolicyholder = this.additionalPolicyholder;\r\n            this.value.captureRelationship = this.captureRelationship;\r\n            this.value.captureAddress = this.captureAddress;\r\n            this.value.representative = this.representative;\r\n            this.value.admin = this.user.isAdmin;\r\n            this.value.isFreeholder = this.isFreeholder;\r\n            this.value.isManagingAgent = this.isManagingAgent;\r\n        }\r\n    }\r\n}\r\n\r\nexport class Contact {\r\n    constructor(leadClaimant: boolean = null) {\r\n        this.isLeadClaimant = leadClaimant;\r\n    }\r\n\r\n    id: string;\r\n    editing = true;\r\n    reporter = false;\r\n    policyholder = false;\r\n    additionalPolicyholder = false;\r\n    captureRelationship = false;\r\n    captureAddress = false;\r\n    representative = false;\r\n    isFreeholder = false;\r\n    isManagingAgent = false;\r\n    admin = false;\r\n\r\n    @Update.IgnoreUpdates()\r\n    @computedFrom('title', 'titleOther', 'firstname', 'surname')\r\n    get name() {\r\n        return `${this.title === 'Other' ? this.titleOther : this.title || ''} ${this.firstname || ''} ${this.surname || ''}`.trim();\r\n    }\r\n\r\n    @IsNotEmpty({ message: \"Please select Company or Private Individual\" })\r\n    contactType: string;\r\n\r\n    @IsNotEmpty({ message: \"Please enter title\" })\r\n    @ValidateIf((o: Contact) => o.contactType === \"Private Individual\" || o.reporter || o.representative)\r\n    title: string;\r\n\r\n    @IsNotBlank({ message: \"Please enter title\" })\r\n    @ValidateIf((o: Contact) => (o.contactType === \"Private Individual\" || o.reporter || o.representative) && o.title === \"Other\")\r\n    titleOther: string;\r\n\r\n    @IsNotBlank({ message: \"Please enter first name\" })\r\n    @ValidateIf((o: Contact) => o.contactType === \"Private Individual\" || o.reporter || o.representative)\r\n    firstname: string;\r\n    \r\n    @IsNotBlank({ message: \"Please enter surname\" })\r\n    @ValidateIf((o: Contact) => o.contactType === \"Private Individual\" || o.reporter || o.representative)\r\n    surname: string;\r\n    \r\n    @IsNotBlank({ message: \"Please enter company name\" })\r\n    @ValidateIf((o: Contact) => o.contactType === \"Company\")\r\n    companyName: string;\r\n    \r\n    @IsOptional()\r\n    telephoneCountryCode: CountryCodeType = CountryCodeType.UNITEDKINGDOM;\r\n\r\n    @IsTelephone({ message: \"Please enter a valid phone number\" })\r\n    @ValidateIf((o: Contact) => o.telephoneRequired || !!o.telephone)\r\n    telephone: string;\r\n    \r\n    @IsEmail({}, { message: \"Please enter a valid email address\" })\r\n    @ValidateIf((o: Contact) => o.emailRequired || !!o.email)\r\n    email: string;\r\n\r\n    @Validate(EqualsPropertyConstraint, ['email'], { message: \"Email addresses do not match\" })\r\n    @ValidateIf((o: Contact) => o.reporter && o.correspondenceMethod !== \"Post\")\r\n    emailConfirmation: string;\r\n    \r\n    @IsNotEmpty({ message: \"Please select Yes or No\" })\r\n    @ValidateIf((o: Contact) => o.reporter)\r\n    isLeadClaimant: boolean;\r\n\r\n    @IsNotEmpty({ message: \"Please select relationship type\" })\r\n    @ValidateIf((o: Contact) => o.captureRelationship && !!o.contactType && !o.isLeadClaimant)\r\n    relationshipToLeadClaimant: string;\r\n    \r\n    @IsNotEmpty({ message: \"Please enter relationship type\" })\r\n    @ValidateIf((o: Contact) => o.captureRelationship && !!o.contactType && !o.isLeadClaimant && o.relationshipToLeadClaimant === \"Other\")\r\n    relationshipToLeadClaimantOther: string;\r\n    \r\n    @IsNotEmpty({ message: \"Please select relationship type\" })\r\n    @ValidateIf((o: Contact) => o.captureRelationship && !!o.contactType && !o.isLeadClaimant && o.relationshipToLeadClaimant === \"Family Member\")\r\n    relationshipToLeadClaimantFamilyMember: string;\r\n    \r\n    @IsNotEmpty({ message: \"Please enter relationship type\" })\r\n    @ValidateIf((o: Contact) => o.captureRelationship && !!o.contactType && !o.isLeadClaimant && o.relationshipToLeadClaimantFamilyMember === \"Other\")\r\n    relationshipToLeadClaimantFamilyMemberOther: string;\r\n\r\n    @Update.UpdateNested()\r\n    @ValidateNested()\r\n    @ValidateIf((o: Contact) => o.addressRequired)\r\n    address: Address = new Address();\r\n\r\n    @IsNotEmpty({ message: \"Please select Email or Post\" })\r\n    correspondenceMethod: string = \"Email\";\r\n\r\n    @Update.IgnoreUpdates()\r\n    @computedFrom('reporter', 'policyholder', 'additionalPolicyholder', 'representative', 'isManagingAgent', 'telephone', 'email', 'address.postcode')\r\n    get telephoneRequired() {\r\n        if (this.isManagingAgent) {\r\n            return (!this.email && !this.address.postcode) || !!this.telephone;\r\n        }\r\n\r\n        return this.reporter || this.policyholder || this.additionalPolicyholder || this.representative;\r\n    }\r\n\r\n    @Update.IgnoreUpdates()\r\n    @computedFrom('reporter', 'correspondenceMethod', 'representative', 'isManagingAgent', 'telephone', 'email', 'address.postcode')\r\n    get emailRequired() {\r\n        if (this.isManagingAgent) {\r\n            return (!this.telephone && !this.address.postcode) || !!this.email;\r\n        }\r\n\r\n        return (this.reporter && this.correspondenceMethod !== \"Post\") || this.representative;\r\n    }\r\n    \r\n    @Update.IgnoreUpdates()\r\n    @computedFrom('captureAddress', 'admin', 'correspondenceMethod', 'isFreeholder', 'isManagingAgent', 'telephone', 'email', 'address.postcode')\r\n    get addressRequired() {\r\n        if (this.isFreeholder) {\r\n            return false;\r\n        }\r\n\r\n        if (this.isManagingAgent) {\r\n            return (!this.telephone && !this.email) || !!this.address.postcode;\r\n        }\r\n\r\n        return this.captureAddress || (this.admin && this.correspondenceMethod === \"Post\");\r\n    }\r\n\r\n    static fromDto(contact: any, additionalPolicyholder = false, representative = false) {\r\n        const result = new Contact();\r\n\r\n        if (contact) {\r\n            result.id = contact.id;\r\n            result.contactType = contact.contactType;\r\n            result.email = contact.email;\r\n            result.emailConfirmation = contact.email;\r\n            result.contactType = contact.contactType;\r\n            result.title = Helpers.handleOther(Lists.titles, contact.title);\r\n            result.titleOther = Helpers.handleOther(Lists.titles, contact.title, true);\r\n            result.firstname = contact.firstname;\r\n            result.surname = contact.surname;\r\n            result.companyName = contact.companyName;\r\n            result.telephoneCountryCode = contact.telephoneCountryCode;\r\n            result.telephone = contact.telephone;\r\n            result.isLeadClaimant = contact.isLeadClaimant;\r\n            result.address = Address.fromDto(contact.address);\r\n            result.correspondenceMethod = contact.correspondenceMethod;\r\n            \r\n            if (!!contact.relationshipToLeadClaimant) {\r\n                const relationships = additionalPolicyholder ? Lists.additionalPolicyholderRelationships :\r\n                                      representative ? Lists.representativeRelationships : Lists.relationships;\r\n\r\n                result.relationshipToLeadClaimant = Helpers.handleOther(relationships, contact.relationshipToLeadClaimant);\r\n                result.relationshipToLeadClaimantOther = Helpers.handleOther(relationships, contact.relationshipToLeadClaimant, true);\r\n            }\r\n\r\n            if (!!contact.relationshipToLeadClaimantFamilyMember) {\r\n                const familyRelationships = additionalPolicyholder || representative ? [] : Lists.familyRelationships;\r\n\r\n                result.relationshipToLeadClaimantFamilyMember = Helpers.handleOther(familyRelationships, contact.relationshipToLeadClaimantFamilyMember);\r\n                result.relationshipToLeadClaimantFamilyMemberOther = Helpers.handleOther(familyRelationships, contact.relationshipToLeadClaimantFamilyMember, true);\r\n            }\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    toDto() {\r\n        const result = new ContactDtoInput();\r\n        result.id = this.id;\r\n        result.email = this.email;\r\n        result.contactType = this.contactType;\r\n        result.title = this.title === \"Other\" ? this.titleOther : this.title;\r\n        result.firstname = this.firstname;\r\n        result.surname = this.surname;\r\n        result.companyName = this.companyName;\r\n        result.telephoneCountryCode = this.telephoneCountryCode;\r\n        result.telephone = this.telephone;\r\n        result.isLeadClaimant = this.isLeadClaimant;\r\n        result.relationshipToLeadClaimant = this.relationshipToLeadClaimant === \"Other\" ? this.relationshipToLeadClaimantOther : this.relationshipToLeadClaimant;\r\n        result.relationshipToLeadClaimantFamilyMember = this.relationshipToLeadClaimantFamilyMember === \"Other\" ? this.relationshipToLeadClaimantFamilyMemberOther : this.relationshipToLeadClaimantFamilyMember;\r\n        result.address = this.address.toDto();\r\n        result.correspondenceMethod = this.correspondenceMethod;\r\n        return result;\r\n    }\r\n}\r\n\r\nexport function IsTelephone(validationOptions?: ValidationOptions) {\r\n    return function (object: Object, propertyName: string) {\r\n        registerDecorator({\r\n            name: \"isTelephone\",\r\n            target: object.constructor,\r\n            propertyName: propertyName,\r\n            constraints: [],\r\n            options: validationOptions,\r\n            validator: {\r\n                validate(value: string, args: ValidationArguments) {\r\n                    const contact = args.object as Contact;\r\n                    if (contact.telephoneCountryCode === CountryCodeType.UNITEDKINGDOM) {\r\n                        return isPhoneNumber(value, 'GB');\r\n                    }\r\n                    else {\r\n                        return value && /^[0-9 ]+$/.test(value.trim());\r\n                    }\r\n                }\r\n            }\r\n        });\r\n    };\r\n}\r\n","import { customElement, bindable, autoinject } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { CountryCodeType } from 'application/gql/createUpdateApplication.tsgql';\r\nimport { Helpers } from 'application/helpers';\r\nimport { Enums } from 'application/enums';\r\n\r\n@customElement('form-input-country')\r\n@autoinject()\r\nexport class FormInputCountry extends InputBase<CountryCodeType> {\r\n    @bindable disabled: boolean = false;\r\n\r\n    countryCodes = Enums.countryCodes;\r\n\r\n    onKeydown(e: KeyboardEvent) {\r\n        if (Helpers.isNavigationOrSelectionKey(e) || Helpers.isSpaceKey(e)) {\r\n            return true;\r\n        }\r\n\r\n        if (!Helpers.isNumberKey(e)) {\r\n            e.preventDefault();\r\n            return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n}\r\n","import { customElement, bindable, useView, bindingMode, autoinject, containerless, PLATFORM, observable } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport * as moment from 'moment'\r\nimport { Helpers } from 'application/helpers';\r\n\r\n@customElement('form-input-date')\r\n@autoinject()\r\nexport class FormInputDate extends InputBase<Date> {\r\n    @bindable showDay = true;\r\n    @observable day: string;\r\n    @observable month: string;\r\n    @observable year: string;\r\n\r\n    @bindable disabled: boolean = false;\r\n    \r\n    bound = false;\r\n    focusMonth = false;\r\n    focusYear = false;\r\n\r\n    dayChanged() {\r\n        if (this.bound) {\r\n            if (this.day && !isNaN(Number(this.day)) && this.day.length === 2) {\r\n                this.focusMonth = true;\r\n            }\r\n        \r\n            this.dateChanged();\r\n        }\r\n    }\r\n\r\n    monthChanged() {\r\n        if (this.bound) {\r\n            if (this.month && !isNaN(Number(this.month)) && this.month.length === 2) {\r\n                this.focusYear = true;\r\n            }\r\n        \r\n            this.dateChanged();\r\n        }\r\n    }\r\n\r\n    yearChanged() {\r\n        if (this.bound) {\r\n            this.dateChanged();\r\n        }\r\n    }\r\n\r\n    dateChanged() {\r\n        if (this.year && this.year.length === 4 && !isNaN(Number(this.day)) && !isNaN(Number(this.month)) && !isNaN(Number(this.year))) {\r\n            const d = this.day.length === 1 ? `0${this.day}` : this.day;\r\n            const m = this.month.length === 1 ? `0${this.month}` : this.month;\r\n            const dateString = `${this.year}-${m}-${d}T00:00:00.000Z`;\r\n            const date = moment(dateString);\r\n            if (date.isValid()) {\r\n                this.value = date.toDate();\r\n                return;\r\n            }\r\n        }\r\n        \r\n        this.value = null;\r\n    }\r\n\r\n    bind() {\r\n        if (!!this.value) {\r\n            const date = moment(this.value);\r\n            this.day = date.format('DD');\r\n            this.month = date.format('MM');\r\n            this.year = date.format('YYYY');\r\n        }\r\n        else {\r\n            this.day = !this.showDay ? '01' : '';\r\n            this.month = '';\r\n            this.year = '';\r\n        }\r\n\r\n        this.bound = true;\r\n    }\r\n\r\n    onKeydown(e: KeyboardEvent) {\r\n        if (Helpers.isNavigationOrSelectionKey(e)) {\r\n            return true;\r\n        }\r\n\r\n        if (!Helpers.isNumberKey(e)) {\r\n            e.preventDefault();\r\n            return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n}\r\n","import { customElement, bindable, bindingMode, autoinject, observable, computedFrom, BindingEngine } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { Document } from '../../../application/components/evidence-item';\r\nimport { BindingSignaler } from 'aurelia-templating-resources';\r\nimport { HttpClient, Interceptor, HttpResponseMessage, RequestMessage } from 'aurelia-http-client';\r\nimport { Router } from 'aurelia-router';\r\nimport { validate } from 'validation';\r\nimport { EventAggregator } from 'aurelia-event-aggregator';\r\nimport { Helpers } from 'application/helpers';\r\nimport { DocumentDownloadService } from '../../../services/documentDownloadService';\r\nimport { TokenService } from '../../../services/tokenService';\r\n\r\n@customElement('form-input-file')\r\n@autoinject()\r\nexport class FormInputFile extends InputBase<Document[]> {\r\n\r\n    constructor(\r\n        private bindingSignaler: BindingSignaler,\r\n        private httpClient: HttpClient,\r\n        private router: Router,\r\n        private aggregator: EventAggregator,\r\n        private documentDownloadService: DocumentDownloadService,\r\n        private tokenService: TokenService) {\r\n        super();\r\n    }\r\n\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay }) existingFiles: Document[];\r\n    fileInputFiles: FileList;\r\n    fileInputValue: any;\r\n    dragOver = false;\r\n    searchText: string;\r\n    parent: any;\r\n    fileSelectionError: string = '';\r\n    showExisting: boolean = false;\r\n\r\n    @bindable disabled: boolean = false;\r\n\r\n    readonly acceptedFileTypes = '.pdf, .doc, .docx, .xlsx, .xls, .pptx, .ppt, .jpg, .jpeg, .tif, .tiff, .gif, .bmp, .png, .dwg, .mpg, .mov, .avi, .mp4, .html, .msg, .txt, .m4a, .mp3, .wav';\r\n    readonly maxFileSize = 1073741824; // 1GB\r\n\r\n    bind(bindingContext: any) {\r\n        this.parent = bindingContext;\r\n\r\n        // remove invalid files which may have been partially uploaded in the last session for example\r\n        var invalidFiles = this.value.filter(x => !x.fileId || x.fileId === \"00000000-0000-0000-0000-000000000000\");\r\n        invalidFiles.forEach(file => this.remove(null, file));\r\n    }\r\n\r\n    async fileInputFilesChanged() {\r\n        if (this.fileInputFiles.length > 0) {\r\n            this.fileSelectionError = '';\r\n        }\r\n\r\n        for (let i = 0; i < this.fileInputFiles.length; i++) {\r\n            const file = this.fileInputFiles.item(i);\r\n            this.selectAndUploadFile(file);\r\n        }\r\n\r\n        if (this.fileInputFiles.length > 0) {\r\n            this.fileInputFiles = null;\r\n            this.fileInputValue = null;\r\n        }\r\n    }\r\n\r\n    async selectAndUploadFile(file: File) {\r\n        if (file.size > this.maxFileSize) {\r\n            this.showFileSelectionError(`File too large: \"${file.name}\"`);\r\n            return;\r\n        }\r\n\r\n        const dotIx = file.name.lastIndexOf('.');\r\n        if (dotIx === -1) {\r\n            this.showFileSelectionError(`Unsupported file type: \"${file.name}\"`);\r\n            return;\r\n        }\r\n\r\n        const extension = file.name.substr(dotIx).toLowerCase();\r\n        if (!this.acceptedFileTypes.split(', ').includes(extension)) {\r\n            this.showFileSelectionError(`Unsupported file type: \"${file.name}\"`);\r\n            return;\r\n        }\r\n\r\n        // check file hasn't already been uploaded\r\n        const alreadyInValue = this.value.some(x => x.fileName === file.name && x.fileSize === file.size && x.fileType === file.type);\r\n        if (alreadyInValue) {\r\n            return;\r\n        }\r\n\r\n        const existing = this.existingFiles.find(x => x.fileName === file.name && x.fileSize === file.size && x.fileType === file.type);\r\n        if (existing) {\r\n            this.selectExisting(existing);\r\n            return;\r\n        }\r\n\r\n        const doc = new Document();\r\n        doc.fileName = file.name;\r\n        doc.fileType = file.type;\r\n        doc.fileSize = file.size;\r\n\r\n        // moved these 2 lines back to before the upload as it broke progress indicator and didn't solve the intermittent issue with saving\r\n        this.value.push(doc);\r\n        this.existingFiles.push(doc);\r\n\r\n        const fileId = await this.upload(file, doc);\r\n\r\n        if (fileId) {\r\n            trySetFileId();\r\n        } else {\r\n            this.remove(null, doc, false);\r\n        }\r\n\r\n        function trySetFileId() {\r\n            // ensure add to collection has fired and returned with an id before setting file id\r\n            setTimeout(async () => {\r\n                if (!doc.id) {\r\n                    trySetFileId();\r\n                }\r\n                else {\r\n                    doc.fileId = fileId;\r\n                }\r\n            }, 100);\r\n        }\r\n\r\n        await validate(this.parent);\r\n    }\r\n\r\n    async upload(file: File, doc: Document): Promise<string> {\r\n        try {\r\n            const formData = new FormData();\r\n            formData.append('file', file);\r\n\r\n            const result = await this.httpClient.createRequest('api/file/upload')\r\n                .asPost()\r\n                .withContent(formData)\r\n                .withProgressCallback((e: ProgressEvent) => { this.uploadProgress(doc, e); })\r\n                .withInterceptor({\r\n                    request: async (request: RequestMessage) => {\r\n                        const token = this.tokenService.getToken();\r\n                        if (token) {\r\n                            request.headers.add('Authorization', 'Bearer ' + token);\r\n                        }\r\n                        return request;\r\n                    },\r\n                    response: async (response: HttpResponseMessage) => {\r\n                        if (response.statusCode === 503) {\r\n                            window['offline'] = true;\r\n                            window.location.reload();\r\n                        }\r\n\r\n                        return response;\r\n                    },\r\n                    responseError: async (response: HttpResponseMessage) => {\r\n                        return response;\r\n                    }\r\n                } as Interceptor)\r\n                .send();\r\n\r\n            if (result.isSuccess) {\r\n                return result.response.replace(/\\\"/g, \"\");\r\n            } else {\r\n                if (result.statusCode === 400) {\r\n                    this.showFileSelectionError(result.response);\r\n                }\r\n            }\r\n\r\n            return null;\r\n        }\r\n        catch {\r\n            return null;\r\n        }\r\n    }\r\n\r\n    uploadProgress(doc: Document, e: ProgressEvent) {\r\n        doc.percentUploaded = Math.round((e.loaded / e.total) * 100);\r\n    }\r\n\r\n    async selectExisting(file: Document) {\r\n        this.fileSelectionError = '';\r\n        this.value.push(file);\r\n        this.bindingSignaler.signal('refresh-existing');\r\n        await validate(this.parent);\r\n    }\r\n\r\n    async remove(event: Event, doc: Document, removeError: boolean = true) {\r\n        if (event) {\r\n            event.stopPropagation();\r\n        }\r\n\r\n        if (removeError) {\r\n            this.fileSelectionError = '';\r\n        }\r\n\r\n        const ix = this.value.indexOf(doc);\r\n        this.value.splice(ix, 1);\r\n\r\n        if (!doc.fileId || doc.fileId === \"00000000-0000-0000-0000-000000000000\") {\r\n            const existingIx = this.existingFiles.indexOf(doc);\r\n            this.existingFiles.splice(existingIx, 1);\r\n        }\r\n\r\n        this.bindingSignaler.signal('refresh-existing');\r\n        await validate(this.parent);\r\n    }\r\n\r\n    async download(doc: Document) {\r\n        this.fileSelectionError = '';\r\n\r\n        if (doc.fileId) {\r\n            this.documentDownloadService.download(doc.id);\r\n        }\r\n    }\r\n\r\n    onDragOver(event: Event) {\r\n        event.preventDefault();\r\n        this.dragOver = true;\r\n        return true;\r\n    }\r\n\r\n    onDragLeave(event: Event) {\r\n        event.preventDefault();\r\n        this.dragOver = false;\r\n        return true;\r\n    }\r\n\r\n    onDrop(event: any) {\r\n        this.dragOver = false;\r\n        event.preventDefault();\r\n        this.fileSelectionError = '';\r\n\r\n        if (event.dataTransfer.items) {\r\n            for (let i = 0; i < event.dataTransfer.items.length; i++) {\r\n                if (event.dataTransfer.items[i].kind === 'file') {\r\n                    const file = event.dataTransfer.items[i].getAsFile();\r\n                    this.selectAndUploadFile(file);\r\n                }\r\n            }\r\n        } else {\r\n            for (let i = 0; i < event.dataTransfer.files.length; i++) {\r\n                this.selectAndUploadFile(event.dataTransfer.files[i]);\r\n            }\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    getFileIcon(file: Document) {\r\n        return Helpers.getFileIcon(file);\r\n    }\r\n\r\n    @computedFrom('existingFiles.length', 'value.length')\r\n    get anyExistingFiles() {\r\n        return this.existingFiles.some(x => !this.value.some(y => y.fileId === x.fileId && y.fileName === x.fileName));\r\n    }\r\n\r\n    @computedFrom('searchText')\r\n    get showNoSearchResults() {\r\n        return !!this.searchText && !this.existingFiles.some(x => !this.value.some(y => y.fileId === x.fileId && y.fileName === x.fileName) && x.fileName.toLowerCase().includes(this.searchText.toLowerCase()));\r\n    }\r\n\r\n    showFileSelectionError(message: string) {\r\n        this.fileSelectionError += message + '\\n';\r\n        setTimeout(() => { this.fileSelectionError = ''; }, 5000);\r\n    }\r\n\r\n    toggleExistingKeydown(event: KeyboardEvent) {\r\n        return Helpers.keypressEnterOrSpace(event, () => this.showExisting = !this.showExisting);\r\n    }\r\n\r\n    callUploadDialog() {\r\n        const input = document.getElementById(this.fieldName as string);\r\n        input.click();\r\n    }\r\n}\r\n\r\nexport class FilterValueConverter {\r\n    toView(allItems: Document[], params: { selectedItems: Document[], search: string }) {\r\n        const result = allItems.filter(x => !params.selectedItems.some(y => y.fileId === x.fileId && y.fileName === x.fileName));\r\n        if (params.search === \"\" || params.search === undefined) return result;\r\n        return result.filter((item) => item.fileName.toLowerCase().includes(params.search.toLowerCase()));\r\n    }\r\n}\r\n","import { customElement, bindable, useView, bindingMode, autoinject, containerless, PLATFORM, observable, BindingEngine } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { Helpers } from 'application/helpers';\r\n\r\n@customElement('form-input-multiple')\r\n@autoinject()\r\nexport class FormInputMultiple extends InputBase<string[]> {\r\n  @bindable({ defaultBindingMode: bindingMode.twoWay }) public value: string[];\r\n  @bindable dual = false;\r\n  @bindable options: Array<any> = null;\r\n  @bindable disabled = false;\r\n\r\n  elem: HTMLElement;\r\n\r\n  values: object = {};\r\n\r\n  constructor(\r\n    private bindingEngine: BindingEngine) {\r\n    super();\r\n  }\r\n\r\n  bind() {\r\n    if (this.value === null || this.value === undefined) {\r\n      this.value = [];\r\n    } else {\r\n      this.value.forEach(v => {\r\n        this.values[v] = true;\r\n      })\r\n    }\r\n\r\n    for (let i = 0; i < this.options.length; i++) {\r\n      const optionName = this.options[i];\r\n      this.bindingEngine\r\n        .propertyObserver(this.values, optionName)\r\n        .subscribe((newValue, oldValue) => {\r\n          const set = new Set(this.value);\r\n          if (newValue) {\r\n            set.add(optionName);\r\n          } else {\r\n            set.delete(optionName);\r\n          }\r\n          this.value = Array.from(set);\r\n        });\r\n    }\r\n  }\r\n\r\n  valueChanged(newVal: string, oldVal: string) {\r\n    if (newVal != oldVal && !!this.elem) {\r\n      Helpers.scrollToElement(this.elem);\r\n    }\r\n  }\r\n}\r\n","import { customElement, bindable, useView, bindingMode, autoinject, containerless, PLATFORM, observable } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { Helpers } from 'application/helpers';\r\n\r\n@customElement('form-input-radio')\r\n@autoinject()\r\nexport class FormInputRadio extends InputBase<string> {\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay })  public value: string;\r\n    @bindable dual = false;\r\n    @bindable options: Array<any> = null;\r\n    @bindable disabled = false;\r\n\r\n    elem: HTMLElement;\r\n\r\n    valueChanged(newVal: string, oldVal: string) {\r\n        if (newVal != oldVal && !!this.elem) {\r\n            Helpers.scrollToElement(this.elem);\r\n        }\r\n    }\r\n\r\n    changeKeydown(event: KeyboardEvent) {\r\n        return Helpers.keypressEnterOrSpace(event, () => this.value = '');\r\n    }\r\n}\r\n","import { customElement, autoinject, bindable } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\n\r\n@customElement('form-input-readonly')\r\n@autoinject()\r\nexport class FormInputText extends InputBase<string> {\r\n    @bindable disabled: boolean = false;\r\n}\r\n","import { customElement, bindable, useView, bindingMode, autoinject, containerless, PLATFORM, observable } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { CountryCodeType } from 'application/gql/createUpdateApplication.tsgql';\r\nimport { Helpers } from 'application/helpers';\r\nimport { Enums } from 'application/enums';\r\n\r\n@customElement('form-input-telephone')\r\n@autoinject()\r\nexport class FormInputTelephone extends InputBase<string> {\r\n    @bindable placeholder = 'Landline or Mobile';\r\n    @bindable({ defaultBindingMode: bindingMode.twoWay }) countryCode: CountryCodeType = CountryCodeType.UNITEDKINGDOM;\r\n\r\n    @bindable disabled: boolean = false;\r\n\r\n    countryCodes = Enums.countryCodes;\r\n\r\n    onKeydown(e: KeyboardEvent) {\r\n        if (Helpers.isNavigationOrSelectionKey(e) || Helpers.isSpaceKey(e)) {\r\n            return true;\r\n        }\r\n\r\n        if (!Helpers.isNumberKey(e)) {\r\n            e.preventDefault();\r\n            return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n}\r\n","import { customElement, bindable, autoinject, computedFrom } from 'aurelia-framework';\r\nimport { InputBase } from '../inputBase';\r\nimport { Helpers } from 'application/helpers';\r\n\r\n@customElement('form-input-text')\r\n@autoinject()\r\nexport class FormInputText extends InputBase<string> {\r\n    @bindable placeholder = '';\r\n    @bindable disabled = false;\r\n    @bindable disablePaste = false;\r\n    @bindable multiline = false;\r\n    @bindable currency = false;\r\n    @bindable preventSpace = false;\r\n    \r\n    onPaste(e: any) {\r\n        if (this.disablePaste) {\r\n            e.preventDefault();\r\n            return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    onKeydown(e: KeyboardEvent) {\r\n        if (this.preventSpace && Helpers.isSpaceKey(e)) {\r\n            e.preventDefault();\r\n            return false;\r\n        }\r\n\r\n        if (this.currency) {\r\n            // allow comma and dot\r\n            if (Helpers.isNavigationOrSelectionKey(e) || e.keyCode === 188 || e.keyCode === 190 || e.keyCode === 110 || e.key === \"£\" || e.key === \"$\" || e.key === \"€\") {\r\n                return true;\r\n            }\r\n    \r\n            if (!Helpers.isNumberKey(e)) {\r\n                e.preventDefault();\r\n                return false;\r\n            }\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    @computedFrom('placeholder')\r\n    get placeholderText() {\r\n        return Helpers.isIE() ? '' : this.placeholder;\r\n    }\r\n}","import {bindable, inject, BindingEngine, customElement, processContent, TargetInstruction, createOverrideContext} from 'aurelia-framework';\r\nimport {ViewCompiler, ViewSlot, ViewResources, Container} from 'aurelia-framework';\r\n\r\n/** Builds the Grid based on the existing template - maybe we can replace this in the future */\r\n/** Currently this builds based on Bootstrap grid template */\r\nimport {Grid} from './grid';\r\nimport {GridTemplate} from './grid-parser';\r\n\r\nexport class GridBuilder {\r\n\tprivate grid: Grid;\r\n\tprivate template: GridTemplate;\r\n\tprivate viewCompiler: ViewCompiler;\r\n\tprivate viewResources: ViewResources;\r\n\tprivate bindingEngine: BindingEngine;\r\n\tprivate container: Container;\r\n\r\n\tprivate element: any;\r\n\r\n\tprivate rowsViewSlot: ViewSlot;\r\n\tprivate rowTemplate: any;\r\n\r\n\tprivate headersViewSlots: ViewSlot[];\r\n\r\n\tprivate pagerViewSlot: ViewSlot;\r\n\r\n\tprivate scrollBarWidth: number = 16;\r\n\r\n\tconstructor(grid: Grid, element: any) {\r\n\t\tthis.grid = grid;\r\n\t\tthis.element = element;\r\n\t\tthis.template = this.grid.template;\r\n\r\n\t\tthis.viewCompiler = this.grid.viewCompiler;\r\n\t\tthis.viewResources = this.grid.viewResources;\r\n\t\tthis.bindingEngine = this.grid.bindingEngine;\r\n\t\tthis.container = this.grid.container;\r\n\t}\r\n\r\n\tbuild() {\r\n\t\t// Listen for window resize so we can re-flow the grid layout\r\n\t\tthis.resizeListener = window.addEventListener('resize', this.headersSyncColumnHeadersWithColumns.bind(this));\r\n\r\n\t\tthis.buildHeadingTemplate();\r\n\t\tthis.buildRowTemplate();\r\n\t\tthis.buildPagerTemplate();\r\n\t}\r\n\r\n\tprivate buildHeadingTemplate(){\r\n\t\tthis.headersViewSlots = [];\r\n\r\n\t\tvar theadTr = this.element.querySelector(\"table.grid-header-table>thead>tr.grid-headings\");\r\n\r\n\t\t// Create the columns headers\r\n\t\tthis.template.columns.forEach(c => {\r\n\t\t\t// each TH has it's own viewSlot so they have different bindings\r\n\t\t\tvar fragment = document.createDocumentFragment();\r\n\r\n\t\t\tvar th = document.createElement(\"th\");\r\n\t\t\tth.setAttribute(\"class\", \"grid-column ${$column.headerClass} ${($column.canSort && $grid.columnsCanSort) ? 'grid-column-sortable': 'grid-column-non-sortable'} ${ $column.class !== '' ? $column.class : '' }\");\r\n\t\t\t\r\n\t\t\tth.innerHTML = c.headingTemplate;\r\n\r\n\t\t\tfragment.appendChild(th);\r\n\r\n\t\t\tvar view = this.viewCompiler.compile(fragment, this.viewResources).create(this.container);\r\n\t\t\tlet bindingContext = {\r\n\t\t\t\t'$grid' : this.grid,\r\n\t\t\t\t'$column' : c,\r\n\t\t\t\t'$p': this.grid.bindingContext\r\n\t\t\t}\r\n\r\n\t\t\tvar context = createOverrideContext(bindingContext, this.grid.bindingContext);\r\n\t\t\tview.bind(this.grid, context);\r\n\r\n\t\t\tvar columnSlot = new ViewSlot(theadTr, true);\r\n\t\t\tcolumnSlot.add(view);\r\n\t\t\tcolumnSlot.attached();\r\n\r\n\t\t\tc.slot = columnSlot;\r\n\t\t\tc.view = view;\r\n\r\n\t\t\tthis.headersViewSlots.push(columnSlot);\r\n\t\t});\r\n\t}\r\n\r\n\tprivate buildRowTemplate() {\r\n\t\t// The table body element will host the rows\r\n\t\tvar tbody = this.element.querySelector(\"table>tbody\");\r\n\t\tthis.rowsViewSlot = new ViewSlot(tbody, true);\r\n\r\n\t\t// Get the row template too and add a repeater/class\r\n\t\tvar row = tbody.querySelector(\"tr\");\r\n\r\n\t\tthis.rowTemplate = document.createDocumentFragment();\r\n\t\tthis.rowTemplate.appendChild(row);\r\n\r\n\t\t// builds <template><tr repeat.for=\"$item of data\">...</template>\r\n\t\trow.setAttribute(\"repeat.for\", \"$item of source.items\");\r\n\t\trow.setAttribute(\"class\", \"${ $item === $grid.selectedItem ? 'info' : '' }\");\r\n\r\n\t\t// TODO: Do we allow the user to customise the row template or just\r\n\t\t// provide a callback?\r\n\t\t// Copy any user specified row attributes to the row template\r\n\t\tfor (var prop in this.template.rowAttributes) {\r\n\t\t\tif (this.template.rowAttributes.hasOwnProperty(prop)) {\r\n\t\t\t\trow.setAttribute(prop, this.template.rowAttributes[prop]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Create a fragment we will manipulate the DOM in\r\n\t\tvar rowTemplate = this.rowTemplate.cloneNode(true);\r\n\t\tvar row = rowTemplate.querySelector(\"tr\");\r\n\r\n\t\t// Create the columns\r\n\t\tthis.template.columns.forEach(col => {\r\n\t\t\tvar td = document.createElement(\"td\");\r\n\r\n\t\t\ttd.innerHTML = col[\"template\"];\r\n\t\t\ttd.className = col[\"class\"];\r\n\t\t\t\r\n\t\t\trow.appendChild(td);\r\n\t\t});\r\n\r\n\t\t// Now compile the row template\r\n\t\tvar view = this.viewCompiler.compile(rowTemplate, this.viewResources).create(this.container);\r\n\r\n\t\tlet bindingContext = { \r\n\t\t\t'$grid': this.grid,\r\n\t\t\t'$p': this.grid.bindingContext\r\n\t\t};\r\n\r\n\t\tvar context = createOverrideContext(bindingContext, this.grid.bindingContext);\r\n\t\tview.bind(this.grid, context);\r\n\r\n\t\tthis.rowsViewSlot.add(view);\r\n\t\tthis.rowsViewSlot.attached();\r\n\t}\r\n\r\n\tprivate buildPagerTemplate(){\r\n\t\t// build the custom template for the pager (if it exists)\r\n\t\t// otherwise the default template will be shown\r\n\t\tvar thost = this.element.querySelector(\"div.grid-footer-custom-container\");\r\n\t\tif(!this.grid.pager.template)\r\n\t\t{\r\n\t\t\t// todo - remove the thost somehow\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.pagerViewSlot = new ViewSlot(thost, true);\r\n\t\tvar template = document.createDocumentFragment();\r\n\t\tvar templateValue = document.createElement('div');\r\n\t\ttemplate.appendChild(templateValue);\r\n\t\ttemplateValue.innerHTML = this.grid.pager.template;\r\n\r\n\t\tvar view = this.viewCompiler.compile(template, this.viewResources).create(this.container);\r\n\t\tlet bindingContext = {\r\n\t\t\t// I'm having problem if I try to use $parent. The template never seems to see that\r\n\t\t\t'$parent': this.grid,\r\n\t\t\t'$grid' : this.grid,\r\n\t\t\t'$pager' : this.grid.pager,\r\n\t\t\t'$source': this.grid.source\r\n\t\t};\r\n\r\n\t\tvar context = createOverrideContext(bindingContext, this.grid.bindingContext);\r\n\t\tview.bind(this.grid, context);\r\n\r\n\t\tthis.pagerViewSlot.add(view);\r\n\t\tthis.pagerViewSlot.attached();\r\n\t}\r\n\r\n\tprivate resizeListener: any;\r\n\tunbind(){\r\n\t\twindow.removeEventListener('resize', this.resizeListener);\r\n\t}\r\n\r\n\theadersSyncColumnHeadersWithColumns() {\r\n\t\t// Get the first row from the data if there is one...\r\n\t\tvar cells = this.element.querySelectorAll(\"table>tbody>tr:first-child>td\");\r\n\r\n\t\tfor (var i = this.grid.gridHeaders.length - 1; i >= 0; i--) {\r\n\t\t\tvar header = this.grid.gridHeaders[i];\r\n\t\t\tvar filter = this.grid.gridFilters[i];\r\n\t\t\tvar cell = cells[i];\r\n\r\n\t\t\tif(cell && header && filter) {\r\n\t\t\t\tvar overflow = this.isBodyOverflowing();\r\n\t\t\t\tvar tgtWidth = cell.offsetWidth + (i == this.grid.gridHeaders.length - 1 && overflow ? this.scrollBarWidth : 0);\r\n\r\n\t\t\t\t// Make the header the same width as the cell...\r\n\t\t\t\theader.setAttribute(\"style\", \"width: \" + tgtWidth + \"px\");\r\n\t\t\t\tfilter.setAttribute(\"style\", \"width: \" + tgtWidth + \"px\");\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\tisBodyOverflowing(): boolean {\r\n\t\tvar container = this.grid.gridContainer;\r\n\t\treturn container.offsetHeight < container.scrollHeight || container.offsetWidth < container.scrollWidth;\r\n\t}\r\n}","import {ViewSlot, View} from 'aurelia-framework';\r\n\r\n/** All Attributes on <grid-col  */\r\nexport class GridColumn{\r\n\theading: string = \"\";\r\n\tfield: string = \"\";\r\n\tclass: string = \"\";\r\n\theaderClass: string = \"\";\r\n\t\r\n\tcanSort: boolean = false;\r\n\t\r\n\tcanFilter: boolean = false;\r\n\tfilterPlaceholder: string = \"\";\r\n\t\r\n\t/** Value for filtering */\r\n\tfilterValue: string = \"\";\r\n\t\r\n\t/** Cell template for rows tbody > tr */\r\n\ttemplate: any;\r\n\r\n\t/** Full HTML template for the heading - either read from <heading>...</heading> or build from the heading attribute */\r\n\theadingTemplate: any;\r\n\r\n\t/** Full HTML template for footers (tfoot) */\r\n\tfooterTemplate: any;\r\n\t\t\r\n\tsorting: string = \"\";\t// asc|desc\r\n\t\r\n\t// internal use\r\n\tslot: ViewSlot;\r\n\tview: View;\r\n\t\r\n\tinit(){\r\n\t\t// we can accept the field to be null if the column has no sorting enabled\r\n\t\tif(this.canSort){\r\n\t\t\tif(!this.field){\r\n\t\t\t\tthrow new Error(`field is required for column ${this.heading} if the column is sortable.`);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif(this.canFilter && !this.filterPlaceholder)\r\n\t\t\tthis.filterPlaceholder = \"filter...\";\r\n\t}\r\n}","import { Grid } from './grid';\r\nimport { GridColumn } from './grid-column';\r\n\r\nimport { IGridDataSource, IGridData, IDataInfo, IDataSortInfo, GridDataSource } from './grid-source';\r\n\r\n/** Remote Source of Grid Data via a function */\r\nexport class DelegateGridData extends GridDataSource {\r\n\tprivate dataRead: (event: IDataInfo) => Promise<any>;\r\n\r\n\tconstructor(grid: Grid) {\r\n\t\tsuper(grid);\r\n\t\tthis.dataRead = grid.sourceRead;\r\n\t\tif (!this.dataRead) {\r\n\t\t\tthrow new Error(\"'data-read.call' is not defined on the grid.\");\r\n\t\t}\r\n\r\n\t\tthis.supportsPagination = this.grid.sourceSupportsPagination;\r\n\t\tthis.supportsSorting = this.grid.sourceSupportsSorting;\r\n\t\tthis.supportsMultiColumnSorting = this.grid.sourceSupportsMultiColumnSorting;\r\n\t}\r\n\r\n\trefresh() {\r\n\r\n\t\tthis.loading = true;\r\n\t\tvar sort = this.sorting.map<IDataSortInfo>(s => {\r\n\t\t\treturn { field: s.field, sorting: s.sorting };\r\n\t\t});\r\n\r\n\t\tvar requestInfo = {\r\n\t\t\tpage: this.page,\r\n\t\t\tpageSize: this.pageSize,\r\n\t\t\tsort: sort\r\n\t\t};\r\n\r\n\t\tif (sort && sort.length > 0) {\r\n\t\t\t// add the default sort field and sort to the default requestInfo\r\n\t\t\tvar s0 = sort[0];\r\n\t\t\trequestInfo[\"field\"] = s0[\"field\"];\r\n\t\t\trequestInfo[\"sorting\"] = s0[\"sorting\"];\r\n\t\t}\r\n\r\n\t\tvar d = this.dataRead(requestInfo);\r\n\r\n\t\tif (!d) {\r\n\t\t\t// uh - no result\r\n\t\t\tthis.count = 0;\r\n\t\t\tthis.items = [];\r\n\t\t\tthis.loading = false;\r\n\t\t\tthis.onData();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (d.then) {\r\n\t\t\td.then(result => {\r\n\t\t\t\tthis.handleResult(result);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t}).catch(error => {\r\n\t\t\t\tif (this.grid.sourceReadError)\r\n\t\t\t\t\tthis.grid.sourceReadError(error);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\tif (Array.isArray(d)) {\r\n\t\t\t\tthis.handleResult(d, true);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t} else {\r\n\t\t\t\tthis.handleResult(d, false);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\tprivate handleResult(result: any, isArray: boolean = false) {\r\n\t\tvar r: IGridData;\r\n\t\tif (this.grid.sourceTransform)\r\n\t\t\tr = this.grid.sourceTransform(result);\r\n\t\telse {\r\n\t\t\tif (isArray) {\r\n\t\t\t\tr = { data: result, count: result.length };\r\n\t\t\t} else {\r\n\t\t\t\tr = <IGridData>result;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (r) {\r\n\t\t\tthis.count = r.count || 0;\r\n\t\t\tthis.items = r.data || [];\r\n\t\t} else{\r\n\t\t\tthis.count = 0;\r\n\t\t\tthis.items = [];\r\n\t\t}\r\n\t\tif(this.count == 0){\r\n\t\t\tthis.page = 1;\r\n\t\t\tthis.pageCount = 0;\r\n\t\t}\r\n\t\tthis.onData();\r\n\t}\r\n}","export class GridIcons{\r\n\trefresh: string = \"fa fa-refresh\";\r\n\t\r\n\tsortingAsc: string = \"fa fa-sort-asc text-primary\";\r\n\tsortingDesc: string = \"fa fa-sort-desc text-primary\";\r\n\t\r\n\tfirstPage: string = \"fa fa-step-backward\";\r\n\tfirstPageTitle: string = \"First page\";\r\n\t\r\n\tprevPage: string = \"fa fa-caret-left\";\r\n\tprevPageTitle: string = \"Previous page\";\r\n\r\n\tnextPage: string = \"fa fa-caret-right\";\r\n\tnextPageTitle: string = \"Next page\";\r\n\r\n\tlastPage: string = \"fa fa-step-forward\";\r\n\tlastPageTitle: string = \"Last page\";\r\n}","import {Grid} from './grid';\r\nimport {GridColumn} from './grid-column';\r\n\r\nimport {IGridDataSource, IGridData, IDataInfo, GridDataSource} from './grid-source';\r\n\r\n/** Local Source of Grid Data - In Memory Paging and Sorting */\r\nexport class LocalGridData extends GridDataSource {\r\n\tsupportsPagination: boolean = true;\r\n\tsupportsSorting: boolean = true;\r\n\tsupportsMultiPageSorting: boolean = true;\r\n\t\r\n\tprivate dataRead: (event: IDataInfo) => Promise<any>;\r\n\tprivate cache: any[];\r\n\tprivate allItems: any[];\r\n\r\n\tconstructor(grid: Grid) {\r\n\t\tsuper(grid);\r\n\t\tthis.dataRead = grid.sourceRead;\r\n\t\tif (!this.dataRead) {\r\n\t\t\tthrow new Error(\"'data-read.call' is not defined on the grid.\");\r\n\t\t}\r\n\t}\r\n\t\r\n\trefresh() {\r\n\t\tthis.loading = true;\r\n\t\tvar d = this.dataRead(null);\r\n        \r\n\t\tif (d.then) {\r\n\t\t\td.then(result=> {\r\n\t\t\t\tthis.handleResult(result);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t}).catch(error=> {\r\n\t\t\t\tif (this.grid.sourceReadError)\r\n\t\t\t\t\tthis.grid.sourceReadError(error);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\tif (Array.isArray(d)) {\r\n\t\t\t\tthis.handleResult(d, true);\r\n\t\t\t\tthis.loading = false;\r\n\t\t\t} else {\r\n                this.handleResult(d, false);\r\n                this.loading = false;\r\n            }\r\n\t\t};\r\n\t}\r\n\r\n\t/** ============ New Data ============== */\r\n\tprivate handleResult(result: any, isArray: boolean = false) {\r\n\t\tvar r: IGridData;\r\n\t\tif (this.grid.sourceTransform)\r\n\t\t\tr = this.grid.sourceTransform(result);\r\n\t\telse {\r\n\t\t\tif (isArray) {\r\n\t\t\t\tr = { data: result, count: result.length };\r\n\t\t\t} else {\r\n\t\t\t\tr = <IGridData>result;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (r) {\r\n\t\t\tthis.allItems = r.data;\r\n\t\t\tthis.cache = this.allItems;\r\n\t\t\tthis.count = r.count;\r\n\r\n\t\t\tthis.filterAndSortLocalData();\r\n\t\t}\r\n\t\tthis.onData();\r\n\t}\r\n\r\n\tprivate filterAndSortLocalData() {\r\n\t\t// Applies filter, sort then page\r\n\t\t// 1. First filter the data down to the set we want, if we are using local data\r\n\t\tvar tempData = this.allItems;\r\n\r\n\t\tif (this.grid.columnsCanFilter)\r\n\t\t\ttempData = this.applyFilter(tempData);\r\n\r\n\t\t// 2. Now sort the data\r\n\t\tif (this.grid.columnsCanSort)\r\n\t\t\ttempData = this.applySort(tempData);\r\n\r\n\t\t// 3. Now apply paging\r\n\t\ttempData = this.applyPage(tempData);\r\n\r\n\t\tthis.items = tempData;\r\n\r\n\t\tthis.updatePager();\r\n\r\n\t\tthis.watchForChanges();\r\n\r\n\t\tsetTimeout(() => this.grid.builder.headersSyncColumnHeadersWithColumns.bind(this), 0);\r\n\t}\r\n\r\n\r\n\t/** ============ Filtering ============== */\r\n\tprivate applyFilter(data: any[]): any[] {\r\n\t\treturn data.filter((row) => {\r\n\t\t\tvar include = true;\r\n\r\n\t\t\tfor (var i = this.grid.template.columns.length - 1; i >= 0; i--) {\r\n\t\t\t\tvar col = this.grid.template.columns[i];\r\n\r\n\t\t\t\tif (col.filterValue !== \"\" && row[col.field].toString().indexOf(col.filterValue) === -1) {\r\n\t\t\t\t\tinclude = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn include;\r\n\t\t});\r\n\t}\r\n\r\n\tprivate getFilterColumns() {\r\n\t\tvar cols = {};\r\n\r\n\t\tfor (var i = this.grid.template.columns.length - 1; i >= 0; i--) {\r\n\t\t\tvar col = this.grid.template.columns[i];\r\n\r\n\t\t\tif (col.filterValue !== \"\")\r\n\t\t\t\tcols[col.field] = col.filterValue;\r\n\t\t}\r\n\r\n\t\treturn cols;\r\n\t}\r\n\r\n\r\n\tprivate applySort(data: any[]): any[] {\r\n\t\t//Format the sort fields\r\n\t\tvar fields = [];\r\n\r\n\t\t// Get the fields in the \"sortingORder\"\r\n\t\tfor (var i = 0; i < this.sorting.length; i++) {\r\n\t\t\tvar col = this.sorting[i];\r\n\t\t\tfields.push(col.sorting === \"asc\" ? (col.field) : (\"-\" + col.field));\r\n\t\t};\r\n\r\n\t\tif (this.sorting.length > 0)\r\n\t\t\treturn this.allItems.sort(this.fieldSorter(fields));\r\n\t\telse\t// don't go through sort as it messses up data\r\n\t\t\treturn data;\r\n\t}\r\n\r\n\tprivate fieldSorter(fields) {\r\n\t\treturn function(a, b) {\r\n\t\t\treturn fields\r\n\t\t\t\t.map(function(o) {\r\n\t\t\t\t\tvar dir = 1;\r\n\t\t\t\t\tif (o[0] === '-') {\r\n\t\t\t\t\t\tdir = -1;\r\n\t\t\t\t\t\to = o.substring(1);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (a[o] > b[o]) return dir;\r\n\t\t\t\t\tif (a[o] < b[o]) return -(dir);\r\n\t\t\t\t\treturn 0;\r\n\t\t\t\t})\r\n\t\t\t\t.reduce(function firstNonZeroValue(p, n) {\r\n\t\t\t\t\treturn p ? p : n;\r\n\t\t\t\t}, 0);\r\n\t\t};\r\n\t}\r\n\r\n\t/** ============ Pagination ============== */\r\n\tprivate applyPage(data: any[]): any[] {\r\n\t\tvar start = (Number(this.page) - 1) * Number(this.pageSize);\r\n\r\n\t\tdata = data.slice(start, start + Number(this.pageSize));\r\n\r\n\t\treturn data;\r\n\t}\r\n\r\n\t/** ============ Monitoring ============== */\r\n\tprivate subscription: any;\r\n\t/** Watch for changes to the data */\r\n\tprivate watchForChanges() {\r\n\t\tthis.dontWatchForChanges();\r\n\r\n\t\tif (!this.grid.unbinding) {\r\n\t\t\t// We can update the pager automagically\r\n\t\t\tthis.subscription = this.grid.bindingEngine\r\n\t\t\t\t.collectionObserver(this.cache)\r\n\t\t\t\t.subscribe((splices) => {\r\n\t\t\t\t\tthis.refresh();\r\n\t\t\t\t});\r\n\t\t}\r\n\t}\r\n\tprivate dontWatchForChanges() {\r\n\t\tif (this.subscription) {\r\n\t\t\tthis.subscription.dispose();\r\n\t\t\tthis.subscription = null;\r\n\t\t}\r\n\t}\r\n\r\n\tunbind() {\r\n\t\tsuper.unbind();\r\n\t\tthis.dontWatchForChanges();\r\n\t}\r\n}","import {bindable, inject, BindingEngine, customElement, processContent, TargetInstruction} from 'aurelia-framework';\r\nimport {ViewCompiler, ViewSlot, ViewResources, Container} from 'aurelia-framework';\r\n\r\nimport {Grid} from './grid';\r\nimport {IGridDataSource} from './grid-source';\r\n\r\nexport class GridPager {\r\n\t// replaced template (if defined - otherwise we use our standard template)\r\n\ttemplate: any;\r\n\tgrid: Grid;\r\n\r\n\tenabled: boolean = true;\r\n\t\r\n\t/** number of pages to show in the pager */\r\n\t@bindable numPagesToShow: number = 5;\r\n\t@bindable showFirstLast: boolean = true;\r\n\t@bindable showJump: boolean = true;\r\n\t@bindable showPagingSummary: boolean = true;\r\n\t\r\n\t// CSV with page sizes\r\n\t@bindable pageSizes: number[] = [10, 25, 50];\r\n\r\n\t@bindable nextDisabled: boolean = false;\r\n\t@bindable prevDisabled: boolean = false;\r\n\r\n\t@bindable firstVisibleItem: number = 0;\r\n\t@bindable lastVisibleItem: number = 0;\r\n\t\r\n\t@bindable autoHide: boolean = false;\r\n\r\n\tpages = [];\r\n\t\r\n\tconstructor() {\r\n\t}\r\n\r\n\trefresh() {\r\n\t\tif (!this.grid.source)\r\n\t\t\treturn;\t// no source?\r\n\t\t\r\n\t\t// something changed in the data - recalculate\r\n\t\t// Cap the number of pages to render if the count is less than number to show at once\r\n\t\tvar numToRender = this.grid.source.pageCount < this.numPagesToShow ? this.grid.source.pageCount : this.numPagesToShow;\r\n\r\n\t\t// The current page should try to appear in the middle, so get the median \r\n\t\t// of the number of pages to show at once - this will be our adjustment factor\r\n\t\tvar indicatorPosition = Math.ceil(numToRender / 2);\r\n\r\n\t\t// Subtract the pos from the current page to get the first page no\r\n\t\tvar firstPageNumber = this.grid.source.page - indicatorPosition + 1;\r\n\r\n\t\t// If the first page is less than 1, make it 1\r\n\t\tif (firstPageNumber < 1)\r\n\t\t\tfirstPageNumber = 1;\r\n\r\n\t\t// Add the number of pages to render\r\n\t\t// remember to subtract 1 as this represents the first page number\r\n\t\tvar lastPageNumber = firstPageNumber + numToRender - 1;\r\n\r\n\t\t// If the last page is greater than the page count\r\n\t\t// add the difference to the first/last page\r\n\t\tif (lastPageNumber > this.grid.source.pageCount) {\r\n\t\t\tvar dif = this.grid.source.pageCount - lastPageNumber;\r\n\r\n\t\t\tfirstPageNumber += dif;\r\n\t\t\tlastPageNumber += dif;\r\n\t\t}\r\n\r\n\t\tvar pages = [];\r\n\r\n\t\tfor (var i = firstPageNumber; i <= lastPageNumber; i++) {\r\n\t\t\tpages.push(i);\r\n\t\t};\r\n\r\n\t\tthis.pages = pages;\r\n\r\n\t\tif(this.grid.source.count > 0)\r\n\t\t{\r\n\t\t\tthis.firstVisibleItem = (this.grid.source.page - 1) * Number(this.grid.source.pageSize) + 1;\r\n\t\t\tthis.lastVisibleItem = Math.min((this.grid.source.page) * Number(this.grid.source.pageSize), this.grid.source.count);\r\n\t\t} else{\r\n\t\t\tthis.firstVisibleItem = 0;\r\n\t\t\tthis.lastVisibleItem = 0;\r\n\t\t\tthis.pages = [];\r\n\t\t}\r\n\r\n\t\tthis.updateButtons();\r\n\t}\r\n\r\n\tupdateButtons() {\r\n\t\tthis.nextDisabled = this.grid.source.page >= this.grid.source.pageCount;\r\n\t\tthis.prevDisabled = this.grid.source.page <= 1;\r\n\t}\r\n\r\n\t// pageSizeChanged(newValue: number, oldValue: number) {\r\n\t// \tdebugger;\r\n\t// \tif (newValue == oldValue)\r\n\t// \t\treturn;\r\n\t// \tthis.grid.source.pageSize = newValue;\r\n\t// \tthis.grid.source.refresh();\r\n\t// }\r\n\r\n\tchangePage(page: number) {\r\n\t\tvar oldPage = this.grid.source.page;\r\n\r\n\t\tthis.grid.source.page = this.validate(page);\r\n\r\n\t\tif (oldPage !== this.grid.source.page) {\r\n\t\t\tthis.grid.source.refresh();\r\n\t\t}\r\n\t}\r\n\r\n\tnext() {\r\n\t\tthis.changePage(this.grid.source.page + 1);\r\n\t}\r\n\r\n\tnextJump() {\r\n\t\tthis.changePage(this.grid.source.page + this.numPagesToShow);\r\n\t}\r\n\r\n\tprev() {\r\n\t\tthis.changePage(this.grid.source.page - 1);\r\n\t}\r\n\r\n\tprevJump() {\r\n\t\tthis.changePage(this.grid.source.page - this.numPagesToShow);\r\n\t}\r\n\r\n\tfirst() {\r\n\t\tthis.changePage(1);\r\n\t}\r\n\r\n\tlast() {\r\n\t\tthis.changePage(this.grid.source.pageCount);\r\n\t}\r\n\r\n\tprivate validate(page: number): number {\r\n\t\tif (page < 1)\r\n\t\t\treturn 1;\r\n\t\tif (page > this.grid.source.pageCount)\r\n\t\t\treturn this.grid.source.pageCount;\r\n\r\n\t\treturn page;\r\n\t}\r\n}\r\n","import {GridColumn} from './grid-column';\r\nimport {GridRowAttributes} from './grid-row';\r\nimport {GridPager} from './grid-pager';\r\nimport {LogManager} from 'aurelia-framework';\r\n\r\nexport interface GridTemplate {\r\n\tcolumns: GridColumn[];\r\n\trowAttributes: GridRowAttributes;\r\n\tpager: GridPager;\r\n}\r\n\r\n/** Helper to do the parsing of the grid content */\r\nexport class GridParser {\r\n\tparse(element: any): GridTemplate {\r\n\t\tvar result = {\r\n\t\t\tcolumns: this.parseGridCols(element),\r\n\t\t\trowAttributes: this.parseGridRow(element),\r\n\t\t\tpager: this.parseGridPager(element)\r\n\t\t};\r\n\r\n\t\treturn result;\r\n\t}\r\n\tprivate parseGridCols(element: any): GridColumn[] {\r\n\t\tvar rowElement = element.querySelector(\"grid-row\");\r\n\t\tif(!rowElement){\r\n\t\t\tLogManager.getLogger(\"aurelia-grid\").warn(\"Grid has no <grid-row> defined\");\r\n\t\t\treturn [];\r\n\t\t}\r\n\t\tvar columnElements = Array.prototype.slice.call(rowElement.querySelectorAll(\"grid-col\"));\r\n\t\tvar cols = [];\r\n\r\n\t\tvar columnTemplate =\r\n\t\t\t'<div class=\"grid-column-header\" click.trigger=\"$grid.source.sortChanged($column, $event)\"><span class=\"grid-column-heading\">${$column.heading}</span>' +\r\n\t\t\t'<span if.bind=\"$column.sorting === \\'desc\\'\" class=\"${$grid.icons.sortingDesc}\"></span>' +\r\n\t\t\t'<span if.bind=\"$column.sorting === \\'asc\\'\" class=\"${$grid.icons.sortingAsc}\"></span></div>';\r\n\r\n\t\t// <grid-col can-sort=\"true\" heading=\"header\"> ..\r\n\t\t// or <grid-col can-sort=\"true\"><heading>header template</heading><template>cell template</template> \r\n\t\tcolumnElements.forEach(c => {\r\n\t\t\tvar col = new GridColumn();\r\n\r\n\t\t\tvar attrs = Array.prototype.slice.call(c.attributes);\r\n\t\t\tattrs.forEach(a => this.tryAssign(col, this.camelCaseName(a.name), a.value));\r\n\r\n\t\t\t// check for inner <heading> of template\r\n\t\t\tvar headingTemplate = c.querySelector(\"heading\");\r\n\t\t\tcol.headingTemplate = (headingTemplate && headingTemplate.innerHTML) ? headingTemplate.innerHTML : columnTemplate;\r\n\t\t\r\n\t\t\t// check for inner content of <template> or use full content as template\r\n\t\t\tvar cellTemplate = c.querySelector(\"template\");\r\n\t\t\tcol.template = (cellTemplate && cellTemplate.innerHTML) ? cellTemplate.innerHTML : c.innerHTML;\r\n\r\n\t\t\tvar footerTemplate = c.querySelector(\"footer\");\r\n\t\t\tcol.footerTemplate = (footerTemplate && footerTemplate.innerHTML) ? footerTemplate.innerHTML : null;\r\n\r\n\t\t\tcol.init();\r\n\t\t\tcols.push(col);\r\n\t\t});\r\n\r\n\t\treturn cols;\r\n\t}\r\n\t\r\n\tprivate parseGridRow(element: any): GridRowAttributes {\r\n\t\t// Pull any row attrs into a hash object\r\n\t\tvar rowsAttributes = new GridRowAttributes();\r\n\r\n\t\tvar rowElement = element.querySelector(\"grid-row\");\r\n\t\tif(!rowElement){\r\n\t\t\tLogManager.getLogger(\"aurelia-grid\").warn(\"Grid has no <grid-row> defined\");\r\n\t\t\treturn rowsAttributes;\r\n\t\t}\r\n\t\t\r\n\t\tvar attrs = Array.prototype.slice.call(rowElement.attributes);\r\n\t\tattrs.forEach(a => rowsAttributes[a.name] = a.value);\r\n\r\n\t\treturn rowsAttributes;\r\n\t}\r\n\r\n\tprivate parseGridPager(element: any): GridPager {\r\n\t\tvar pagerElement = element.querySelector(\"grid-pager\");\r\n\t\tvar pager = new GridPager();\r\n\t\tif(!pagerElement){\r\n\t\t\treturn pager;\r\n\t\t}\r\n\t\t// fill in all properties\r\n\t\tvar attrs = Array.prototype.slice.call(pagerElement.attributes);\r\n\t\tattrs.forEach(a =>\r\n\t\t{ \r\n\t\t\tthis.tryAssign(pager, this.camelCaseName(a.name), a.value);\r\n\t\t});\r\n\t\t\r\n\t\tvar template = pagerElement.querySelector(\"template\");\r\n\t\tpager.template = (template && template.innerHTML) ? template.innerHTML : null;\r\n\t\t\r\n\t\treturn pager;\r\n\t}\r\n\r\n\tprivate camelCaseName(name: string): string {\r\n\t\treturn name.replace(/-([a-z])/g, function(g) { return g[1].toUpperCase(); });\r\n\t};\r\n\t\r\n\tprivate tryAssign(target: any, name: string, value: string){\r\n\t\tvar existing = target[name];\r\n\t\tswitch(typeof existing){\r\n\t\t\tcase 'boolean':\r\n\t\t\t\ttarget[name] = (value == 'true');\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'number':\r\n\t\t\t\ttarget[name] = parseInt(value);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\ttarget[name] = value;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}","/** Really, any attributes will be carried accros */\r\nexport class GridRowAttributes{\r\n}","import {Grid} from './grid';\r\n\r\nexport class GridSelection{\r\n\tprivate grid: Grid;\r\n\tconstructor(grid: Grid){\r\n\t\tthis.grid = grid;\r\n\t}\r\n\t\r\n\tselect(item: any, event){\r\n\t\t// TODO: if multi-selection check event for shift pressed\r\n\t\tthis.grid.selectedItem = item;\r\n\t\treturn true;\r\n\t}\r\n}","import {Grid} from './grid';\r\nimport {GridColumn} from './grid-column';\r\n\r\nexport interface IGridDataSource {\r\n\tsupportsPagination: boolean;\r\n\tsupportsSorting: boolean;\r\n\tsupportsMultiColumnSorting: boolean;\r\n\r\n\tcount: number;\r\n\titems: any[];\r\n\tloading: boolean;\r\n\r\n\t/** 1 - first page */\r\n\tpage: number;\r\n\t/** 10 - default page size */\r\n\tpageSize: number;\r\n\tpageCount: number;\r\n\r\n\t/** Dictionary of sorting name:asc|desc  */\r\n\tsorting: Array<GridColumn>;\r\n\r\n\t/** grid was attached - start loading & monitoring for changes */\r\n\tattached();\r\n\t/** trigger a refresh */\r\n\trefresh();\r\n\t/** unbind - stop loading and monitoring for changes */\r\n\tunbind();\r\n\r\n\t/** Trigger a sort changed - FIX: event for now is the click event */\r\n\tsortChanged(column: GridColumn, event);\r\n}\r\n\r\n/** Shape of the result data */\r\nexport interface IGridData {\r\n\tcount: number;\r\n\tdata: any[];\r\n}\r\n\r\n/** Used in the read callback to ask the local data source for data */\r\nexport interface IDataInfo {\r\n\t/** 1 - first page */\r\n\tpage: number;\r\n\t/** 10 - default page size */\r\n\tpageSize: number;\r\n    /** sort information */\r\n    sort: IDataSortInfo[];\r\n}\r\n\r\nexport interface IDataSortInfo{\r\n    field: string;\r\n    sorting: string;    // asc|desc\r\n}\r\n\r\nexport class GridDataSource implements IGridDataSource {\r\n\tsupportsPagination: boolean = false;\r\n\tsupportsSorting: boolean = false;\r\n\tsupportsMultiColumnSorting: boolean = false;\r\n\r\n\tcount: number = 0;\r\n\titems: any[];\r\n\tloading: boolean;\r\n\r\n\tpage: number = 1;\r\n\tpageSize: number;\r\n\tpageCount: number = 0;\r\n\r\n\tsorting: Array<GridColumn> = new Array<GridColumn>();\r\n\r\n\tprotected grid: Grid;\r\n\r\n\tconstructor(grid: Grid) {\r\n\t\tthis.grid = grid;\r\n\t}\r\n\r\n\r\n\tattached() {\r\n\t\tthis.page = 1;\r\n\r\n\t\tif (this.grid.pager && this.grid.pager.pageSizes)\r\n\t\t\tthis.pageSize = this.grid.pager.pageSizes[0];\r\n\t\telse\r\n\t\t\tthis.pageSize = 10;\r\n\r\n\t\t// process page sizes\r\n\t\tif (this.grid.sourceAutoLoad) {\r\n\t\t\tthis.refresh();\r\n\t\t}\r\n\t}\r\n\trefresh() {\r\n\t\tthrow new Error(\"Data source does not implement read?\");\r\n\t}\r\n\r\n\tupdatePager() {\r\n\t\t// TODO:\r\n\t}\r\n\r\n\tonData() {\r\n\t\tif (this.pageSize == 0)\r\n\t\t\tthis.pageSize = 10;\r\n\t\tthis.pageCount = Math.ceil(this.count / this.pageSize);\r\n\t\tthis.grid.pager.refresh();\r\n\t}\r\n\r\n\tunbind() {\r\n\t}\r\n\r\n\t/** Events from Aurelia */\r\n\tpageSizeChanged(newValue: number, oldValue: number) {\r\n\t\tif(newValue == oldValue)\r\n\t\t\treturn;\r\n\t\tthis.refresh();\r\n\t}\r\n\r\n\t/** ============ Sorting ============== */\r\n\tsortChanged(column: GridColumn, event) {\r\n\t\tif(!column.canSort)\r\n\t\t\treturn;\r\n\t\t\t\r\n\t\t// Determine new sort\r\n\t\tvar newSort = undefined;\r\n\r\n\t\t// Figure out which way this field should be sorting\r\n\t\tswitch (column.sorting) {\r\n\t\t\tcase \"asc\":\r\n\t\t\t\tnewSort = \"desc\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"desc\":\r\n\t\t\t\tnewSort = \"\";\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tnewSort = \"asc\";\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif (!event.ctrlKey || !this.supportsMultiColumnSorting) {\r\n\t\t\tthis.sorting.forEach(s=> s.sorting = \"\");\r\n\t\t\tthis.sorting = [];\r\n\t\t}\r\n\r\n\t\tcolumn.sorting = newSort;\r\n\r\n\t\t// If the sort is present in the sort stack, slice it to the back of the stack, otherwise just add it\r\n\t\tvar pos = this.sorting.indexOf(column);\r\n\r\n\t\tif (pos > -1)\r\n\t\t\tthis.sorting.splice(pos, 1);\r\n\r\n\t\tif (newSort)\r\n\t\t\tthis.sorting.push(column);\r\n\r\n\t\t// Apply the new sort\r\n\t\tthis.refresh();\r\n\t}\r\n}\r\n","import {noView, children, bindable, child, inject, BindingEngine, customElement, processContent, TargetInstruction, useView, PLATFORM} from 'aurelia-framework';\r\nimport {ViewCompiler, ViewSlot, ViewResources, Container} from 'aurelia-framework';\r\n\r\nimport {GridColumn} from './grid-column';\r\nimport {GridRowAttributes} from './grid-row';\r\nimport {GridSelection} from './grid-selection';\r\nimport {GridBuilder} from './grid-builder';\r\nimport {GridIcons} from './grid-icons';\r\nimport {GridPager} from './grid-pager';\r\n\r\nimport {GridTemplate, GridParser} from './grid-parser';\r\nimport * as D from './grid-source';\r\nimport {LocalGridData} from './grid-local-source';\r\nimport {DelegateGridData} from './grid-delegate-source';\r\n\r\n@customElement('grid')\r\n@useView(PLATFORM.moduleName('./grid.html'))\r\n@processContent(function(viewCompiler, viewResources, element, instruction) {\r\n\tvar result = processUserTemplate(element);\r\n\t\r\n\tinstruction.columns = result.columns;\r\n\tinstruction.rowAttributes = result.rowAttributes;\r\n\tinstruction.pager = result.pager;\r\n\r\n\treturn true;\r\n})\r\n@inject(Element, ViewCompiler, ViewResources, Container, TargetInstruction, BindingEngine)\r\nexport class Grid{\r\n\tprivate element: any;\r\n\tprivate targetInstruction: TargetInstruction;\r\n\tviewCompiler: ViewCompiler;\r\n\tviewResources: ViewResources;\r\n\tbindingEngine: BindingEngine;\r\n\tcontainer: Container;\r\n\t\r\n\ttemplate: GridTemplate;\r\n\t\r\n\t// Columns\r\n\t@bindable columnsShowHeaders: boolean = true;\r\n\t@bindable columnsCanSort: boolean = true;\r\n\t@bindable columnsCanFilter: boolean = false;\r\n\t\r\n\t// Visuals\r\n\t@bindable gridHeight: number;\r\n\t@bindable icons: GridIcons;\r\n\t\r\n\tselection: GridSelection;\r\n\t@bindable selectedItem: any;\r\n\t\r\n\tbuilder: GridBuilder;\r\n\t\r\n\t// Data Source\r\n\t@bindable source: D.IGridDataSource;\r\n\t@bindable sourceAutoLoad: boolean = true;\r\n\t@bindable sourceType: string;\t// local, remote\r\n\t@bindable sourceRead: (event: D.IDataInfo) => Promise<any>;\r\n\t/** allow the client to pre-process the data to get it in the right shape in case the data is not in the expected shape */\r\n\t@bindable sourceTransform: (result: any) => D.IGridData;\r\n\t@bindable sourceReadError: (result: any) => void;\r\n\t@bindable sourceLoadingMessage: string = \"Loading ...\";\r\n\t\r\n\t// Potential overrides (might not apply!!!) as some sources have their own definition of supports\r\n\t// these only really work for the delegate and remote sources\r\n\t@bindable sourceSupportsPagination: boolean = false;\r\n\t@bindable sourceSupportsSorting: boolean = false;\r\n\t@bindable sourceSupportsMultiColumnSorting: boolean = false;\r\n\r\n\t// no-data-message=\"No data\"\r\n\t@bindable noDataMessage: string = \"\";\r\n\t\r\n\tpager: GridPager;\r\n\t\r\n\tbindingContext: any;\r\n\r\n\tconstructor(element: Element, vc: ViewCompiler, vr: ViewResources, container: Container, targetInstruction: TargetInstruction, bindingEngine: BindingEngine) {\r\n\t\tthis.element = element;\r\n\t\tthis.viewCompiler = vc;\r\n\t\tthis.viewResources = vr;\r\n\t\tthis.container = container;\r\n\t\tthis.bindingEngine = bindingEngine;\r\n\r\n\t\tthis.template = <GridTemplate>((<any>targetInstruction).behaviorInstructions[0]);\r\n\t\tthis.pager = this.template.pager;\r\n\t\tthis.pager.grid = this;\r\n\t\t\r\n\t\tthis.selection = new GridSelection(this);\r\n\t\tthis.builder = new GridBuilder(this, this.element);\r\n\t}\r\n\r\n\tunbinding: boolean = false;\r\n\tbind(bindingContext, overrideBindingContext){\r\n\t\tthis.bindingContext = bindingContext;\r\n\t\r\n\t\t// todo - make glyphicons and fa icons classes\r\n\t\tthis.icons = new GridIcons();\r\n\t\t\r\n\t\tswitch(this.sourceType)\r\n\t\t{\r\n\t\t\tcase \"remote\":{\r\n\t\t\t\t// todo:\r\n\t\t\t\tthrow new Error(\"Remote data source not supported\");\r\n\t\t\t}\r\n\t\t\tcase \"delegate\":{\r\n\t\t\t\tthis.source = new DelegateGridData(this);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:{\r\n\t\t\t\t// local\r\n\t\t\t\tthis.source = new LocalGridData(this);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tthis.builder.build();\r\n\t}\r\n\t\r\n\tunbind(){\r\n\t\tthis.unbinding = true;\r\n\t\tthis.builder.unbind();\r\n\t\tthis.source.unbind();\r\n\t}\r\n\t\r\n\tattached(){\r\n\t\tthis.gridHeightChanged();\r\n\t\tthis.pager.refresh();\r\n\t\t\r\n\t\t// fix pageSize\r\n\t\tthis.pageSize = this.pager.pageSizes[0];\r\n\t\tthis.source.pageSize = this.pageSize;\r\n\t\t\r\n\t\tthis.source.attached();\r\n\t}\r\n\t\r\n\t\r\n\t/* ==== Visual Handling ===== */\r\n\tgridHeightChanged() {\r\n\t\tif(this.gridHeight > 0) {\r\n\t\t\tthis.gridContainer.setAttribute(\"style\", \"height:\" + this.gridHeight + \"px\");\r\n\t\t} else {\r\n\t\t\tthis.gridContainer.removeAttribute(\"style\");\r\n\t\t}\r\n\t}\r\n\t\r\n\trefresh(resetPage?: boolean){\r\n\t\t// use reset when you want to start searches\r\n\t\tif(resetPage)\r\n\t\t\tthis.source.page = 1;\r\n\r\n\t\tthis.source.refresh();\r\n\t}\r\n\t\r\n\t@bindable pageSize: number = 25;\r\n\tpageSizeChanged(newValue: number, oldValue: number){\r\n\t\tif(this.source.pageSize == this.pageSize)\r\n\t\t\treturn;\r\n\t\tthis.source.pageSize = newValue;\r\n\t\tthis.source.refresh();\r\n\t}\r\n\t\r\n\t/** Cached Properties */\r\n\tprivate _gridContainer: any;\r\n\tget gridContainer(): any{\r\n\t\tthis._gridContainer = this._gridContainer || this.element.querySelector(\".grid-content-container\");\r\n\t\treturn this._gridContainer;\r\n\t}\r\n\tprivate _gridHeaders: any;\r\n\tget gridHeaders(): any{\r\n\t\tif(!this._gridHeaders)\r\n\t\t\tthis._gridHeaders = this.element.querySelectorAll(\"table>thead>tr:first-child>th\");\r\n\t\treturn this._gridHeaders;\r\n\t}\r\n\tprivate _gridFilters: any;\r\n\tget gridFilters(): any{\r\n\t\tif(!this._gridFilters)\r\n\t\t\tthis._gridFilters = this.element.querySelectorAll(\"table>thead>tr:last-child>th\");\r\n\t\treturn this._gridFilters;\r\n\t}\r\n}\r\nfunction processUserTemplate(element: any): GridTemplate{\r\n\tvar parser = new GridParser();\r\n\treturn parser.parse(element);\t\r\n}\r\n"],"names":[],"sourceRoot":""}