diff --git a/app/app.js b/app/app.js
index db7a0f7d7b..ee7d9dc652 100644
--- a/app/app.js
+++ b/app/app.js
@@ -39,7 +39,6 @@ var backendUrl = window.ushahidi.backendUrl = (window.ushahidi.backendUrl || BAC
apiUrl = window.ushahidi.apiUrl = backendUrl + '/api/v3',
platform_websocket_redis_adapter_url = window.ushahidi.platform_websocket_redis_adapter_url || '',
claimedAnonymousScopes = [
- 'apikeys',
'posts',
'country_codes',
'media',
@@ -58,8 +57,7 @@ var backendUrl = window.ushahidi.backendUrl = (window.ushahidi.backendUrl || BAC
'contacts',
'roles',
'permissions',
- 'csv',
- 'tos'
+ 'csv'
];
angular.module('app',
@@ -94,7 +92,7 @@ angular.module('app',
OAUTH_CLIENT_ID : 'ushahidiui',
OAUTH_CLIENT_SECRET : '35e7f0bca957836d05ca0492211b0ac707671261',
CLAIMED_ANONYMOUS_SCOPES : claimedAnonymousScopes,
- CLAIMED_USER_SCOPES : claimedAnonymousScopes.concat('dataproviders'),
+ CLAIMED_USER_SCOPES : ['*'],
MAPBOX_API_KEY : window.ushahidi.mapboxApiKey || 'pk.eyJ1IjoidXNoYWhpZGkiLCJhIjoiY2lxaXUzeHBvMDdndmZ0bmVmOWoyMzN6NiJ9.CX56ZmZJv0aUsxvH5huJBw', // Default OSS mapbox api key
TOS_RELEASE_DATE : new Date(window.ushahidi.tosReleaseDate).toJSON() ? new Date(window.ushahidi.tosReleaseDate) : false, // Date in UTC
PLATFORM_WEBSOCKET_REDIS_ADAPTER_URL : platform_websocket_redis_adapter_url,
diff --git a/app/bootstrap.js b/app/bootstrap.js
index 762663cac1..d7025224f5 100644
--- a/app/bootstrap.js
+++ b/app/bootstrap.js
@@ -13,9 +13,14 @@ angular.lazy()
// Show loading
angular.element(document.getElementById('bootstrap-loading')).removeClass('hidden');
})
- .error(function () {
+ .error(function (error) {
// Show error
- angular.element(document.getElementById('bootstrap-error')).removeClass('hidden');
+ try {
+ error.data.errors[0].message &&
+ angular.element(document.getElementById('bootstrap-error-message')).html(error.data.errors[0].message);
+ } finally {
+ angular.element(document.getElementById('bootstrap-error')).removeClass('hidden');
+ }
})
.done(function () {
// Hide loading
diff --git a/app/common/auth/authentication-interceptor.config.js b/app/common/auth/authentication-interceptor.config.js
index 742b10415e..28ad87366c 100644
--- a/app/common/auth/authentication-interceptor.config.js
+++ b/app/common/auth/authentication-interceptor.config.js
@@ -31,7 +31,11 @@ function AuthInterceptor($rootScope, $injector, $q, CONST, Session, _) {
// Save access token
Session.setSessionDataEntry('accessToken', accessToken);
// Save token expires time
- Session.setSessionDataEntry('accessTokenExpires', authResponse.data.expires);
+ if (authResponse.data.expires_in) {
+ Session.setSessionDataEntry('accessTokenExpires', Math.floor(Date.now() / 1000) + authResponse.data.expires_in);
+ } else if (authResponse.data.expires) {
+ Session.setSessionDataEntry('accessTokenExpires', authResponse.data.expires);
+ }
Session.setSessionDataEntry('grantType', 'client_credentials');
// Add Authorization header
diff --git a/app/common/auth/authentication.service.js b/app/common/auth/authentication.service.js
index 1ca0e7d868..11e3b1d428 100644
--- a/app/common/auth/authentication.service.js
+++ b/app/common/auth/authentication.service.js
@@ -89,7 +89,11 @@ function (
handleRequestSuccess = function (authResponse) {
var accessToken = authResponse.data.access_token;
Session.setSessionDataEntry('accessToken', accessToken);
- Session.setSessionDataEntry('accessTokenExpires', authResponse.data.expires);
+ if (authResponse.data.expires_in) {
+ Session.setSessionDataEntry('accessTokenExpires', Math.floor(Date.now() / 1000) + authResponse.data.expires_in);
+ } else if (authResponse.data.expires) {
+ Session.setSessionDataEntry('accessTokenExpires', authResponse.data.expires);
+ }
Session.setSessionDataEntry('grantType', 'password');
$http.get(Util.apiUrl('/users/me')).then(
diff --git a/app/common/common-module.js b/app/common/common-module.js
index c398fc2300..cee463eeb5 100644
--- a/app/common/common-module.js
+++ b/app/common/common-module.js
@@ -29,6 +29,7 @@ angular.module('ushahidi.common', [
.service('ApiKeyEndpoint', require('./services/endpoints/apikey.js'))
.service('ConfigEndpoint', require('./services/endpoints/config.js'))
.service('UserEndpoint', require('./services/endpoints/user-endpoint.js'))
+.service('UserSettingsEndpoint', require('./services/endpoints/user-settings.js'))
.service('FormEndpoint', require('./services/endpoints/form.js'))
.service('FormAttributeEndpoint', require('./services/endpoints/form-attributes.js'))
.service('FormRoleEndpoint', require('./services/endpoints/form-roles.js'))
@@ -52,8 +53,10 @@ angular.module('ushahidi.common', [
.service('TermsOfServiceEndpoint', require('./services/endpoints/terms-of-service-endpoint.js'))
.service('ExportJobEndpoint', require('./services/endpoints/export-jobs.js'))
.service('CountryCodeEndpoint', require('./services/endpoints/country-code-endpoint.js'))
-
-
+.service('HxlTagEndpoint', require('./services/endpoints/hxl-tag-endpoint.js'))
+.service('HxlLicenseEndpoint', require('./services/endpoints/hxl-license-endpoint.js'))
+.service('HxlMetadataEndpoint', require('./services/endpoints/hxl-metadata-endpoint.js'))
+.service('HxlOrganisationsEndpoint', require('./services/endpoints/hxl-organisations-endpoint.js'))
// Other services
.service('ViewHelper', require('./services/view-helper.js'))
.service('Features', require('./services/features.js'))
@@ -71,6 +74,7 @@ angular.module('ushahidi.common', [
.controller('intercom', require('./controllers/intercom.js'))
.service('LoadingProgress', require('./services/loadingProgress.service.js'))
.service('DataExport', require('./services/data-export.service.js'))
+.service('HxlExport', require('./services/hxl-export.service.js'))
.service('DataImport', require('./services/data-import.service.js'))
// Global directives
.directive('publishSelector', require('./directives/publish-selector.js'))
diff --git a/app/common/locales/en.json b/app/common/locales/en.json
index 2a1a35c791..8a727c608b 100644
--- a/app/common/locales/en.json
+++ b/app/common/locales/en.json
@@ -145,8 +145,6 @@
"new_post" : "New Post",
"by" : "By",
"context_body": "A summary of how people are interacting with {{site}}.",
- "by" : "By",
- "context_body": "A summary of how people are interacting with {{site}}.",
"inbound": "Inbound Response Messages",
"outbound": "Outbound Surveying Messages",
"recipients": "Unique Recipients of Targeted Survey",
@@ -283,6 +281,10 @@
"require_section" : "Require this task be completed before a post can be visible to the public",
"hide_author_information" : "Hide author information",
"hide_author_information_desc" : "Only people with permission to edit responses will be able to see who submitted them; and only when editing them.",
+ "hide_location_information" : "Hide exact location information",
+ "hide_location_information_desc" : "Only people with permission to edit responses will be able to see exact locations. Other people will see rounded locations. The location will be accurate to {{precision}}km.",
+ "hide_time_information" : "Hide exact time information",
+ "hide_time_information_desc" : "Only people with permission to edit responses will be able to see exact time submitted. Other people will see only the date.",
"share" : "Share",
"task_name" : "Task name",
"required_field" : "Required",
@@ -990,7 +992,11 @@
"data_sources_desc" : "Configure email, SMS, and social media channels that help your deployment collect survey data.",
"import" : "Import",
"import_desc" : "Upload survey data to your deployment from a CSV file.",
+ "user_settings": "Configure HDX API",
+ "user_settings_desc": "Configure your API so that your tagged Ushahidi data can be uploaded to your Humanitarian Data Exchange (HDX) account.",
"export": "Export data",
+ "export_hxl": "Export and tag data",
+ "export_desc_hxl": "Export your data as a CSV file or assign tags and attributes to your data and upload directly to a Humanitarian Data Exchange (HDX) account or export as a tagged CSV file.",
"export_desc": "Export all of your data as a CSV file or choose custom fields to export",
"users" : "Users",
"users_desc" : "Create and manage the people that contribute to your deployment.",
@@ -1003,6 +1009,19 @@
"plans" : "Plans",
"plan_desc" : "Your deployment's current plan is {{current_plan}}."
},
+ "user_settings": {
+ "user_settings_desc_1": "Here you can add your unique API key for your Humanitarian Data Exchange (HDX) account.",
+ "user_settings_desc_2": "Once set up, this will enable you to upload data directly to a Humanitarian Data Exchange (HDX) account.",
+ "user_settings_desc_3": "You can find your API key on your Humanitarian Data Exchange (HDX) profile once you're logged in.",
+ "view_guide": "View the guide to your API key",
+ "hdx_maintainer_id" : "HDX Maintainer Id",
+ "api_key": "Api key",
+ "profile_page": "Found on your Humanitarian Data Exchange (HDX) profile page",
+ "valid_key": "A valid key is required",
+ "valid_user": "A valid maintainer id is required",
+ "api_key_saved": "API key saved! You can now tag your data and upload to a Humanitarian Data Exchange (HDX) account.",
+ "start_tagging": "Start tagging data"
+ },
"webhooks": {
"use_webhook_for": "Use webhook for",
"enable_source_destination" : "Enable Source and Destination Fields",
@@ -1121,6 +1140,8 @@
"deployment_logo" : "Deployment logo",
"delete_logo": "Delete logo",
"map_default_baselayer": "Default base layer",
+ "map_location_precision": "Map Precision Level",
+ "map_precise_to": "When hide location is enabled for a survey, locations will be precise to: ",
"map_clustering": "Combine nearby posts",
"map_default_latitude": "Default latitude",
"map_default_longitude": "Default longitude",
@@ -1201,14 +1222,23 @@
},
"data_export": {
"title": "Export data",
+ "title_hxl": "Export and tag data",
"description": "Export all of your data as a CSV or choose specific survey fields you want to export.",
+ "description_hxl": "Export all of your data from Ushahidi as a CSV, choose specific survey fields you want to export as a CSV or assign",
+ "export": "Export",
+ "export_history": "Export History",
+ "hxl_tags": "HXL tags",
+ "hxl_attributes": "HXL attributes",
+ "and_choose": "and choose to upload to an",
+ "HDX": "Humanitarian Data Exchange",
+ "account": "account or download as a HXL 'tagged' CSV file.",
"all": "Export all data",
"select_fields": "Select fields",
"select_fields_title": "Select fields for export...",
"select_fields_desc": "If you don't want to export all of your data at once, you can select specific fields from each survey for export.",
"export_selected": "Export selected fields",
"cancel": "Cancel",
- "export_progress": "Export in progress...",
+ "export_progress": "
Export in progress...
You can leave this page if you want. Your export will continue.
We will let you know when we're done.
",
"no_fields": "Uh oh... you need to select some fields to export first.",
"expires": "Expires: {{expires}}",
"job": "CSV Export {{jobId}}",
@@ -1217,8 +1247,65 @@
"pending": "Status: Pending",
"failed": "Status: Failed",
"queued": "Status: In Progress",
- "export": "Export",
- "export_history": "Export History"
+ "pending_hdx": "Pending HDX",
+ "exported_to_cdn": "Exported to CDN",
+ "tags_attributes": "Assign tags and attributes",
+ "hxl_apikey_alert_1": "It looks like you haven't set up your Humanitarian Data Exchange (HDX) API. Without this set up, you can't tag data and upload to a Humanitarian Data Exchange (HDX) account.",
+ "hxl_configure": "Configure HDX API",
+ "hxl_apikey_alert_2": "We strongly advide you set this up now in",
+ "hxl_apikey_alert_3": "before continuing as you won't be able to upload your data to HDX",
+ "hxl_title": "Assign your HXL tags and attributes, select fields and export or upload",
+ "hxl_desc": "Select specific fields from a survey, assign a tag per field and then choose to assign multiple attributes. Preview your tag and attributes in tag preview.",
+ "hxl_instructions_1": "You can then choose to export your tagged fields to a CSV file or upload to a",
+ "hxl_instructions_2": "Humanitarian Data Exchange (HDX)",
+ "hxl_instructions_3": "account that has been set up in",
+ "hxl_instructions_4": "Configure HDX API",
+ "hxl_instructions_5": "(found in settings menu).",
+ "hxl_instructions_6": "Visit the",
+ "hxl_instructions_7": "HXL tag assist",
+ "hxl_instructions_8": "for more information on how to choose the best HXL tags and attributes for your data or the",
+ "hxl_instructions_9": "HXL 'cheat sheet'",
+ "HXL_tags": "HXL tags",
+ "HXL_attributes": "HXL attributes",
+ "tag_preview": "Tag preview",
+ "upload_title": "Are you ready to upload to an Humanitarian Data Exchange (HDX) account?",
+ "hdx_csv_title": "Are you ready to export to CSV?",
+ "upload_desc": "You selected {{fields}} fields to upload to a Humanitarian Data Exchange (HDX) account.
You assigned tags and attributes - to check, you can go back. If you are done, you can add details and upload.
The Humanitarian Data Exchange (HDX) requires a few more details in order to upload to their system. You'll add these next",
+ "hdx_csv_desc": "You selected {{fields}} fields to export to CSV.
You assigned tags and attributes - to check these are correct, you can go back and check. If you're done, you can export.",
+ "upload_button": "Add dataset details and upload to hdx",
+ "export_button": "Export to csv",
+ "go_back": "Go back and check",
+ "add_details": "Add details",
+ "details_desc": "To upload to the Humanitarian Data Exchange (HDX) some extra details are required.",
+ "privacy_title": "Privacy Settings",
+ "privacy_desc": "You have a choice of sharing your dataset publicly or restricting access to other members of the organisation which owns the dataset.",
+ "this_dataset": "This data set is:",
+ "private_desc": "Private (Only you and other HDX members of your organisation can search, view/edit or download this dataset)",
+ "public_desc": "Public (Anyone can search, view/edit or download this dataset)",
+ "dataset": "Dataset Title & Description",
+ "dataset_desc": "When users search for data on HDX, their search terms will be matched to terms in your title. Avoid using abbreviations in the title which may not be familiar to all users. Also, avoid using words such as current, latest or previous when referring to the time period (e.g Latest 3W) as these terms become misleading as the dataset ages.",
+ "dataset_example": "Example dataset title: Who is Doing What Where in Afghanistan, Jan-Dec 2015",
+ "dataset_title": "Title of data set",
+ "metadata_title": "Metadata",
+ "metadata_desc": "Metadata is additional information about your dataset that will make it easier for others to understand and put your data into context. Datasets on HDX must include a set of metadata fields.",
+ "source": "Source",
+ "organisation": "Organisation",
+ "select_organisation": "Select an organisation",
+ "license": "License",
+ "add_license": "Add license",
+ "read_more_licenses":"Read more about licenses",
+ "submit_hdx": "Submit to HDX Account",
+ "uploading_data": "Uploading data...",
+ "uploading_data_desc": "The data upload to your Humanitarian Data Exchange (HDX) account is in progress...
You can navigate away from this page while this upload happens but please don't close the browser.",
+ "uploading_data_err": "Uh oh... Something went wrong when uploading your data, please check the required fields and your api-key and try again.",
+ "no_fields_selected": "You haven't selected any fields or assigned any hxl tags or attributes. Please select at least one field and assign at least one tag to be able to export to CSV or upload to a Humanitarian Data Exchange (HDX) account.",
+ "validation": {
+ "title": "A title is needed",
+ "source": "Source is needed",
+ "organisation": "An organisation is needed",
+ "license": "A license is needed",
+ "all_fields": "Please fill in all required fields"
+ }
},
"user": {
"role_display" : "Role: {{role}}",
@@ -1324,6 +1411,8 @@
"csv_import_success_info" : "The data from your CSV spreadsheet, {{filename}}, was successfully imported into your {{form_name}} survey.",
"duplicate_fields" : "Columns must be mapped to unique survey fields. The following columns have more than 1 mapping: {{duplicates}}",
"required_fields" : "Required fields must be set to a value. The following fields have not been set: {{required}}",
+ "empty_mapping" : "The CSV file you uploaded is empty. Please check your CSV file and try again",
+ "empty_mapping_empty" : "The CSV file does not contain column names. Please check your CSV file and try again",
"no_mappings" : "No fields have been assigned mappings - at least one field must be mapped to continue",
"csv_import_cancel" : "CSV import cancelled",
"csv_import_cancel_confirm": "Are you sure you want to cancel importing?"
@@ -1472,7 +1561,8 @@
"complete_data_found_message" : "The data from your export can be found in your browser's downloads",
"confirmation": "Got it",
"cancel_export": "Cancel export",
- "canceled_job" : "Your export-job is canceled"
+ "canceled_job" : "Your export-job is canceled",
+ "upload_complete": "Upload complete. You should now see your tagged data in your HDX account."
}
},
"empty": {
diff --git a/app/common/notifications/notify.service.js b/app/common/notifications/notify.service.js
index f0837d28f6..3a6082f8d2 100644
--- a/app/common/notifications/notify.service.js
+++ b/app/common/notifications/notify.service.js
@@ -133,7 +133,7 @@ function Notify(_, $q, $rootScope, $translate, SliderService, ModalService) {
return deferred.promise;
}
- function confirmModal(confirmText, translateValues, description, descriptionValues, button) {
+ function confirmModal(confirmText, translateValues, description, descriptionValues, button, cancel) {
var deferred = $q.defer();
var scope = getScope();
@@ -155,7 +155,13 @@ function Notify(_, $q, $rootScope, $translate, SliderService, ModalService) {
descriptionTemplate = ``;
}
let buttonText = button ? button : 'message.button.default';
- let template = '
' + descriptionTemplate + '
notify.default.proceed_warning
' + '' + `` + '
';
+ let cancelButtonText = cancel ? cancel : 'message.button.cancel';
+ let template = `
+ ${descriptionTemplate}
+
notify.default.proceed_warning
+
+
+
`;
ModalService.openTemplate(
template, confirmText, false, scope, false, false);
diff --git a/app/common/services/data-export.service.js b/app/common/services/data-export.service.js
index a64e6ec90e..79a0f0d277 100644
--- a/app/common/services/data-export.service.js
+++ b/app/common/services/data-export.service.js
@@ -3,15 +3,19 @@ module.exports = DataExport;
DataExport.$inject = ['$rootScope', 'ExportJobEndpoint', 'Notify', '$window', '$timeout', '$interval', 'CONST', '$q', '_'];
function DataExport($rootScope, ExportJobEndpoint, Notify, $window, $timeout, $interval, CONST, $q, _) {
var exportJobs = [];
- function startExport(query) {
+ function startExport(query, hideStartNotification) {
query.entity_type = 'post';
+
// saving the new job to the db
- ExportJobEndpoint.save(query).$promise.then(function (job) {
+ return ExportJobEndpoint.save(query).$promise.then(function (job) {
updateExportJobsList(job);
- // notifies the user
- loadingStatus(true, null, job);
+ if (!hideStartNotification) {
+ // notifies the user
+ loadingStatus(true, null, job);
+ }
// start polling for ready job.
startPolling([ExportJobEndpoint.getFresh({id: job.id})]);
+ return job.id;
}, function (err) {
loadingStatus(false, err);
});
@@ -42,8 +46,13 @@ function DataExport($rootScope, ExportJobEndpoint, Notify, $window, $timeout, $
if (job.status === 'SUCCESS') {
// when job is successful, we stop the polling...
$rootScope.$broadcast('event:export_job:stopped');
- // ..and download the file
- downloadFile(job.url);
+ if (job.send_to_browser) {
+ // ..and download the file
+ downloadFile(job.url);
+ } else if (job.send_to_hdx) {
+ loadingStatus(false, false, job);
+ }
+
updateExportJobsList(job);
} else if (job.status === 'FAILED') {
// when job is failed, we stop the polling...
@@ -126,7 +135,7 @@ function DataExport($rootScope, ExportJobEndpoint, Notify, $window, $timeout, $
Notify.apiErrors(err);
} else {
if (status === true) {
- message = '