diff --git a/akvo/rest/serializers/iati_export.py b/akvo/rest/serializers/iati_export.py
index 7b19eff9e9..20ee5bdcbb 100644
--- a/akvo/rest/serializers/iati_export.py
+++ b/akvo/rest/serializers/iati_export.py
@@ -4,14 +4,17 @@
# See more details in the license.txt file located at the root folder of the Akvo RSR module.
# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
-
+from akvo.rest.serializers.rsr_serializer import BaseRSRSerializer
from akvo.rsr.models import IatiActivityExport, IatiExport
-from .rsr_serializer import BaseRSRSerializer
+from rest_framework import serializers
class IatiExportSerializer(BaseRSRSerializer):
+ user_name = serializers.Field(source='user.get_full_name')
+ status_label = serializers.Field(source='show_status')
+
class Meta:
model = IatiExport
diff --git a/akvo/rsr/static/scripts-src/my-iati.js b/akvo/rsr/static/scripts-src/my-iati.js
index 6c3bdd66fa..aede84615a 100644
--- a/akvo/rsr/static/scripts-src/my-iati.js
+++ b/akvo/rsr/static/scripts-src/my-iati.js
@@ -7,6 +7,7 @@
var csrftoken,
endpoints,
+ months,
i18n;
/* CSRF TOKEN (this should really be added in base.html, we use it everywhere) */
@@ -27,7 +28,7 @@ function getCookie(name) {
csrftoken = getCookie('csrftoken');
/* Capitalize the first character of a string */
-function capitalizeFirstLetter(string) {
+function cap(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
@@ -45,17 +46,30 @@ function apiCall(method, url, data, successCallback, retries) {
var success = function(newResponse) {
var oldResults = response.results;
response.results = oldResults.concat(newResponse.results);
- return successCallback(response);
+ if (successCallback !== undefined) {
+ return successCallback(response);
+ } else {
+ return false;
+ }
};
apiCall(method, response.next, data, success);
} else {
- return successCallback(response);
+ if (successCallback !== undefined) {
+ return successCallback(response);
+ } else {
+ return false;
+ }
}
} else {
- return successCallback(response);
+ if (successCallback !== undefined) {
+ return successCallback(response);
+ } else {
+ return false;
+ }
}
} else {
- var message = i18nResults.general_error + ': ';
+ // var message = i18nResults.general_error + ': ';
+ var message = 'general error: ';
for (var key in response) {
if (response.hasOwnProperty(key)) {
message += response[key] + '. ';
@@ -115,6 +129,47 @@ function loadAsync(url, callback, retryCount, retryLimit) {
xmlHttp.send();
}
+function getDateDescription(month) {
+ switch (month) {
+ case 0:
+ return months.january;
+ case 1:
+ return months.february;
+ case 2:
+ return months.march;
+ case 3:
+ return months.april;
+ case 4:
+ return months.may;
+ case 5:
+ return months.june;
+ case 6:
+ return months.july;
+ case 7:
+ return months.august;
+ case 8:
+ return months.september;
+ case 9:
+ return months.october;
+ case 10:
+ return months.november;
+ case 11:
+ return months.december;
+ }
+}
+
+function displayDate(dateString) {
+ // Display a dateString like "25 Jan 2016"
+ if (dateString !== undefined && dateString !== null) {
+ var date = new Date(dateString.split(".")[0].replace("/", /-/g));
+ var day = date.getUTCDate();
+ var month = getDateDescription(date.getUTCMonth());
+ var year = date.getUTCFullYear();
+ return day + " " + month + " " + year;
+ }
+ return i18n.unknown_date;
+}
+
function processResponse(label, response) {
var label_content, checks, all_checks_passed, span, checks_response;
@@ -217,20 +272,102 @@ function loadComponents() {
}
});
+ var ExportRow = React.createClass({displayName: 'ExportRow',
+ openPublicFile: function() {
+ window.open(i18n.last_exports_url, '_blank');
+ },
+
+ openFile: function() {
+ window.open(endpoints.base_url + '/media/' + this.props.exp.iati_file, '_blank');
+ },
+
+ setPublic: function() {
+ this.props.setPublic(this.props.exp.id);
+ },
+
+ renderActions: function() {
+ if (this.props.publicFile) {
+ return (
+ React.DOM.button( {className:"btn btn-success btn-sm", onClick:this.openPublicFile},
+ React.DOM.i( {className:"fa fa-globe"} ), " ", cap(i18n.view_public_file)
+ )
+ );
+ } else if (this.props.exp.iati_file) {
+ return (
+ React.DOM.div(null,
+ React.DOM.button( {className:"btn btn-default btn-sm", onClick:this.openFile},
+ React.DOM.i( {className:"fa fa-code"} ), " ", cap(i18n.view_file)
+ ),
+ React.DOM.button( {className:"btn btn-default btn-sm", onClick:this.setPublic},
+ React.DOM.i( {className:"fa fa-globe"} ), " ", cap(i18n.set_public)
+ )
+ )
+ );
+ } else {
+ return (
+ React.DOM.button( {className:"btn btn-default btn-sm disabled"},
+ React.DOM.i( {className:"fa fa-globe"} ), " ", cap(i18n.no_iati_file)
+ )
+ );
+ }
+ },
+
+ renderRowClass: function() {
+ if (this.props.publicFile) {
+ return 'publicFile';
+ } else if (this.props.exp.status === 2) {
+ return 'inProgress';
+ } else if (this.props.exp.status === 4 || this.props.exp.iati_file === '') {
+ return 'cancelled';
+ } else {
+ return '';
+ }
+ },
+
+ render: function() {
+ return (
+ React.DOM.tr( {className:this.renderRowClass()},
+ React.DOM.td(null, this.props.exp.status_label),
+ React.DOM.td(null, this.props.exp.projects.length),
+ React.DOM.td(null, this.props.exp.user_name),
+ React.DOM.td(null, displayDate(this.props.exp.created_at)),
+ React.DOM.td(null, 'v' + this.props.exp.version),
+ React.DOM.td( {className:"text-right"}, this.renderActions())
+ )
+ );
+ }
+ });
+
var ExportsTable = React.createClass({displayName: 'ExportsTable',
render: function() {
+ var thisTable = this;
+
+ var exports = this.props.exports.results.map(function(exp) {
+ var publicFile = thisTable.props.publicFile === exp.id;
+
+ return React.createElement(ExportRow, {
+ key: exp.id,
+ exp: exp,
+ publicFile: publicFile,
+ setPublic: thisTable.props.setPublic
+ });
+ });
+
+
return (
- React.DOM.table( {className:"table table-striped table-responsive myProjectList"},
+ React.DOM.table( {className:"table table-striped table-responsive myProjectList topMargin"},
React.DOM.thead(null,
React.DOM.tr(null,
- React.DOM.th(null, "Last export"),
- React.DOM.th(null, "User"),
- React.DOM.th(null, "Created at"),
- React.DOM.th(null, "IATI version"),
- React.DOM.th(null, "status"),
- React.DOM.th(null, "IATI file"),
- React.DOM.th(null, "Number of projects")
+ React.DOM.th(null, cap(i18n.status)),
+ React.DOM.th(null, i18n.number_of_projects),
+ React.DOM.th(null, cap(i18n.created_by)),
+ React.DOM.th(null, cap(i18n.created_at)),
+ React.DOM.th(null, i18n.iati_version),
+ React.DOM.th( {className:"text-right"}, cap(i18n.actions))
)
+ ),
+ React.DOM.tbody(null,
+ exports
)
)
);
@@ -242,7 +379,8 @@ function loadComponents() {
return {
exports: null,
initializing: true,
- refreshing: false
+ refreshing: false,
+ actionInProgress: false
};
},
@@ -277,16 +415,122 @@ function loadComponents() {
}
},
+ publicFile: function() {
+ if (this.state.exports === null) {
+ return null;
+ } else {
+ for (var i = 0; i < this.state.exports.results.length; i++) {
+ var exp = this.state.exports.results[i];
+ if (exp.iati_file !== '' && exp.is_public) {
+ return exp.id;
+ }
+ }
+ return null;
+ }
+ },
+
+ findExport: function(exportId) {
+ for (var i = 0; i < this.state.exports.results.length; i++) {
+ var exp = this.state.exports.results[i];
+ if (exp.id === exportId) {
+ return exp;
+ }
+ }
+ return null;
+ },
+
+ setPublic: function(exportId) {
+ // Basically what we do is to set this export to public first, and then set all
+ // newer exports to private. This automatically makes this export the public export.
+ var thisApp = this,
+ exportUrl = endpoints.base_url + endpoints.iati_export,
+ thisExport = this.findExport(exportId),
+ newerExports = [],
+ newerExportsUpdated = 0,
+ publicData = JSON.stringify({'is_public': true}),
+ privateData = JSON.stringify({'is_public': false});
+
+ function allExportsUpdated() {
+ thisApp.loadExports(false);
+ thisApp.setState({actionInProgress: false});
+ }
+
+ function exportUpdated(response) {
+ newerExportsUpdated++;
+ if (newerExportsUpdated === newerExports.length) {
+ allExportsUpdated();
+ }
+ }
+
+ // Set current IATI export to public
+ this.setState({actionInProgress: true});
+ apiCall('PATCH', exportUrl.replace('{iati_export}', exportId), publicData);
+
+ // Find the newer IATI exports
+ for (var i = 0; i < this.state.exports.results.length; i++) {
+ var newerExp = this.state.exports.results[i];
+ if (newerExp.id !== exportId && newerExp.created_at > thisExport.created_at) {
+ newerExports.push(newerExp);
+ }
+ }
+
+ // Update the newer IATI exports
+ if (newerExports.length > 0) {
+ for (var j = 0; j < newerExports.length; j++) {
+ var exp = newerExports[j];
+ apiCall('PATCH', exportUrl.replace('{iati_export}', exp.id), privateData, exportUpdated);
+ }
+ } else {
+ allExportsUpdated();
+ }
+ },
+
render: function() {
+ var initOrTable,
+ refreshing,
+ exportCount,
+ exportCountString,
+ lastExportDescription;
+
+ refreshing = this.state.refreshing ? React.DOM.span( {className:"small"}, React.DOM.i( {className:"fa fa-spin fa-spinner"} ),' ' + cap(i18n.refreshing) + ' ' + i18n.iati_exports + '...') : React.DOM.span(null );
+ exportCount = !this.state.initializing ? this.state.exports.count : null;
+ exportCountString = (exportCount !== null && exportCount > 0) ? ' ' + this.state.exports.count + ' ' : ' ';
+
+ if (this.state.initializing) {
+ // Only show a message that data is being loading when initializing
+ initOrTable = React.DOM.span( {className:"small"}, React.DOM.i( {className:"fa fa-spin fa-spinner"}),' ' + cap(i18n.loading) + ' ' + i18n.last + ' ' + i18n.iati_exports + '...');
+ } else if (exportCount > 0) {
+ // Show a table of exiting imports (max 10) when the data has been loaded and exports exist
+ initOrTable = React.createElement(ExportsTable, {
+ exports: this.state.exports,
+ refreshing: this.state.refreshing,
+ publicFile: this.publicFile(),
+ setPublic: this.setPublic
+ });
+ } else {
+ // Do not show the 'Last exports' part when no exports exist yet
+ return (
+ React.DOM.div(null,
+ React.DOM.h4( {className:"topMargin"}, cap(i18n.new) + ' ' + i18n.iati_export)
+ )
+ );
+ }
+
+ lastExportDescription = React.DOM.div( {className:"lastExportDescription"},
+ React.DOM.span(null, cap(i18n.last_exports_1)),
+ React.DOM.a( {href:i18n.last_exports_url, target:"_blank"}, i18n.last_exports_url),
+ React.DOM.span(null, '. ' + cap(i18n.last_exports_2) + ' ' + cap(i18n.last_exports_3)),
+ React.DOM.a( {href:"http://iatiregistry.org", target:"_blank"}, i18n.iati_registry),
+ React.DOM.span(null, i18n.last_exports_4)
+ );
+
return (
React.DOM.div(null,
- React.DOM.h4( {className:"topMargin"}, capitalizeFirstLetter(i18n.last_ten) + ' ' + i18n.iati_exports),
- React.createElement(ExportsTable, {
- exports: this.state.exports,
- initializing: this.state.initializing,
- refreshing: this.state.refreshing
- }),
- React.DOM.h4( {className:"topMargin"}, capitalizeFirstLetter(i18n.new) + ' ' + i18n.iati_export)
+ React.DOM.h4( {className:"topMargin"}, cap(i18n.last) + exportCountString + i18n.iati_exports),
+ lastExportDescription,
+ refreshing,
+ initOrTable,
+ React.DOM.h4( {className:"topMargin"}, cap(i18n.new) + ' ' + i18n.iati_export)
)
);
}
@@ -329,8 +573,9 @@ function loadAndRenderReact() {
}
document.addEventListener('DOMContentLoaded', function() {
- i18n = JSON.parse(document.getElementById("translations").innerHTML);
endpoints = JSON.parse(document.getElementById("endpoints").innerHTML);
+ months = JSON.parse(document.getElementById("months").innerHTML);
+ i18n = JSON.parse(document.getElementById("translations").innerHTML);
if (document.getElementById('myIATIContainer')) {
if (typeof React !== 'undefined' && typeof ReactDOM !== 'undefined') {
diff --git a/akvo/rsr/static/scripts-src/my-iati.jsx b/akvo/rsr/static/scripts-src/my-iati.jsx
index d3d4947483..6ec817c0ac 100644
--- a/akvo/rsr/static/scripts-src/my-iati.jsx
+++ b/akvo/rsr/static/scripts-src/my-iati.jsx
@@ -7,6 +7,7 @@
var csrftoken,
endpoints,
+ months,
i18n;
/* CSRF TOKEN (this should really be added in base.html, we use it everywhere) */
@@ -27,7 +28,7 @@ function getCookie(name) {
csrftoken = getCookie('csrftoken');
/* Capitalize the first character of a string */
-function capitalizeFirstLetter(string) {
+function cap(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
@@ -45,17 +46,30 @@ function apiCall(method, url, data, successCallback, retries) {
var success = function(newResponse) {
var oldResults = response.results;
response.results = oldResults.concat(newResponse.results);
- return successCallback(response);
+ if (successCallback !== undefined) {
+ return successCallback(response);
+ } else {
+ return false;
+ }
};
apiCall(method, response.next, data, success);
} else {
- return successCallback(response);
+ if (successCallback !== undefined) {
+ return successCallback(response);
+ } else {
+ return false;
+ }
}
} else {
- return successCallback(response);
+ if (successCallback !== undefined) {
+ return successCallback(response);
+ } else {
+ return false;
+ }
}
} else {
- var message = i18nResults.general_error + ': ';
+ // var message = i18nResults.general_error + ': ';
+ var message = 'general error: ';
for (var key in response) {
if (response.hasOwnProperty(key)) {
message += response[key] + '. ';
@@ -115,6 +129,47 @@ function loadAsync(url, callback, retryCount, retryLimit) {
xmlHttp.send();
}
+function getDateDescription(month) {
+ switch (month) {
+ case 0:
+ return months.january;
+ case 1:
+ return months.february;
+ case 2:
+ return months.march;
+ case 3:
+ return months.april;
+ case 4:
+ return months.may;
+ case 5:
+ return months.june;
+ case 6:
+ return months.july;
+ case 7:
+ return months.august;
+ case 8:
+ return months.september;
+ case 9:
+ return months.october;
+ case 10:
+ return months.november;
+ case 11:
+ return months.december;
+ }
+}
+
+function displayDate(dateString) {
+ // Display a dateString like "25 Jan 2016"
+ if (dateString !== undefined && dateString !== null) {
+ var date = new Date(dateString.split(".")[0].replace("/", /-/g));
+ var day = date.getUTCDate();
+ var month = getDateDescription(date.getUTCMonth());
+ var year = date.getUTCFullYear();
+ return day + " " + month + " " + year;
+ }
+ return i18n.unknown_date;
+}
+
function processResponse(label, response) {
var label_content, checks, all_checks_passed, span, checks_response;
@@ -217,21 +272,103 @@ function loadComponents() {
}
});
+ var ExportRow = React.createClass({
+ openPublicFile: function() {
+ window.open(i18n.last_exports_url, '_blank');
+ },
+
+ openFile: function() {
+ window.open(endpoints.base_url + '/media/' + this.props.exp.iati_file, '_blank');
+ },
+
+ setPublic: function() {
+ this.props.setPublic(this.props.exp.id);
+ },
+
+ renderActions: function() {
+ if (this.props.publicFile) {
+ return (
+
+ {cap(i18n.view_public_file)}
+
+ );
+ } else if (this.props.exp.iati_file) {
+ return (
+
+
+ {cap(i18n.view_file)}
+
+
+ {cap(i18n.set_public)}
+
+
+ );
+ } else {
+ return (
+
+ {cap(i18n.no_iati_file)}
+
+ );
+ }
+ },
+
+ renderRowClass: function() {
+ if (this.props.publicFile) {
+ return 'publicFile';
+ } else if (this.props.exp.status === 2) {
+ return 'inProgress';
+ } else if (this.props.exp.status === 4 || this.props.exp.iati_file === '') {
+ return 'cancelled';
+ } else {
+ return '';
+ }
+ },
+
+ render: function() {
+ return (
+
+ {this.props.exp.status_label}
+ {this.props.exp.projects.length}
+ {this.props.exp.user_name}
+ {displayDate(this.props.exp.created_at)}
+ {'v' + this.props.exp.version}
+ {this.renderActions()}
+
+ );
+ }
+ });
+
var ExportsTable = React.createClass({
render: function() {
+ var thisTable = this;
+
+ var exports = this.props.exports.results.map(function(exp) {
+ var publicFile = thisTable.props.publicFile === exp.id;
+
+ return React.createElement(ExportRow, {
+ key: exp.id,
+ exp: exp,
+ publicFile: publicFile,
+ setPublic: thisTable.props.setPublic
+ });
+ });
+
+
return (
-
+
- Last export
- User
- Created at
- IATI version
- status
- IATI file
- Number of projects
+ {cap(i18n.status)}
+ {i18n.number_of_projects}
+ {cap(i18n.created_by)}
+ {cap(i18n.created_at)}
+ {i18n.iati_version}
+ {cap(i18n.actions)}
+
+ {exports}
+
);
}
@@ -242,7 +379,8 @@ function loadComponents() {
return {
exports: null,
initializing: true,
- refreshing: false
+ refreshing: false,
+ actionInProgress: false
};
},
@@ -277,16 +415,122 @@ function loadComponents() {
}
},
+ publicFile: function() {
+ if (this.state.exports === null) {
+ return null;
+ } else {
+ for (var i = 0; i < this.state.exports.results.length; i++) {
+ var exp = this.state.exports.results[i];
+ if (exp.iati_file !== '' && exp.is_public) {
+ return exp.id;
+ }
+ }
+ return null;
+ }
+ },
+
+ findExport: function(exportId) {
+ for (var i = 0; i < this.state.exports.results.length; i++) {
+ var exp = this.state.exports.results[i];
+ if (exp.id === exportId) {
+ return exp;
+ }
+ }
+ return null;
+ },
+
+ setPublic: function(exportId) {
+ // Basically what we do is to set this export to public first, and then set all
+ // newer exports to private. This automatically makes this export the public export.
+ var thisApp = this,
+ exportUrl = endpoints.base_url + endpoints.iati_export,
+ thisExport = this.findExport(exportId),
+ newerExports = [],
+ newerExportsUpdated = 0,
+ publicData = JSON.stringify({'is_public': true}),
+ privateData = JSON.stringify({'is_public': false});
+
+ function allExportsUpdated() {
+ thisApp.loadExports(false);
+ thisApp.setState({actionInProgress: false});
+ }
+
+ function exportUpdated(response) {
+ newerExportsUpdated++;
+ if (newerExportsUpdated === newerExports.length) {
+ allExportsUpdated();
+ }
+ }
+
+ // Set current IATI export to public
+ this.setState({actionInProgress: true});
+ apiCall('PATCH', exportUrl.replace('{iati_export}', exportId), publicData);
+
+ // Find the newer IATI exports
+ for (var i = 0; i < this.state.exports.results.length; i++) {
+ var newerExp = this.state.exports.results[i];
+ if (newerExp.id !== exportId && newerExp.created_at > thisExport.created_at) {
+ newerExports.push(newerExp);
+ }
+ }
+
+ // Update the newer IATI exports
+ if (newerExports.length > 0) {
+ for (var j = 0; j < newerExports.length; j++) {
+ var exp = newerExports[j];
+ apiCall('PATCH', exportUrl.replace('{iati_export}', exp.id), privateData, exportUpdated);
+ }
+ } else {
+ allExportsUpdated();
+ }
+ },
+
render: function() {
+ var initOrTable,
+ refreshing,
+ exportCount,
+ exportCountString,
+ lastExportDescription;
+
+ refreshing = this.state.refreshing ? {' ' + cap(i18n.refreshing) + ' ' + i18n.iati_exports + '...'} : ;
+ exportCount = !this.state.initializing ? this.state.exports.count : null;
+ exportCountString = (exportCount !== null && exportCount > 0) ? ' ' + this.state.exports.count + ' ' : ' ';
+
+ if (this.state.initializing) {
+ // Only show a message that data is being loading when initializing
+ initOrTable = {' ' + cap(i18n.loading) + ' ' + i18n.last + ' ' + i18n.iati_exports + '...'} ;
+ } else if (exportCount > 0) {
+ // Show a table of exiting imports (max 10) when the data has been loaded and exports exist
+ initOrTable = React.createElement(ExportsTable, {
+ exports: this.state.exports,
+ refreshing: this.state.refreshing,
+ publicFile: this.publicFile(),
+ setPublic: this.setPublic
+ });
+ } else {
+ // Do not show the 'Last exports' part when no exports exist yet
+ return (
+
+
{cap(i18n.new) + ' ' + i18n.iati_export}
+
+ );
+ }
+
+ lastExportDescription = ;
+
return (
-
{capitalizeFirstLetter(i18n.last_ten) + ' ' + i18n.iati_exports}
- {React.createElement(ExportsTable, {
- exports: this.state.exports,
- initializing: this.state.initializing,
- refreshing: this.state.refreshing
- })}
- {capitalizeFirstLetter(i18n.new) + ' ' + i18n.iati_export}
+ {cap(i18n.last) + exportCountString + i18n.iati_exports}
+ {lastExportDescription}
+ {refreshing}
+ {initOrTable}
+ {cap(i18n.new) + ' ' + i18n.iati_export}
);
}
@@ -329,8 +573,9 @@ function loadAndRenderReact() {
}
document.addEventListener('DOMContentLoaded', function() {
- i18n = JSON.parse(document.getElementById("translations").innerHTML);
endpoints = JSON.parse(document.getElementById("endpoints").innerHTML);
+ months = JSON.parse(document.getElementById("months").innerHTML);
+ i18n = JSON.parse(document.getElementById("translations").innerHTML);
if (document.getElementById('myIATIContainer')) {
if (typeof React !== 'undefined' && typeof ReactDOM !== 'undefined') {
diff --git a/akvo/rsr/static/styles-src/main.css b/akvo/rsr/static/styles-src/main.css
index 5f94194a27..b91a848704 100755
--- a/akvo/rsr/static/styles-src/main.css
+++ b/akvo/rsr/static/styles-src/main.css
@@ -631,16 +631,13 @@ nav.navbar-fixed-top {
#createProject:hover {
background: #2c2a74; }
-.indicator-period-list.parentProject .relatedInfo,
-.indicator-period-list.childProject .relatedInfo {
+.indicator-period-list.parentProject .relatedInfo, .indicator-period-list.childProject .relatedInfo {
color: #2c2a74; }
-.indicator-period-list.parentProject .relatedInfoProjectTitle,
-.indicator-period-list.childProject .relatedInfoProjectTitle {
+.indicator-period-list.parentProject .relatedInfoProjectTitle, .indicator-period-list.childProject .relatedInfoProjectTitle {
display: none;
margin-top: 15px; }
- .indicator-period-list.parentProject .relatedInfoProjectTitle + .indicator-periods-title,
- .indicator-period-list.childProject .relatedInfoProjectTitle + .indicator-periods-title {
+ .indicator-period-list.parentProject .relatedInfoProjectTitle + .indicator-periods-title, .indicator-period-list.childProject .relatedInfoProjectTitle + .indicator-periods-title {
margin-top: 15px; }
.indicator-period-list thead tr {
@@ -1333,7 +1330,7 @@ h4.detailedInfo {
.main-list.organisations ul li:hover img {
filter: 0;
-webkit-filter: grayscale(0%);
- filter: url();
+ filter: url(url();
filter: grayscale(0%); }
/* PROJECT */
@@ -1520,7 +1517,7 @@ div.projectTopRow {
div.projectTopRow .projectSideInfo ul li.projectPartners a.logoImg img:hover {
filter: 0;
-webkit-filter: grayscale(0%);
- filter: url();
+ filter: url(url();
filter: grayscale(0%); }
div.projectTopRow .projectSideInfo ul li.projectPartners .partType {
overflow: hidden;
@@ -1634,7 +1631,7 @@ div.textBlock {
.updateComponent {
padding-top: 10px;
padding-bottom: 15px;
- background: #fff6f1; }
+ background: #fff6f2; }
.updateComponent h4 {
margin-bottom: 10px; }
.updateComponent .updateLinkTitle {
@@ -1679,8 +1676,7 @@ div.textBlock {
.projectFinancial .budgetItem {
margin-top: 12px;
width: 60%; }
- .projectFinancial .budgetItem:nth-child(1),
- .projectFinancial .budgetItem:nth-child(2) {
+ .projectFinancial .budgetItem:nth-child(1), .projectFinancial .budgetItem:nth-child(2) {
margin-top: 0; }
/* Project hierarchy */
@@ -1762,8 +1758,7 @@ ul.typeahead-selector {
padding-left: 6px;
padding-top: 4px;
padding-bottom: 4px; }
- ul.typeahead-selector li:hover,
- ul.typeahead-selector li.hover {
+ ul.typeahead-selector li:hover, ul.typeahead-selector li.hover {
font-weight: bold;
cursor: pointer; }
ul.typeahead-selector li a {
@@ -2162,7 +2157,7 @@ body.translationBarActive div.skiptranslate ~ #map {
display: block;
overflow: hidden;
box-sizing: border-box;
- transition: all 0.5s linear;
+ transition: all .5s linear;
padding: 5px 15px;
margin: 0 auto;
-moz-border-radius: 5px;
@@ -2424,8 +2419,7 @@ body.translationBarActive div.skiptranslate ~ #map {
padding: 0.5em;
margin: 0 1em;
color: #00aaff; }
- .tab-menu a:hover,
- .tab-menu a.selected {
+ .tab-menu a:hover, .tab-menu a.selected {
border-bottom: 3px solid #646363;
color: #646363; }
.tab-menu a:active {
@@ -2536,8 +2530,7 @@ article {
.periodValues .period-actual > span:first-child span,
.periodValues .period-target-comment > span:first-child span {
display: inline; }
- .baseline .baseline-value span:nth-child(2n),
- .baseline .baseline-value .actualValueSpan,
+ .baseline .baseline-value span:nth-child(2n), .baseline .baseline-value .actualValueSpan,
.baseline .baseline-year span:nth-child(2n),
.baseline .baseline-year .actualValueSpan,
.baseline .period-target span:nth-child(2n),
@@ -2554,11 +2547,11 @@ article {
.periodValues .period-target .actualValueSpan,
.periodValues .period-actual span:nth-child(2n),
.periodValues .period-actual .actualValueSpan,
- .periodValues .period-target-comment span:nth-child(2n), .periodValues .period-target-comment .actualValueSpan {
+ .periodValues .period-target-comment span:nth-child(2n),
+ .periodValues .period-target-comment .actualValueSpan {
display: block;
font-family: "Montserrat", "Helvetica Neue", Helvetica, Arial, sans-serif; }
- .baseline .baseline-value span:nth-child(2n) span,
- .baseline .baseline-value .actualValueSpan span,
+ .baseline .baseline-value span:nth-child(2n) span, .baseline .baseline-value .actualValueSpan span,
.baseline .baseline-year span:nth-child(2n) span,
.baseline .baseline-year .actualValueSpan span,
.baseline .period-target span:nth-child(2n) span,
@@ -2575,10 +2568,10 @@ article {
.periodValues .period-target .actualValueSpan span,
.periodValues .period-actual span:nth-child(2n) span,
.periodValues .period-actual .actualValueSpan span,
- .periodValues .period-target-comment span:nth-child(2n) span, .periodValues .period-target-comment .actualValueSpan span {
+ .periodValues .period-target-comment span:nth-child(2n) span,
+ .periodValues .period-target-comment .actualValueSpan span {
display: inline; }
- .baseline .baseline-value span:nth-child(2n) span:nth-child(1),
- .baseline .baseline-value .actualValueSpan span:nth-child(1),
+ .baseline .baseline-value span:nth-child(2n) span:nth-child(1), .baseline .baseline-value .actualValueSpan span:nth-child(1),
.baseline .baseline-year span:nth-child(2n) span:nth-child(1),
.baseline .baseline-year .actualValueSpan span:nth-child(1),
.baseline .period-target span:nth-child(2n) span:nth-child(1),
@@ -2595,7 +2588,8 @@ article {
.periodValues .period-target .actualValueSpan span:nth-child(1),
.periodValues .period-actual span:nth-child(2n) span:nth-child(1),
.periodValues .period-actual .actualValueSpan span:nth-child(1),
- .periodValues .period-target-comment span:nth-child(2n) span:nth-child(1), .periodValues .period-target-comment .actualValueSpan span:nth-child(1) {
+ .periodValues .period-target-comment span:nth-child(2n) span:nth-child(1),
+ .periodValues .period-target-comment .actualValueSpan span:nth-child(1) {
margin-left: 10px; }
.baseline .period-target-comment span:nth-child(2n),
.periodValues .period-target-comment span:nth-child(2n) {
@@ -2696,8 +2690,7 @@ article {
border: 1px solid rgba(153, 153, 153, 0.8);
left: 50px;
top: -2px; }
- .baseline .baseline-year .result-tooltip .tooltip-arrow:after,
- .baseline .baseline-year .result-tooltip .tooltip-arrow:before,
+ .baseline .baseline-year .result-tooltip .tooltip-arrow:after, .baseline .baseline-year .result-tooltip .tooltip-arrow:before,
.baseline .period-actual .result-tooltip .tooltip-arrow:after,
.baseline .period-actual .result-tooltip .tooltip-arrow:before,
.periodValues .baseline-year .result-tooltip .tooltip-arrow:after,
@@ -3032,10 +3025,7 @@ article {
margin-right: 1.4em; }
.indicator-container .indicator-group .table td {
vertical-align: middle; }
- .indicator-container .indicator-group .table td.period-td,
- .indicator-container .indicator-group .table td.actual-td,
- .indicator-container .indicator-group .table td.target-td,
- .indicator-container .indicator-group .table td.actions-td {
+ .indicator-container .indicator-group .table td.period-td, .indicator-container .indicator-group .table td.actual-td, .indicator-container .indicator-group .table td.target-td, .indicator-container .indicator-group .table td.actions-td {
white-space: nowrap; }
.indicator-container .indicator-group .table td.target-td {
font-weight: 600; }
@@ -3661,8 +3651,7 @@ label.fileUpload input[type="file"] {
opacity: 0.5; }
.update-dialog-container td .update-entry-container .edit-slider .change-indicator.negative {
background-color: red; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal {
height: 5px;
border: 0;
background-color: rgba(255, 255, 255, 0);
@@ -3673,15 +3662,13 @@ label.fileUpload input[type="file"] {
-webkit-border-radius: 4px;
border-radius: 4px;
box-shadow: none; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-origin,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-origin {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-origin, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-origin {
background-color: rgba(255, 255, 255, 0);
-moz-border-radius: 4px;
-o-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle {
position: relative;
width: 28px;
height: 28px;
@@ -3692,8 +3679,7 @@ label.fileUpload input[type="file"] {
box-shadow: none;
top: -7px;
color: white; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:after,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:after {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:after, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:after {
display: block;
content: '|||';
color: white;
@@ -3706,17 +3692,13 @@ label.fileUpload input[type="file"] {
background-color: transparent;
top: 0;
left: -1px; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:before,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:before {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:before, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:before {
display: none; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:hover,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:hover {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:hover, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:hover {
background-color: #009ceb; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:active,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:active {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle:active, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle:active {
background-color: #de8929; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle .handle-label,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle .handle-label {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle .handle-label, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle .handle-label {
position: absolute;
top: -32px;
background-color: #007ab8;
@@ -3724,8 +3706,7 @@ label.fileUpload input[type="file"] {
width: 44px;
left: -8px;
text-align: center; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle .handle-label:after,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle .handle-label:after {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle .handle-label:after, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle .handle-label:after {
content: '';
height: 0px;
width: 0px;
@@ -3735,8 +3716,7 @@ label.fileUpload input[type="file"] {
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #007ab8; }
- .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle .handle-change-label,
- .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle .handle-change-label {
+ .update-dialog-container td .update-entry-container .edit-slider .noUi-base .noUi-handle .handle-change-label, .update-dialog-container td .update-entry-container .edit-slider.noUi-horizontal .noUi-handle .handle-change-label {
position: absolute;
width: 42px;
text-align: center;
@@ -3936,8 +3916,7 @@ div#my-reports {
border: 1px solid rgba(153, 153, 153, 0.8);
right: 8px;
top: -2px; }
- .period-td .result-tooltip .tooltip-arrow:after,
- .period-td .result-tooltip .tooltip-arrow:before {
+ .period-td .result-tooltip .tooltip-arrow:after, .period-td .result-tooltip .tooltip-arrow:before {
bottom: 100%;
left: 50%;
border: solid transparent;
@@ -3957,6 +3936,26 @@ div#my-reports {
border-width: 8px;
margin-left: -8px; }
+div#myIATIContainer tr.publicFile {
+ background: rgba(92, 184, 92, 0.1) !important;
+ color: #5cb85c !important; }
+
+div#myIATIContainer tr.inProgress {
+ background: rgba(222, 137, 41, 0.1) !important;
+ color: #de8929 !important; }
+
+div#myIATIContainer tr.cancelled {
+ background: rgba(238, 49, 36, 0.1) !important;
+ color: #ee3124 !important; }
+
+div#myIATIContainer button.btn-default {
+ margin: -5px 0 0 25px;
+ background: #202024;
+ color: white;
+ border: none; }
+ div#myIATIContainer button.btn-default:hover {
+ background: #2c2a74; }
+
.iatiCheck span.noCheck {
color: #202024; }
diff --git a/akvo/rsr/static/styles-src/main.scss b/akvo/rsr/static/styles-src/main.scss
index 0bf147c17a..278c7c0750 100755
--- a/akvo/rsr/static/styles-src/main.scss
+++ b/akvo/rsr/static/styles-src/main.scss
@@ -4613,6 +4613,33 @@ div#my-reports {
}
}
+// My IATI
+div#myIATIContainer {
+ tr {
+ &.publicFile {
+ background: rgba($progressSuccess, 0.1) !important;
+ color: $progressSuccess !important;
+ }
+ &.inProgress {
+ background: rgba($flowOrange, 0.1) !important;
+ color: $flowOrange !important;
+ }
+ &.cancelled {
+ background: rgba($akvoTvRed, 0.1) !important;
+ color: $akvoTvRed !important;
+ }
+ }
+ button.btn-default {
+ margin: -5px 0 0 25px;
+ background: $akvoBlack;
+ color: white;
+ border: none;
+ &:hover {
+ background: $rsrBlue;
+ }
+ }
+}
+
.iatiCheck {
span.noCheck {
color: $akvoBlack;
diff --git a/akvo/templates/myrsr/my_iati.html b/akvo/templates/myrsr/my_iati.html
index 67da5b0c06..d8634c83b4 100644
--- a/akvo/templates/myrsr/my_iati.html
+++ b/akvo/templates/myrsr/my_iati.html
@@ -43,16 +43,6 @@ {% trans 'Select an organisation' %}
{# Container for showing a table with existing IATI exports and creating a new IATI export (React) #}
-
- {% blocktrans with org_id=selected_org.id host=request.META.HTTP_HOST %}
- The latest IATI file for your organisation is always available at this link:
-
http://{{ host }}/organisation/{{ org_id }}/iati/ .
- If you already have existing IATI exports, you can select which of the IATI exports should be available at this link.
- This makes it possible to register only this link in the
-
IATI registry and automatically update your IATI file in the IATI
- registry by updating your IATI file in RSR.
- {% endblocktrans %}
-
{# React implementation for creating a new IATI export #}
@@ -119,11 +109,31 @@
{
"iati_export": "{% trans 'IATI export' %}",
"iati_exports": "{% trans 'IATI exports' %}",
+ "last_exports_1": "{% trans 'the public IATI file for your organisation is always available at this link: ' %}",
+ "last_exports_2": "{% trans 'if you already have existing IATI exports, you can select which of the IATI exports should be available at this link.' %}",
+ "last_exports_3": "{% trans 'this makes it possible to register only this link in the ' %}",
+ "last_exports_4": "{% trans ' and automatically update your IATI file in the IATI registry by updating your IATI file in RSR.' %}",
+ "last_exports_url": "http://{{ request.META.HTTP_HOST }}/organisation/{{ selected_org.id }}/iati/",
+ "iati_registry": "{% trans 'IATI registry' %}",
+ "loading": "{% trans 'loading' %}",
+ "refreshing": "{% trans 'refreshing' %}",
+ "last": "{% trans 'last' %}",
+ "view_public_file": "{% trans 'view public file' %}",
+ "view_file": "{% trans 'view file' %}",
+ "set_public": "{% trans 'set as public file' %}",
+ "created_by": "{% trans 'created by' %}",
+ "created_at": "{% trans 'created at' %}",
+ "iati_version": "{% trans 'IATI version' %}",
+ "status": "{% trans 'status' %}",
+ "number_of_projects": "{% trans '# of projects' %}",
+ "actions": "{% trans 'actions' %}",
+ "no_iati_file": "{% trans 'no IATI file' %}",
"new": "{% trans 'new' %}",
- "last_ten": "{% trans 'last 10' %}",
+ "no_exports": "{% trans 'your organisation has no IATI exports yet, create a new IATI export below' %}",
"perform_checks": "{% trans 'Perform checks' %}",
"performing_checks": "{% trans 'Performing checks' %}",
- "warning": "{% trans 'Warning' %}"
+ "warning": "{% trans 'Warning' %}",
+ "unknown_date": "{% trans 'Unknown date' %}"
}
@@ -131,7 +141,26 @@
+
+ {# Months #}
+