From 5b25f5c1f223643246750f74538fe1e95aea4382 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 27 Aug 2014 10:34:21 -0400 Subject: Bug 1021902 - UI to view a user's review history r=glob --- extensions/Review/Extension.pm | 18 ++ extensions/Review/lib/WebService.pm | 33 ++- .../en/default/pages/review_history.html.tmpl | 62 ++++ extensions/Review/web/js/moment.min.js | 6 + extensions/Review/web/js/review_history.js | 324 +++++++++++++++++++++ extensions/Review/web/styles/review_history.css | 10 + .../en/default/pages/user_profile.html.tmpl | 5 + 7 files changed, 455 insertions(+), 3 deletions(-) create mode 100644 extensions/Review/template/en/default/pages/review_history.html.tmpl create mode 100644 extensions/Review/web/js/moment.min.js create mode 100644 extensions/Review/web/js/review_history.js create mode 100644 extensions/Review/web/styles/review_history.css diff --git a/extensions/Review/Extension.pm b/extensions/Review/Extension.pm index 78e19f9b7..8a7a9fe62 100644 --- a/extensions/Review/Extension.pm +++ b/extensions/Review/Extension.pm @@ -601,6 +601,9 @@ sub page_before_template { elsif ($args->{page_id} eq 'review_requests_rebuild.html') { $self->review_requests_rebuild($args); } + elsif ($args->{page_id} eq 'review_history.html') { + $self->review_history($args); + } } sub review_suggestions_report { @@ -655,6 +658,21 @@ sub review_requests_rebuild { } } +sub review_history { + my ($self, $args) = @_; + + my $user = Bugzilla->login(LOGIN_REQUIRED); + + Bugzilla::User::match_field({ 'requestee' => { 'type' => 'single' } }); + my $requestee = Bugzilla->input_params->{requestee}; + if ($requestee) { + $args->{vars}{requestee} = Bugzilla::User->check({ name => $requestee, cache => 1 }); + } + else { + $args->{vars}{requestee} = $user; + } +} + # # installation # diff --git a/extensions/Review/lib/WebService.pm b/extensions/Review/lib/WebService.pm index 8d10b5423..b3baf509a 100644 --- a/extensions/Review/lib/WebService.pm +++ b/extensions/Review/lib/WebService.pm @@ -15,7 +15,7 @@ use base qw(Bugzilla::WebService); use Bugzilla::Bug; use Bugzilla::Component; use Bugzilla::Error; -use Bugzilla::Util qw(detaint_natural); +use Bugzilla::Util qw(detaint_natural trick_taint); use Bugzilla::WebService::Util 'filter'; sub suggestions { @@ -83,6 +83,15 @@ sub flag_activity { $match_criteria{flag_id} = $flag_id; } + if (my $flag_ids = $params->{flag_ids}) { + foreach my $flag_id (@$flag_ids) { + detaint_natural($flag_id) + or ThrowUserError('invalid_flag_id', { flag_id => $flag_id }); + } + + $match_criteria{flag_id} = $flag_ids; + } + if (my $type_id = $params->{type_id}) { detaint_natural($type_id) or ThrowUserError('invalid_flag_type_id', { type_id => $type_id }); @@ -90,6 +99,12 @@ sub flag_activity { $match_criteria{type_id} = $type_id; } + if (my $type_name = $params->{type_name}) { + trick_taint($type_name); + my $flag_types = Bugzilla::FlagType::match({ name => $type_name }); + $match_criteria{type_id} = [map { $_->id } @$flag_types]; + } + for my $user_field (qw( requestee setter )) { if (my $user_name = $params->{$user_field}) { my $user = Bugzilla::User->check({ name => $user_name, cache => 1, _error => 'invalid_username' }); @@ -178,6 +193,14 @@ sub rest_resources { }, }, }, + qr{^/review/flag_activity/type_name/(\w+)$}, { + GET => { + method => 'flag_activity', + params => sub { + return { type_name => $_[0] } + }, + }, + }, # flag activity by user qr{^/review/flag_activity/(requestee|setter|type_id)/(.*)$}, { GET => { @@ -335,13 +358,15 @@ Returns the history of flag status changes based on requestee, setter, flag_id, =item B -GET /rest/review/flag_activity/C +GET /rest/review/flag_activity/C GET /rest/review/flag_activity/requestee/C GET /rest/review/flag_activity/setter/C -GET /rest/review/flag_activity/type_id/C +GET /rest/review/flag_activity/type_id/C + +GET /rest/review/flag_activity/type/C GET /rest/review/flag_activity @@ -363,6 +388,8 @@ Note that searching by C is not reliable because when flags are removed =item C (int) - The flag type id of a change +=item C (string) - the flag type name of a change + =back =item B diff --git a/extensions/Review/template/en/default/pages/review_history.html.tmpl b/extensions/Review/template/en/default/pages/review_history.html.tmpl new file mode 100644 index 000000000..32ac83ceb --- /dev/null +++ b/extensions/Review/template/en/default/pages/review_history.html.tmpl @@ -0,0 +1,62 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Review History" + style_urls = [ "extensions/Review/web/styles/review_history.css" ] + javascript_urls = [ 'js/yui3/yui/yui-min.js', + 'extensions/Review/web/js/review_history.js', + 'extensions/Review/web/js/moment.min.js', + 'js/util.js', + 'js/field.js' ] + yui = [ "autocomplete" ] +%] + + + +
+
+ + + [% INCLUDE global/userselect.html.tmpl + id => "requestee" + name => "requestee" + value => requestee.login + classes => ["bz_userfield"] + %] + + + +
+
+ +
+
Loading...
+
+
+ +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/Review/web/js/moment.min.js b/extensions/Review/web/js/moment.min.js new file mode 100644 index 000000000..26ac5cc9d --- /dev/null +++ b/extensions/Review/web/js/moment.min.js @@ -0,0 +1,6 @@ +//! moment.js +//! version : 2.8.2 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +(function(a){function b(a,b,c){switch(arguments.length){case 2:return null!=a?a:b;case 3:return null!=a?a:null!=b?b:c;default:throw new Error("Implement me")}}function c(a,b){return yb.call(a,b)}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function e(a){sb.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function f(a,b){var c=!0;return m(function(){return c&&(e(a),c=!1),b.apply(this,arguments)},b)}function g(a,b){pc[a]||(e(b),pc[a]=!0)}function h(a,b){return function(c){return p(a.call(this,c),b)}}function i(a,b){return function(c){return this.localeData().ordinal(a.call(this,c),b)}}function j(){}function k(a,b){b!==!1&&F(a),n(this,a),this._d=new Date(+a._d)}function l(a){var b=y(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=sb.localeData(),this._bubble()}function m(a,b){for(var d in b)c(b,d)&&(a[d]=b[d]);return c(b,"toString")&&(a.toString=b.toString),c(b,"valueOf")&&(a.valueOf=b.valueOf),a}function n(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Hb.length>0)for(c in Hb)d=Hb[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function o(a){return 0>a?Math.ceil(a):Math.floor(a)}function p(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&A(a[d])!==A(b[d]))&&g++;return g+f}function x(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=ic[a]||jc[b]||b}return a}function y(a){var b,d,e={};for(d in a)c(a,d)&&(b=x(d),b&&(e[b]=a[d]));return e}function z(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}sb[b]=function(e,f){var g,h,i=sb._locale[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=sb().utc().set(d,a);return i.call(sb._locale,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function A(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function B(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function C(a,b,c){return gb(sb([a,11,31+b-c]),b,c).week}function D(a){return E(a)?366:365}function E(a){return a%4===0&&a%100!==0||a%400===0}function F(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[Ab]<0||a._a[Ab]>11?Ab:a._a[Bb]<1||a._a[Bb]>B(a._a[zb],a._a[Ab])?Bb:a._a[Cb]<0||a._a[Cb]>23?Cb:a._a[Db]<0||a._a[Db]>59?Db:a._a[Eb]<0||a._a[Eb]>59?Eb:a._a[Fb]<0||a._a[Fb]>999?Fb:-1,a._pf._overflowDayOfYear&&(zb>b||b>Bb)&&(b=Bb),a._pf.overflow=b)}function G(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function H(a){return a?a.toLowerCase().replace("_","-"):a}function I(a){for(var b,c,d,e,f=0;f0;){if(d=J(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&w(e,c,!0)>=b-1)break;b--}f++}return null}function J(a){var b=null;if(!Gb[a]&&Ib)try{b=sb.locale(),require("./locale/"+a),sb.locale(b)}catch(c){}return Gb[a]}function K(a,b){return b._isUTC?sb(a).zone(b._offset||0):sb(a).local()}function L(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function M(a){var b,c,d=a.match(Mb);for(b=0,c=d.length;c>b;b++)d[b]=oc[d[b]]?oc[d[b]]:L(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function N(a,b){return a.isValid()?(b=O(b,a.localeData()),kc[b]||(kc[b]=M(b)),kc[b](a)):a.localeData().invalidDate()}function O(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Nb.lastIndex=0;d>=0&&Nb.test(a);)a=a.replace(Nb,c),Nb.lastIndex=0,d-=1;return a}function P(a,b){var c,d=b._strict;switch(a){case"Q":return Yb;case"DDDD":return $b;case"YYYY":case"GGGG":case"gggg":return d?_b:Qb;case"Y":case"G":case"g":return bc;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?ac:Rb;case"S":if(d)return Yb;case"SS":if(d)return Zb;case"SSS":if(d)return $b;case"DDD":return Pb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Tb;case"a":case"A":return b._locale._meridiemParse;case"X":return Wb;case"Z":case"ZZ":return Ub;case"T":return Vb;case"SSSS":return Sb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?Zb:Ob;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Ob;case"Do":return Xb;default:return c=new RegExp(Y(X(a.replace("\\","")),"i"))}}function Q(a){a=a||"";var b=a.match(Ub)||[],c=b[b.length-1]||[],d=(c+"").match(gc)||["-",0,0],e=+(60*d[1])+A(d[2]);return"+"===d[0]?-e:e}function R(a,b,c){var d,e=c._a;switch(a){case"Q":null!=b&&(e[Ab]=3*(A(b)-1));break;case"M":case"MM":null!=b&&(e[Ab]=A(b)-1);break;case"MMM":case"MMMM":d=c._locale.monthsParse(b),null!=d?e[Ab]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[Bb]=A(b));break;case"Do":null!=b&&(e[Bb]=A(parseInt(b,10)));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=A(b));break;case"YY":e[zb]=sb.parseTwoDigitYear(b);break;case"YYYY":case"YYYYY":case"YYYYYY":e[zb]=A(b);break;case"a":case"A":c._isPm=c._locale.isPM(b);break;case"H":case"HH":case"h":case"hh":e[Cb]=A(b);break;case"m":case"mm":e[Db]=A(b);break;case"s":case"ss":e[Eb]=A(b);break;case"S":case"SS":case"SSS":case"SSSS":e[Fb]=A(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=Q(b);break;case"dd":case"ddd":case"dddd":d=c._locale.weekdaysParse(b),null!=d?(c._w=c._w||{},c._w.d=d):c._pf.invalidWeekday=b;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":a=a.substr(0,1);case"gggg":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=A(b));break;case"gg":case"GG":c._w=c._w||{},c._w[a]=sb.parseTwoDigitYear(b)}}function S(a){var c,d,e,f,g,h,i;c=a._w,null!=c.GG||null!=c.W||null!=c.E?(g=1,h=4,d=b(c.GG,a._a[zb],gb(sb(),1,4).year),e=b(c.W,1),f=b(c.E,1)):(g=a._locale._week.dow,h=a._locale._week.doy,d=b(c.gg,a._a[zb],gb(sb(),g,h).year),e=b(c.w,1),null!=c.d?(f=c.d,g>f&&++e):f=null!=c.e?c.e+g:g),i=hb(d,e,f,h,g),a._a[zb]=i.year,a._dayOfYear=i.dayOfYear}function T(a){var c,d,e,f,g=[];if(!a._d){for(e=V(a),a._w&&null==a._a[Bb]&&null==a._a[Ab]&&S(a),a._dayOfYear&&(f=b(a._a[zb],e[zb]),a._dayOfYear>D(f)&&(a._pf._overflowDayOfYear=!0),d=cb(f,0,a._dayOfYear),a._a[Ab]=d.getUTCMonth(),a._a[Bb]=d.getUTCDate()),c=0;3>c&&null==a._a[c];++c)a._a[c]=g[c]=e[c];for(;7>c;c++)a._a[c]=g[c]=null==a._a[c]?2===c?1:0:a._a[c];a._d=(a._useUTC?cb:bb).apply(null,g),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()+a._tzm)}}function U(a){var b;a._d||(b=y(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],T(a))}function V(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function W(a){if(a._f===sb.ISO_8601)return void $(a);a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=""+a._i,h=g.length,i=0;for(d=O(a._f,a._locale).match(Mb)||[],b=0;b0&&a._pf.unusedInput.push(f),g=g.slice(g.indexOf(c)+c.length),i+=c.length),oc[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),R(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=h-i,g.length>0&&a._pf.unusedInput.push(g),a._isPm&&a._a[Cb]<12&&(a._a[Cb]+=12),a._isPm===!1&&12===a._a[Cb]&&(a._a[Cb]=0),T(a),F(a)}function X(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function Y(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Z(a){var b,c,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;fg)&&(e=g,c=b));m(a,c||b)}function $(a){var b,c,d=a._i,e=cc.exec(d);if(e){for(a._pf.iso=!0,b=0,c=ec.length;c>b;b++)if(ec[b][1].exec(d)){a._f=ec[b][0]+(e[6]||" ");break}for(b=0,c=fc.length;c>b;b++)if(fc[b][1].exec(d)){a._f+=fc[b][0];break}d.match(Ub)&&(a._f+="Z"),W(a)}else a._isValid=!1}function _(a){$(a),a._isValid===!1&&(delete a._isValid,sb.createFromInputFallback(a))}function ab(b){var c,d=b._i;d===a?b._d=new Date:v(d)?b._d=new Date(+d):null!==(c=Jb.exec(d))?b._d=new Date(+c[1]):"string"==typeof d?_(b):u(d)?(b._a=d.slice(0),T(b)):"object"==typeof d?U(b):"number"==typeof d?b._d=new Date(d):sb.createFromInputFallback(b)}function bb(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function cb(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function db(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function eb(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function fb(a,b,c){var d=sb.duration(a).abs(),e=xb(d.as("s")),f=xb(d.as("m")),g=xb(d.as("h")),h=xb(d.as("d")),i=xb(d.as("M")),j=xb(d.as("y")),k=e0,k[4]=c,eb.apply({},k)}function gb(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=sb(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function hb(a,b,c,d,e){var f,g,h=cb(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:D(a-1)+g}}function ib(b){var c=b._i,d=b._f;return b._locale=b._locale||sb.localeData(b._l),null===c||d===a&&""===c?sb.invalid({nullInput:!0}):("string"==typeof c&&(b._i=c=b._locale.preparse(c)),sb.isMoment(c)?new k(c,!0):(d?u(d)?Z(b):W(b):ab(b),new k(b)))}function jb(a,b){var c,d;if(1===b.length&&u(b[0])&&(b=b[0]),!b.length)return sb();for(c=b[0],d=1;d=0?"+":"-";return b+p(Math.abs(a),6)},gg:function(){return p(this.weekYear()%100,2)},gggg:function(){return p(this.weekYear(),4)},ggggg:function(){return p(this.weekYear(),5)},GG:function(){return p(this.isoWeekYear()%100,2)},GGGG:function(){return p(this.isoWeekYear(),4)},GGGGG:function(){return p(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return A(this.milliseconds()/100)},SS:function(){return p(A(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},SSSS:function(){return p(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+":"+p(A(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+p(A(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},pc={},qc=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];mc.length;)ub=mc.pop(),oc[ub+"o"]=i(oc[ub],ub);for(;nc.length;)ub=nc.pop(),oc[ub+ub]=h(oc[ub],2);oc.DDDD=h(oc.DDD,3),m(j.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=sb.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=sb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return gb(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),sb=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=b,g._f=c,g._l=e,g._strict=f,g._isUTC=!1,g._pf=d(),ib(g)},sb.suppressDeprecationWarnings=!1,sb.createFromInputFallback=f("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i)}),sb.min=function(){var a=[].slice.call(arguments,0);return jb("isBefore",a)},sb.max=function(){var a=[].slice.call(arguments,0);return jb("isAfter",a)},sb.utc=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=b,g._f=c,g._strict=f,g._pf=d(),ib(g).utc()},sb.unix=function(a){return sb(1e3*a)},sb.duration=function(a,b){var d,e,f,g,h=a,i=null;return sb.isDuration(a)?h={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(h={},b?h[b]=a:h.milliseconds=a):(i=Kb.exec(a))?(d="-"===i[1]?-1:1,h={y:0,d:A(i[Bb])*d,h:A(i[Cb])*d,m:A(i[Db])*d,s:A(i[Eb])*d,ms:A(i[Fb])*d}):(i=Lb.exec(a))?(d="-"===i[1]?-1:1,f=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*d},h={y:f(i[2]),M:f(i[3]),d:f(i[4]),h:f(i[5]),m:f(i[6]),s:f(i[7]),w:f(i[8])}):"object"==typeof h&&("from"in h||"to"in h)&&(g=r(sb(h.from),sb(h.to)),h={},h.ms=g.milliseconds,h.M=g.months),e=new l(h),sb.isDuration(a)&&c(a,"_locale")&&(e._locale=a._locale),e},sb.version=vb,sb.defaultFormat=dc,sb.ISO_8601=function(){},sb.momentProperties=Hb,sb.updateOffset=function(){},sb.relativeTimeThreshold=function(b,c){return lc[b]===a?!1:c===a?lc[b]:(lc[b]=c,!0)},sb.lang=f("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return sb.locale(a,b)}),sb.locale=function(a,b){var c;return a&&(c="undefined"!=typeof b?sb.defineLocale(a,b):sb.localeData(a),c&&(sb.duration._locale=sb._locale=c)),sb._locale._abbr},sb.defineLocale=function(a,b){return null!==b?(b.abbr=a,Gb[a]||(Gb[a]=new j),Gb[a].set(b),sb.locale(a),Gb[a]):(delete Gb[a],null)},sb.langData=f("moment.langData is deprecated. Use moment.localeData instead.",function(a){return sb.localeData(a)}),sb.localeData=function(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return sb._locale;if(!u(a)){if(b=J(a))return b;a=[a]}return I(a)},sb.isMoment=function(a){return a instanceof k||null!=a&&c(a,"_isAMomentObject")},sb.isDuration=function(a){return a instanceof l};for(ub=qc.length-1;ub>=0;--ub)z(qc[ub]);sb.normalizeUnits=function(a){return x(a)},sb.invalid=function(a){var b=sb.utc(0/0);return null!=a?m(b._pf,a):b._pf.userInvalidated=!0,b},sb.parseZone=function(){return sb.apply(null,arguments).parseZone()},sb.parseTwoDigitYear=function(a){return A(a)+(A(a)>68?1900:2e3)},m(sb.fn=k.prototype,{clone:function(){return sb(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=sb(this).utc();return 00:!1},parsingFlags:function(){return m({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.zone(0,a)},local:function(a){return this._isUTC&&(this.zone(0,a),this._isUTC=!1,a&&this.add(this._d.getTimezoneOffset(),"m")),this},format:function(a){var b=N(this,a||sb.defaultFormat);return this.localeData().postformat(b)},add:s(1,"add"),subtract:s(-1,"subtract"),diff:function(a,b,c){var d,e,f=K(a,this),g=6e4*(this.zone()-f.zone());return b=x(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-sb(this).startOf("month")-(f-sb(f).startOf("month")))/d,e-=6e4*(this.zone()-sb(this).startOf("month").zone()-(f.zone()-sb(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:o(e)},from:function(a,b){return sb.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(sb(),a)},calendar:function(a){var b=a||sb(),c=K(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this))},isLeapYear:function(){return E(this.year())},isDST:function(){return this.zone()+sb(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+sb(a).startOf(b)},isSame:function(a,b){return b=b||"ms",+this.clone().startOf(b)===+K(a,this).startOf(b)},min:f("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(a){return a=sb.apply(null,arguments),this>a?this:a}),max:f("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){return a=sb.apply(null,arguments),a>this?this:a}),zone:function(a,b){var c,d=this._offset||0;return null==a?this._isUTC?d:this._d.getTimezoneOffset():("string"==typeof a&&(a=Q(a)),Math.abs(a)<16&&(a=60*a),!this._isUTC&&b&&(c=this._d.getTimezoneOffset()),this._offset=a,this._isUTC=!0,null!=c&&this.subtract(c,"m"),d!==a&&(!b||this._changeInProgress?t(this,sb.duration(d-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,sb.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?sb(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return B(this.year(),this.month())},dayOfYear:function(a){var b=xb((sb(this).startOf("day")-sb(this).startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")},quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=gb(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=gb(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=gb(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return C(this.year(),1,4)},weeksInYear:function(){var a=this.localeData()._week;return C(this.year(),a.dow,a.doy)},get:function(a){return a=x(a),this[a]()},set:function(a,b){return a=x(a),"function"==typeof this[a]&&this[a](b),this},locale:function(b){return b===a?this._locale._abbr:(this._locale=sb.localeData(b),this)},lang:f("moment().lang() is deprecated. Use moment().localeData() instead.",function(b){return b===a?this.localeData():(this._locale=sb.localeData(b),this)}),localeData:function(){return this._locale}}),sb.fn.millisecond=sb.fn.milliseconds=nb("Milliseconds",!1),sb.fn.second=sb.fn.seconds=nb("Seconds",!1),sb.fn.minute=sb.fn.minutes=nb("Minutes",!1),sb.fn.hour=sb.fn.hours=nb("Hours",!0),sb.fn.date=nb("Date",!0),sb.fn.dates=f("dates accessor is deprecated. Use date instead.",nb("Date",!0)),sb.fn.year=nb("FullYear",!0),sb.fn.years=f("years accessor is deprecated. Use year instead.",nb("FullYear",!0)),sb.fn.days=sb.fn.day,sb.fn.months=sb.fn.month,sb.fn.weeks=sb.fn.week,sb.fn.isoWeeks=sb.fn.isoWeek,sb.fn.quarters=sb.fn.quarter,sb.fn.toJSON=sb.fn.toISOString,m(sb.duration.fn=l.prototype,{_bubble:function(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;g.milliseconds=d%1e3,a=o(d/1e3),g.seconds=a%60,b=o(a/60),g.minutes=b%60,c=o(b/60),g.hours=c%24,e+=o(c/24),h=o(ob(e)),e-=o(pb(h)),f+=o(e/30),e%=30,h+=o(f/12),f%=12,g.days=e,g.months=f,g.years=h},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return o(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*A(this._months/12)},humanize:function(a){var b=fb(this,!a,this.localeData());return a&&(b=this.localeData().pastFuture(+this,b)),this.localeData().postformat(b)},add:function(a,b){var c=sb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=sb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=x(a),this[a.toLowerCase()+"s"]()},as:function(a){var b,c;if(a=x(a),b=this._days+this._milliseconds/864e5,"month"===a||"year"===a)return c=this._months+12*ob(b),"month"===a?c:c/12;switch(b+=pb(this._months/12),a){case"week":return b/7;case"day":return b;case"hour":return 24*b;case"minute":return 24*b*60;case"second":return 24*b*60*60;case"millisecond":return 24*b*60*60*1e3;default:throw new Error("Unknown unit "+a)}},lang:sb.fn.lang,locale:sb.fn.locale,toIsoString:f("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"},localeData:function(){return this._locale}}),sb.duration.fn.toString=sb.duration.fn.toISOString;for(ub in hc)c(hc,ub)&&qb(ub.toLowerCase());sb.duration.fn.asMilliseconds=function(){return this.as("ms")},sb.duration.fn.asSeconds=function(){return this.as("s")},sb.duration.fn.asMinutes=function(){return this.as("m")},sb.duration.fn.asHours=function(){return this.as("h")},sb.duration.fn.asDays=function(){return this.as("d")},sb.duration.fn.asWeeks=function(){return this.as("weeks")},sb.duration.fn.asMonths=function(){return this.as("M")},sb.duration.fn.asYears=function(){return this.as("y")},sb.locale("en",{ordinal:function(a){var b=a%10,c=1===A(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),Ib?module.exports=sb:"function"==typeof define&&define.amd?(define("moment",function(a,b,c){return c.config&&c.config()&&c.config().noGlobal===!0&&(wb.moment=tb),sb}),rb(!0)):rb()}).call(this); \ No newline at end of file diff --git a/extensions/Review/web/js/review_history.js b/extensions/Review/web/js/review_history.js new file mode 100644 index 000000000..7a9b28743 --- /dev/null +++ b/extensions/Review/web/js/review_history.js @@ -0,0 +1,324 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This Source Code Form is "Incompatible With Secondary Licenses", as + * defined by the Mozilla Public License, v. 2.0. */ + +(function () { + 'use strict'; + + YUI.add('bz-review-history', function (Y) { + function format_duration(o) { + return moment.duration(o.value).humanize(); + } + + function format_attachment(o) { + return o.value.description; + } + + function format_status(o) { + return o.value; + } + + function format_setter(o) { + return o.value.real_name ? o.value.real_name + " <" + o.value.name + ">" : o.value.name; + } + + function format_date(o) { + return o.value && Y.DataType.Date.format(o.value, { + format: "%Y-%m-%d" + }); + } + + function parse_date(str) { + var parts = str.split(/\D/); + return new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]); + } + + var flagDS, bugDS, attachmentDS, historyTable; + flagDS = new Y.DataSource.IO({ source: 'jsonrpc.cgi' }); + flagDS.plug(Y.Plugin.DataSourceJSONSchema, { + schema: { + resultListLocator: 'result', + resultFields: [ + { key: 'requestee' }, + { key: 'setter' }, + { key: 'flag_id' }, + { key: 'creation_time' }, + { key: 'status' }, + { key: 'bug_id' }, + { key: 'type' }, + { key: 'attachment_id' } + ] + } + }); + + bugDS = new Y.DataSource.IO({ source: 'jsonrpc.cgi' }); + bugDS.plug(Y.Plugin.DataSourceJSONSchema, { + schema: { + resultListLocator: 'result.bugs', + resultFields: [ + { key: 'id' }, + { key: 'summary' } + ] + } + }); + + attachmentDS = new Y.DataSource.IO({ source: 'jsonrpc.cgi' }); + attachmentDS.plug(Y.Plugin.DataSourceJSONSchema, { + schema: { + metaFields: { 'attachments': 'result.attachments' } + } + }); + + historyTable = new Y.DataTable({ + columns: [ + { key: 'creation_time', label: 'Created', sortable: true, formatter: format_date }, + { key: 'attachment', label: 'Attachment', formatter: format_attachment, allowHTML: true }, + { key: 'setter', label: 'Requester', formatter: format_setter }, + { key: "status", label: "Status", sortable: true, allowHTML: true, formatter: format_status }, + { key: "duration", label: "Duration", sortable: true, formatter: format_duration }, + { key: "bug_id", label: "Bug", sortable: true, allowHTML: true, + formatter: '{value}' }, + { key: 'bug_summary', label: 'Summary' } + ] + }); + + function fetch_flag_ids(user) { + return new Y.Promise(function (resolve, reject) { + var flagIdCallback = { + success: function (e) { + var flags = e.response.results; + var flag_ids = flags.filter(function (flag) { + return flag.status === '?'; + }) + .map(function (flag) { + return flag.flag_id; + }); + + if (flag_ids.length > 0) { + resolve(flag_ids); + } else { + reject("No reviews found"); + } + }, + failure: function (e) { + reject(e.error.message); + } + }; + + flagDS.sendRequest({ + request: Y.JSON.stringify({ + version: '1.1', + method: 'Review.flag_activity', + params: { + type_name: 'review', + requestee: user, + include_fields: ['flag_id', 'status'] + } + }), + cfg: { + method: "POST", + headers: { 'Content-Type': 'application/json' } + }, + callback: flagIdCallback + }); + }); + } + + function fetch_flags(flag_ids) { + return new Y.Promise(function (resolve, reject) { + flagDS.sendRequest({ + request: Y.JSON.stringify({ + version: '1.1', + method: 'Review.flag_activity', + params: { flag_ids: flag_ids } + }), + cfg: { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }, + callback: { + success: function (e) { + resolve(e.response.results); + }, + failure: function (e) { + reject(e.error.message); + } + } + }); + }); + } + + function fetch_bug_summaries(flags) { + return new Y.Promise(function (resolve, reject) { + var bug_ids = Y.Array.dedupe(flags.map(function (f) { + return f.bug_id; + })); + + bugDS.sendRequest({ + request: Y.JSON.stringify({ + version: '1.1', + method: 'Bug.get', + params: { ids: bug_ids, include_fields: ['summary', 'id'] } + }), + cfg: { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }, + callback: { + success: function (e) { + var bugs = e.response.results, + summary = {}; + + bugs.forEach(function (bug) { + summary[bug.id] = bug.summary; + }); + flags.forEach(function (flag) { + flag.bug_summary = summary[flag.bug_id]; + }); + resolve(flags); + }, + failure: function (e) { + reject(e.error.message); + } + } + }); + }); + } + + function fetch_attachment_descriptions(flags) { + return new Y.Promise(function (resolve, reject) { + var attachment_ids = Y.Array.dedupe(flags.map(function (f) { + return f.attachment_id; + })); + + attachmentDS.sendRequest({ + request: Y.JSON.stringify({ + version: '1.1', + method: 'Bug.attachments', + params: { + attachment_ids: attachment_ids, + include_fields: ['id', 'description'] + } + }), + cfg: { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }, + callback: { + success: function (e) { + var attachments = e.response.meta.attachments; + flags.forEach(function (flag) { + flag.attachment = attachments[flag.attachment_id]; + }); + resolve(flags); + }, + failure: function (e) { + reject(e.error.message); + } + } + }); + }); + } + + function generate_history(flags) { + var history = [], + stash = {}, + i = 1, stash_key; + + flags.forEach(function (flag) { + var flag_id = flag.flag_id; + + switch (flag.status) { + case '?': + if (stash[flag_id]) { + stash["#" + i] = stash[flag_id]; + i = i + 1; + } + + stash[flag_id] = { + setter: flag.setter, + bug_id: flag.bug_id, + bug_summary: flag.bug_summary, + attachment: flag.attachment, + start: parse_date(flag.creation_time), + creation_time: parse_date(flag.creation_time) + }; + break; + + case '+': + case '-': + if (stash[flag_id]) { + history.push({ + setter: stash[flag_id].setter, + bug_id: stash[flag_id].bug_id, + bug_summary: stash[flag_id].bug_summary, + attachment: stash[flag_id].attachment, + status: 'review' + flag.status, + duration: parse_date(flag.creation_time) - stash[flag_id].start, + creation_time: stash[flag_id].creation_time + }); + stash[flag_id] = null; + } + break; + } + }); + for (stash_key in stash) { + if (stash[stash_key]) { + history.push({ + setter: stash[stash_key].setter, + bug_id: stash[stash_key].bug_id, + bug_summary: stash[stash_key].bug_summary, + attachment: stash[stash_key].attachment, + creation_time: stash[stash_key].creation_time, + status: 'review?', + duration: new Date() - stash[stash_key].creation_time + }); + } + } + + return history; + } + + Y.ReviewHistory = {}; + + Y.ReviewHistory.render = function (sel) { + Y.one('#history-loading').hide(); + historyTable.render(sel); + historyTable.setAttrs({ + width: "100%" + }, true); + }; + + Y.ReviewHistory.refresh = function (user, real_name) { + var caption = "Review History for " + (real_name ? real_name + ' <' + user + '>' : user); + historyTable.setAttrs({ + caption: caption + }); + historyTable.set('data', null); + historyTable.showMessage('Loading...'); + fetch_flag_ids(user) + .then(fetch_flags) + .then(fetch_bug_summaries) + .then(fetch_attachment_descriptions) + .then(generate_history) + .then(function (history) { + historyTable.set('data', history); + historyTable.sort({ + creation_time: 'asc' + }); + }, function (message) { + historyTable.showMessage(message); + }); + }; + + }, '0.0.1', { + requires: [ + "node", "datatype-date", "datatable", "datatable-sort", "datatable-message", "json-stringify", + "datatable-datasource", "datasource-io", "datasource-jsonschema", "cookie", + "gallery-datatable-row-expansion-bmo", "handlebars", "escape", "promise" + ] + }); +}()); diff --git a/extensions/Review/web/styles/review_history.css b/extensions/Review/web/styles/review_history.css new file mode 100644 index 000000000..b72b2efb2 --- /dev/null +++ b/extensions/Review/web/styles/review_history.css @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This Source Code Form is "Incompatible With Secondary Licenses", as + * defined by the Mozilla Public License, v. 2.0. */ + +.yui3-skin-sam .yui3-datatable-table > table { + width: 100%; +} diff --git a/extensions/UserProfile/template/en/default/pages/user_profile.html.tmpl b/extensions/UserProfile/template/en/default/pages/user_profile.html.tmpl index ba2c4ab57..cc10d1706 100644 --- a/extensions/UserProfile/template/en/default/pages/user_profile.html.tmpl +++ b/extensions/UserProfile/template/en/default/pages/user_profile.html.tmpl @@ -132,6 +132,11 @@ [% target.review_request_count FILTER html %] [% "" IF user.id %] + [% IF user.id %] + + (Review History) + + [% END %]   -- cgit v1.2.3-24-g4f1b