From: Alex Sadleir Date: Sat, 19 Jan 2013 13:22:22 +0000 Subject: Merge branch 'master' of ssh://apples.lambdacomplex.org/git/scannr X-Git-Url: http://maxious.lambdacomplex.org/git/?p=scannr.git&a=commitdiff&h=e2a40f793bb5cc73cc423d9abd00fa43566174c7 --- Merge branch 'master' of ssh://apples.lambdacomplex.org/git/scannr Conflicts: .idea/workspace.xml generateHourlys.php --- --- /dev/null +++ b/.idea/sqldialects.xml @@ -1,1 +1,8 @@ + + + + + + + --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,7 +2,6 @@ - --- a/.idea/workspace.xml +++ /dev/null @@ -1,497 +1,1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1350026709905 - 1350026709905 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --- a/README.md +++ /dev/null @@ -1,64 +1,1 @@ -# [HTML5 Boilerplate](http://html5boilerplate.com) -HTML5 Boilerplate is a professional front-end template for building fast, -robust, and adaptable web apps or sites. - -This project is the product of many years of iterative development and combined -community knowledge. It does not impose a specific development philosophy or -framework, so you're free to architect your code in the way that you want. - -* Source: [https://github.com/h5bp/html5-boilerplate](https://github.com/h5bp/html5-boilerplate) -* Homepage: [http://html5boilerplate.com](http://html5boilerplate.com) -* Twitter: [@h5bp](http://twitter.com/h5bp) - - -## Quick start - -Choose one of the following options: - -1. Download the latest stable release from - [html5boilerplate.com](http://html5boilerplate.com/) or a custom build from - [Initializr](http://www.initializr.com). -2. Clone the git repo — `git clone - https://github.com/h5bp/html5-boilerplate.git` - and checkout the tagged - release you'd like to use. - - -## Features - -* HTML5 ready. Use the new elements with confidence. -* Cross-browser compatible (Chrome, Opera, Safari, Firefox 3.6+, IE6+). -* Designed with progressive enhancement in mind. -* Includes [Normalize.css](http://necolas.github.com/normalize.css/) for CSS - normalizations and common bug fixes. -* The latest [jQuery](http://jquery.com/) via CDN, with a local fallback. -* The latest [Modernizr](http://modernizr.com/) build for feature detection. -* IE-specific classes for easier cross-browser control. -* Placeholder CSS Media Queries. -* Useful CSS helpers. -* Default print CSS, performance optimized. -* Protection against any stray `console.log` causing JavaScript errors in - IE6/7. -* An optimized Google Analytics snippet. -* Apache server caching, compression, and other configuration defaults for - Grade-A performance. -* Cross-domain Ajax and Flash. -* "Delete-key friendly." Easy to strip out parts you don't need. -* Extensive inline and accompanying documentation. - - -## Documentation - -Take a look at the [documentation table of -contents](/h5bp/html5-boilerplate/blob/master/doc/README.md). This -documentation is bundled with the project, which makes it readily available for -offline reading and provides a useful starting point for any documentation -you want to write about your project. - - -## Contributing - -Anyone and everyone is welcome to -[contribute](/h5bp/html5-boilerplate/blob/master/doc/contribute.md). Hundreds -of developers have helped make the HTML5 Boilerplate what it is today. - --- a/README.txt +++ /dev/null @@ -1,1 +1,1 @@ -ffmpeg from http://ffmpeg.zeranoe.com/builds/ + --- a/common.inc.php +++ b/common.inc.php @@ -57,12 +57,20 @@ + + + + + + + + + + + + +
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + --- a/db.sql +++ b/db.sql @@ -92,4 +92,22 @@ -- PostgreSQL database dump complete -- +CREATE TABLE "compilation" ( + "filename" text NOT NULL, + "files" text ARRAY NOT NULL, + "datetime" timestamp NOT NULL +); +CREATE TABLE "trunk_log" ( + "id" text NOT NULL, + "datetime" integer NOT NULL, + "site" integer NOT NULL, + "action" text NOT NULL, + "sourcetype" character(1) NOT NULL, + "sourceid" smallint NOT NULL, + "targettype" character(1) NOT NULL, + "targetid" smallint NOT NULL, + "channel" smallint NOT NULL, + "calltype" text NOT NULL +); + --- a/generateConvos.php +++ /dev/null @@ -1,36 +1,1 @@ -prepare('select * from recordings limit 100;'); -$sth->execute(); -$recordings = $sth->fetchAll(); -$convos = Array(); -$convo = Array(); -foreach ($recordings as $i => $recording) { - - if (count($convo) > 0) { - echo "
" . strcasecmp($convos[count($convos) - 1][0]['call_timestamp'], $recording['call_timestamp']); - if (abs(strcasecmp($convos[count($convos) - 1][0]['call_timestamp'], $recording['call_timestamp'])) > 2) { - echo " " . $convos[count($convos) - 1][0]['call_timestamp'] . " " . $recording['call_timestamp']; - } - if (strcasecmp($convos[count($convos) - 1][0]['tgid'], $recording['tgid']) != 0) { - $convos[] = $convo; - $convo = Array(); - } - } - ; - //print_r($recording); - $convo[] = $recording; - //print_r($convo); - //echo "
\n"; -} -foreach ($convos as $i => $convo) { - foreach ($convo as $recording) { - echo $recording['filename'] . " , "; - } - echo "

\n"; -} -?> - - --- a/generateHourlys.php +++ b/generateHourlys.php @@ -3,25 +3,36 @@ function processHourly($hourly) { $filename = str_replace(' ',"_",$hourly['tgid']).'-'.str_replace(' 00:00:00+1','',$hourly['aday']).'-'.$hourly['ahour'].'.3gp'; - if(!file_exists("hourly/".$filename)) { + $hfilename = $hourly['tgid'] . '-' . str_replace(' 00:00:00+10', '', $hourly['aday']) . '-' . $hourly['ahour'] . '.3gp'; - $filenames = explode(",",$hourly['filenames']); - $cmd = "/usr/local/bin/ffmpeg -filter_complex concat=n=".count($filenames).":v=0:a=1 -i data/".implode(" -i data/",$filenames)." -ar 8000 -ab 4.75k -ac 1 hourly/".$filename . ' 2>&1'; + if (!file_exists("hourly/" . $hfilename)) { + + $filenames = explode(",", $hourly['filenames']); + $cmd = "/usr/local/bin/ffmpeg -filter_complex concat=n=" . count($filenames) . ":v=0:a=1 -i data/" . implode(" -i data/", $filenames) . " -ar 8000 -ab 4.75k -ac 1 hourly/" . $hfilename . ' 2>&1'; //print_r($hourly); - exec ( $cmd,$output,$returncode ); - echo $cmd."
\n"; + exec($cmd, $output, $returncode); + echo $cmd . "
\n"; if ($returncode != 10) { - //print_r($output); + print_r($output); //die(); + } else { + $q = " insert into compilations (filename files datetime) ('" . $hfilename . "',{'" . implode("', '", $filenames) . "'},'" . strtottime($hourly['aday'] . ' +' . $hourly['ahour'] . " hours')") . "' "; + + foreach ($filenames as $filename) { + $q = "UPDATE recordings SET archived = '$hfilename' WHERE filename = '$filename' "; + } } + } } /*$sth = $conn->prepare("select tgid, extract(hour from call_timestamp) ahour, date_trunc('day', call_timestamp) aday, count(filename), array_to_string(array_agg(filename order by call_timestamp), ',') filenames from recordings group by tgid, ahour, aday order by aday DESC, ahour, tgid;"); +$sth = $conn->prepare("SELECT tgid, EXTRACT(HOUR FROM call_timestamp) ahour, date_trunc('day', call_timestamp) aday, COUNT(filename), array_to_string(array_agg(filename ORDER BY call_timestamp), ',') filenames FROM recordings GROUP BY tgid, ahour, aday ORDER BY aday DESC, ahour, tgid;"); +// TODO use tgid categories instead, tgid too specific $sth->execute(); $hourlies = $sth->fetchAll(PDO::FETCH_ASSOC); -foreach($hourlies as $hourly) { +foreach ($hourlies as $hourly) { processHourly($hourly); } $sth = $conn->prepare("select 'hour' as tgid, extract(hour from call_timestamp) ahour, date_trunc('day', call_timestamp) aday, @@ -29,10 +40,9 @@ $sth->execute(); $hourlies = $sth->fetchAll(PDO::FETCH_ASSOC); -foreach($hourlies as $hourly) { +foreach ($hourlies as $hourly) { processHourly($hourly); } -*/ $sth = $conn->prepare("select coalesce(category,'unknown') as tgid, extract(hour from call_timestamp) ahour, date_trunc('day', call_timestamp) aday, count(filename), array_to_string(array_agg(filename order by call_timestamp), ',') filenames from recordings inner join tgids on recordings.tgid = tgids.tgid group by category, ahour, aday order by aday DESC, ahour, category;"); --- /dev/null +++ b/js/daterangepicker.js @@ -1,1 +1,609 @@ - +/** +* @version: 1.0.1 +* @author: Dan Grossman http://www.dangrossman.info/ +* @date: 2012-08-20 +* @copyright: Copyright (c) 2012 Dan Grossman. All rights reserved. +* @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0 +* @website: http://www.improvely.com/ +*/ +!function ($) { + + var DateRangePicker = function (element, options, cb) { + var hasOptions = typeof options == 'object' + var localeObject; + + //state + this.startDate = Date.create('today'); + this.endDate = Date.create('today'); + this.minDate = false; + this.maxDate = false; + this.changed = false; + this.cleared = false; + this.ranges = {}; + this.opens = 'right'; + this.cb = function () { }; + this.format = '{MM}/{dd}/{yyyy}'; + this.separator = ' - '; + this.showWeekNumbers = false; + this.buttonClasses = ['btn-success']; + this.locale = { + applyLabel: 'Apply', + clearLabel:"Clear", + fromLabel: 'From', + toLabel: 'To', + weekLabel: 'W', + customRangeLabel: 'Custom Range', + daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr','Sa'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + firstDay: 0 + }; + + localeObject = this.locale; + + this.leftCalendar = { + month: Date.create('today').set({ day: 1, month: this.startDate.getMonth(), year: this.startDate.getFullYear() }), + calendar: Array() + }; + + this.rightCalendar = { + month: Date.create('today').set({ day: 1, month: this.endDate.getMonth(), year: this.endDate.getFullYear() }), + calendar: Array() + }; + + //element that triggered the date range picker + this.element = $(element); + + if (this.element.hasClass('pull-right')) + this.opens = 'left'; + + if (this.element.is('input')) { + this.element.on({ + click: $.proxy(this.show, this), + focus: $.proxy(this.show, this) + }); + } else { + this.element.on('click', $.proxy(this.show, this)); + } + + if (hasOptions) { + if(typeof options.locale == 'object') { + $.each(localeObject, function (property, value) { + localeObject[property] = options.locale[property] || value; + }); + } + } + + var DRPTemplate = ''; + + this.container = $(DRPTemplate).appendTo('body'); + + if (hasOptions) { + + if (typeof options.format == 'string') + this.format = options.format; + + if (typeof options.separator == 'string') + this.separator = options.separator; + + if (typeof options.startDate == 'string') + this.startDate = Date.create(options.startDate); + + if (typeof options.endDate == 'string') + this.endDate = Date.create(options.endDate); + + if (typeof options.minDate == 'string') + this.minDate = Date.create(options.minDate); + + if (typeof options.maxDate == 'string') + this.maxDate = Date.create(options.maxDate); + + + if (typeof options.startDate == 'object') + this.startDate = options.startDate; + + if (typeof options.endDate == 'object') + this.endDate = options.endDate; + + if (typeof options.minDate == 'object') + this.minDate = options.minDate; + + if (typeof options.maxDate == 'object') + this.maxDate = options.maxDate; + + if (typeof options.ranges == 'object') { + for (var range in options.ranges) { + + var start = options.ranges[range][0]; + var end = options.ranges[range][1]; + + if (typeof start == 'string') + start = Date.create(start); + + if (typeof end == 'string') + end = Date.create(end); + + // If we have a min/max date set, bound this range + // to it, but only if it would otherwise fall + // outside of the min/max. + if (this.minDate && start < this.minDate) + start = this.minDate; + + if (this.maxDate && end > this.maxDate) + end = this.maxDate; + + // If the end of the range is before the minimum (if min is set) OR + // the start of the range is after the max (also if set) don't display this + // range option. + if ((this.minDate && end < this.minDate) || (this.maxDate && start > this.maxDate)) + { + continue; + } + + this.ranges[range] = [start, end]; + } + + var list = ''; + this.container.find('.ranges').prepend(list); + } + + // update day names order to firstDay + if (typeof options.locale == 'object') { + if (typeof options.locale.firstDay == 'number') { + this.locale.firstDay = options.locale.firstDay; + var iterator = options.locale.firstDay; + while (iterator > 0) { + this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); + iterator--; + } + } + } + + if (typeof options.opens == 'string') + this.opens = options.opens; + + if (typeof options.showWeekNumbers == 'boolean') { + this.showWeekNumbers = options.showWeekNumbers; + } + + if (typeof options.buttonClasses == 'string') { + this.buttonClasses = [options.buttonClasses]; + } + + if (typeof options.buttonClasses == 'object') { + this.buttonClasses = options.buttonClasses; + } + + } + + //apply CSS classes to buttons + var c = this.container; + $.each(this.buttonClasses, function (idx, val) { + c.find('button').addClass(val); + }); + + if (this.opens == 'right') { + //swap calendar positions + var left = this.container.find('.calendar.left'); + var right = this.container.find('.calendar.right'); + left.removeClass('left').addClass('right'); + right.removeClass('right').addClass('left'); + } + + if (typeof options == 'undefined' || typeof options.ranges == 'undefined') + this.container.find('.calendar').show(); + + if (typeof cb == 'function') + this.cb = cb; + + this.container.addClass('opens' + this.opens); + + //event listeners + this.container.on('mousedown', $.proxy(this.mousedown, this)); + this.container.find('.calendar').on('click', '.prev', $.proxy(this.clickPrev, this)); + this.container.find('.calendar').on('click', '.next', $.proxy(this.clickNext, this)); + this.container.find('.ranges').on('click', 'button.applyBtn', $.proxy(this.clickApply, this)); + this.container.find('.ranges').on('click', 'button.clearBtn', $.proxy(this.clickClear, this)); + + this.container.find('.calendar').on('click', 'td.available', $.proxy(this.clickDate, this)); + this.container.find('.calendar').on('mouseenter', 'td.available', $.proxy(this.enterDate, this)); + this.container.find('.calendar').on('mouseleave', 'td.available', $.proxy(this.updateView, this)); + + this.container.find('.ranges').on('click', 'li', $.proxy(this.clickRange, this)); + this.container.find('.ranges').on('mouseenter', 'li', $.proxy(this.enterRange, this)); + this.container.find('.ranges').on('mouseleave', 'li', $.proxy(this.updateView, this)); + + this.element.on('keyup', $.proxy(this.updateFromControl, this)); + + this.updateView(); + this.updateCalendars(); + + }; + + DateRangePicker.prototype = { + + constructor: DateRangePicker, + + mousedown: function (e) { + e.stopPropagation(); + e.preventDefault(); + }, + + updateView: function () { + this.leftCalendar.month.set({ month: this.startDate.getMonth(), year: this.startDate.getFullYear() }); + this.rightCalendar.month.set({ month: this.endDate.getMonth(), year: this.endDate.getFullYear() }); + + this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format)); + this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format)); + + if (this.startDate.is(this.endDate) || this.startDate.isBefore(this.endDate)) { + this.container.find('button.applyBtn').removeAttr('disabled'); + } else { + this.container.find('button.applyBtn').attr('disabled', 'disabled'); + } + }, + + updateFromControl: function () { + if (!this.element.is('input')) return; + + var dateString = this.element.val().split(this.separator); + var start = Date.create(dateString[0]); + var end = Date.create(dateString[1]); + + if (start == null || end == null) return; + if (end.isBefore(start)) return; + + this.startDate = start; + this.endDate = end; + + this.updateView(); + this.cb(this.startDate, this.endDate); + this.updateCalendars(); + }, + + notify: function () { + if (!this.cleared) { + this.updateView(); + } + + if (this.element.is('input')) { + this.element.val(this.cleared ? '' : this.startDate.format(this.format) + this.separator + this.endDate.format(this.format)); + } + var arg1 = (this.cleared ? null : this.startDate), + arg2 = (this.cleared ? null : this.endDate); + this.cleared = false; + this.cb(arg1,arg2); + }, + + move: function () { + if (this.opens == 'left') { + this.container.css({ + top: this.element.offset().top + this.element.outerHeight(), + right: $(window).width() - this.element.offset().left - this.element.outerWidth(), + left: 'auto' + }); + } else { + this.container.css({ + top: this.element.offset().top + this.element.outerHeight(), + left: this.element.offset().left, + right: 'auto' + }); + } + }, + + show: function (e) { + this.container.show(); + this.move(); + + if (e) { + e.stopPropagation(); + e.preventDefault(); + } + + this.changed = false; + + this.element.trigger('shown',{target:e.target,picker:this}); + + $(document).on('mousedown', $.proxy(this.hide, this)); + }, + + hide: function (e) { + this.container.hide(); + $(document).off('mousedown', this.hide); + + if (this.changed) { + this.changed = false; + this.notify(); + } + }, + + enterRange: function (e) { + var label = e.target.innerHTML; + if (label == this.locale.customRangeLabel) { + this.updateView(); + } else { + var dates = this.ranges[label]; + this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format)); + this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format)); + } + }, + + clickRange: function (e) { + var label = e.target.innerHTML; + if (label == this.locale.customRangeLabel) { + this.container.find('.calendar').show(); + } else { + var dates = this.ranges[label]; + + this.startDate = dates[0]; + this.endDate = dates[1]; + + this.leftCalendar.month.set({ month: this.startDate.getMonth(), year: this.startDate.getFullYear() }); + this.rightCalendar.month.set({ month: this.endDate.getMonth(), year: this.endDate.getFullYear() }); + this.updateCalendars(); + + this.changed = true; + + this.container.find('.calendar').hide(); + this.hide(); + } + }, + + clickPrev: function (e) { + var cal = $(e.target).parents('.calendar'); + if (cal.hasClass('left')) { + this.leftCalendar.month.addMonths(-1); + } else { + this.rightCalendar.month.addMonths(-1); + } + this.updateCalendars(); + }, + + clickNext: function (e) { + var cal = $(e.target).parents('.calendar'); + if (cal.hasClass('left')) { + this.leftCalendar.month.addMonths(1); + } else { + this.rightCalendar.month.addMonths(1); + } + this.updateCalendars(); + }, + + enterDate: function (e) { + + var title = $(e.target).attr('title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(e.target).parents('.calendar'); + + if (cal.hasClass('left')) { + this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format)); + } else { + this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format)); + } + + }, + + clickDate: function (e) { + var title = $(e.target).attr('title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(e.target).parents('.calendar'); + + if (cal.hasClass('left')) { + startDate = this.leftCalendar.calendar[row][col]; + endDate = this.endDate; + this.element.trigger('clicked',{ + dir: 'left', + picker: this + }); + } else { + startDate = this.startDate; + endDate = this.rightCalendar.calendar[row][col]; + this.element.trigger('clicked',{ + dir: 'right', + picker: this + }); + } + + cal.find('td').removeClass('active'); + + if (startDate.is(endDate) || startDate.isBefore(endDate)) { + $(e.target).addClass('active'); + if (!startDate.is(this.startDate) || !endDate.is(this.endDate)) + this.changed = true; + this.startDate = startDate; + this.endDate = endDate; + } + else if (startDate.isAfter(endDate)) { + $(e.target).addClass('active'); + this.changed = true; + this.startDate = startDate; + this.endDate = startDate.clone().addDays(1); + } + + this.leftCalendar.month.set({ month: this.startDate.getMonth(), year: this.startDate.getFullYear() }); + this.rightCalendar.month.set({ month: this.endDate.getMonth(), year: this.endDate.getFullYear() }); + this.updateCalendars(); + }, + + clickApply: function (e) { + this.hide(); + }, + + clickClear: function (e) { + this.changed = true; + this.cleared = true; + this.hide(); + }, + + updateCalendars: function () { + this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.getMonth(), this.leftCalendar.month.getFullYear()); + this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.getMonth(), this.rightCalendar.month.getFullYear()); + this.container.find('.calendar.left').html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate)); + this.container.find('.calendar.right').html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate)); + this.element.trigger('updated',this); + }, + + buildCalendar: function (month, year) { + + var firstDay = Date.create('today').set({ day: 1, month: month, year: year