Skip to content

Commit

Permalink
Merge branch 'master' into dockerhub-push
Browse files Browse the repository at this point in the history
  • Loading branch information
tuxpiper authored Apr 20, 2020
2 parents 81bd4b1 + 492a043 commit d9dcc29
Show file tree
Hide file tree
Showing 20 changed files with 170 additions and 48 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Ushahidi Platform Web Client
[![Dependency Status](https://david-dm.org/ushahidi/platform-client/dev-status.svg?style=flat)](https://david-dm.org/ushahidi/platform-client#info=devDependencies)

___
## Report and find Ushahidi Platform V3 issues

All our issues live in https://github.com/ushahidi/platform/issues .

## Try it out on Heroku

Expand Down
2 changes: 1 addition & 1 deletion app/common/directives/filter-system/filter-searchbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
ng-model="model.q"
ng-focus="showSearchResults()"
ng-keyup="detectSubmit($event)"
ng-value="model.q"
ng-value="model.q=''"
>
<svg class="iconic" ng-show="!form.q.$viewValue.length">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/img/iconic-sprite.svg#magnifying-glass"></use>
Expand Down
11 changes: 5 additions & 6 deletions app/common/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -844,10 +844,7 @@
"error_in_upload": "Your image is too large (maximum size is 1MB) or has the wrong format (allowed formats are gif, png, jpg and jpeg), please check and try again!"
},
"video" : {
"enter_a" : "Enter a",
"or" : " or ",
"vimeo" : " Vimeo",
"video_url" : " video URL"
"enter_a_url": "Enter a video URL from Youtube or Vimeo."
},
"unstructured" : {
"add_survey" : {
Expand Down Expand Up @@ -1523,8 +1520,10 @@
"save_attribute_success" : "Field {{name}} added",
"edit_form_success" : "Survey {{name}} updated",
"edit_stage_success" : "Survey task {{name}} updated",
"delete_form_confirm" : "Are you sure you want to delete this survey?",
"delete_form_confirm_desc" : "This action cannot be undone. Deleting this survey will remove all of its data, including posts.",
"delete_form_confirm" : "Are you sure you want to delete this survey and all of its data?",
"delete_form_confirm_desc" : "This action cannot be undone. Deleting this survey will remove all of its data, including posts. Write the name of the survey: <br><br><strong>{{check_name}}</strong><br><br>in the box below to confirm deletion.",
"delete_form_error": "The text you entered does not match the survey-name, please try again",
"delete_form_button": "Delete this survey",
"destroy_form_success" : "Survey {{name}} deleted",
"delete_stage_confirm" : "Are you sure you want to delete this task?",
"delete_stage_confirm_desc" : "This action cannot be undone. Deleting this task will remove all of its fields, and any data in them.",
Expand Down
46 changes: 44 additions & 2 deletions app/common/notifications/notify.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ function Notify(_, $q, $rootScope, $translate, SliderService, ModalService, Demo
infoModal: infoModal,
confirmLeave: confirmLeave,
demo: demo,
notifyPermanent: notifyPermanent
notifyPermanent: notifyPermanent,
deleteWithInput: deleteWithInput
};

function notify(message, translateValues) {
Expand Down Expand Up @@ -217,7 +218,49 @@ function Notify(_, $q, $rootScope, $translate, SliderService, ModalService, Demo

return deferred.promise;
}
function deleteWithInput (type, checkName) {
var scope = getScope();
var deferred = $q.defer();
scope.isEqual = true;

const modalText = {
survey: {
title: 'notify.form.delete_form_confirm',
modalBody: 'notify.form.delete_form_confirm_desc',
errorLabel: 'notify.form.delete_form_error',
button: 'notify.form.delete_form_button'
}
};

var texts = modalText[type];

$translate(texts.modalBody, {check_name: checkName}).then(show, show);

function show(body) {
scope.confirm = function (name) {
scope.isEqual = name === checkName;
if (scope.isEqual) {
deferred.resolve();
ModalService.close();
}
};

scope.cancel = function () {
deferred.reject();
ModalService.close();
};

ModalService.openTemplate(
`<div class="form-field">
<p>${body}</p>
<p class="alert error" ng-show="!isEqual" translate>${texts.errorLabel}</p>
<input class="form-field" type="text" name="survey" ng-model="name">
<button class="button-destructive button-flat" ng-click="$parent.confirm(name)" translate>${texts.button}</button>
<button class="button-flat" ng-click="$parent.cancel()" translate="message.button.cancel">Cancel</button>
</div>`, texts.title, false, scope, false, false);
}
return deferred.promise;
}

function confirmDelete(confirmText, confirmWarningText, translateValues) {
var deferred = $q.defer();
Expand All @@ -227,7 +270,6 @@ function Notify(_, $q, $rootScope, $translate, SliderService, ModalService, Demo
translateValues = confirmWarningText;
confirmWarningText = false;
}

$translate(confirmText, translateValues).then(show, show);

function show(confirmText) {
Expand Down
2 changes: 1 addition & 1 deletion app/common/verifier/verifier.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import isUrl from 'is-url';
import fetch from 'node-fetch';
import fetch from 'cross-fetch';
import * as forms from '../../../mocked_backend/api/v3/forms.json';
import * as tags from '../../../mocked_backend/api/v3/tags.json';
import * as features from '../../../mocked_backend/api/v3/config/features.json';
Expand Down
8 changes: 1 addition & 7 deletions app/main/posts/modify/video.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@
<form>
<div class="form-field video_embed">
<label>{{label}}</label>
<p>
<span translate="post.video.enter_a">Enter a</span>

<img src="/img/youtube.png" class="wordmark-replace">
<span translate="post.video.or"> or </span>
<img src="/img/vimeo.png" class="wordmark-replace">
<span translate="post.video.video_url"> video URL</span>
<p translate="post.video.enter_a_url">Enter a video URL from Youtube or Vimeo.
</p>
<input type="text" ng-model="videoUrl" ng-blur="constructIframe(videoUrl)" placeholder="https://youtu.be/123456">

Expand Down
2 changes: 1 addition & 1 deletion app/main/posts/views/add-post-button.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="fab" ng-class="{'upgrade-button': upgradeButton}" data-message="add-post">
<button type="button" class="button-alpha button-fab" ng-click="handleClick()" ng-disabled="disabled" ng-class="{'disabled': $parent.$parent.bulkActionsSelected}">
<button type="button" class="button-alpha button-fab" ng-click="handleClick()" ng-disabled="disabled" ng-class="{'ng-hide': $parent.$parent.bulkActionsSelected || editMode()}">
<svg class="iconic">
<use xlink:href="/img/iconic-sprite.svg#plus"></use>
<foreignObject>
Expand Down
21 changes: 19 additions & 2 deletions app/main/posts/views/filters/filter-form.directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,24 @@ function FormSelectDirective(FormEndpoint) {
};

function FormSelectLink(scope, element, attrs, ngModel) {
scope.checkAll = true;
if (!ngModel) {
return;
}

scope.forms = [];
scope.selectedForms = [];

scope.toggleAll = toggleAll;
activate();

function toggleAll() {
if (!scope.checkAll) {
scope.checkAll = true;
Array.prototype.splice.apply(scope.selectedForms, [0, scope.selectedForms.length].concat(scope.forms.map(f => f.id).concat('none')));
} else {
scope.checkAll = false;
Array.prototype.splice.apply(scope.selectedForms, [0, scope.selectedForms.length]);
}
}
function activate() {
// Load forms
scope.forms = FormEndpoint.query();
Expand All @@ -35,6 +44,14 @@ function FormSelectDirective(FormEndpoint) {
}

function saveValueToView(selectedForms) {
// the length +1 check is because we add 'none' through ng-models for unknown survey type (messages with no post)
// this "fixes" the usecase where the user manually selected/unselected all checkboxes
const sameValues = selectedForms.length === scope.forms.length + 1;
if (!sameValues && scope.checkAll === true) {
scope.checkAll = false;
} else if (sameValues && scope.checkAll === false) {
scope.checkAll = true;
}
ngModel.$setViewValue(angular.copy(selectedForms));
}
}
Expand Down
6 changes: 3 additions & 3 deletions app/main/posts/views/filters/filter-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@

<div class="form-field checkbox" ng-show="forms.length > 5">
<label>
<input type="checkbox" name="selectedForms" ng-model="all"><em><span translate="category.select_all"></span></em>
<input type="checkbox" name="selectedForms" ng-checked="checkAll" ng-click="toggleAll()"><em><span translate="category.select_all"></span></em>
</label>
</div>
<div class="form-field checkbox" ng-repeat="(index, form) in forms">
<label>
<input checklist-value="form.id" checklist-model="selectedForms" type="checkbox" name="selectedForms" ng-checked="all"> <bdi>{{ ::form.name }}</bdi>
<input checklist-value="form.id" checklist-model="selectedForms" type="checkbox" name="selectedForms"> <bdi>{{ ::form.name }}</bdi>
</label>
</div>
<div class="form-field checkbox">
<label>
<input checklist-value="'none'" checklist-model="selectedForms" type="checkbox" name="selectedForms" ng-checked="all" > <span translate="nav.unknown">Unknown</span>
<input checklist-value="'none'" checklist-model="selectedForms" type="checkbox" name="selectedForms"> <span translate="nav.unknown">Unknown</span>
</label>
</div>
</fieldset>
2 changes: 1 addition & 1 deletion app/main/posts/views/post-view-data.directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ function PostViewDataController(
limit: $scope.itemsPerPage
});
if (useOffset === true) {
postQuery.offset = ($scope.currentPage - 1) * $scope.itemsPerPage;
postQuery.offset = $scope.posts.length;
}
PostEndpoint.query(postQuery).$promise.then(function (postsResponse) {
//Clear posts
Expand Down
8 changes: 6 additions & 2 deletions app/settings/data-import/data-import.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ <h2 class="stepper-heading">
<div class="form-field select" data-fieldgroup-target="status-model-columns" ng-show="isStatusOption('defined_column')">
<div class="custom-select">
<select ng-model="selectedStatus">
<option ng-repeat="column in csv.columns track by $index" value="{{$index}}" label="{{column}}" >
<option ng-repeat="column in csv.columns track by $index" value="{{$index}}">
{{column}}
</option>
</select>
</div>
<p><em translate="data_import.status_explanation">Ushahidi recognizes one of three post statuses: Published, Under review, and Archived. So be sure that each entry in the column you select has one of those three values.</em></p>
Expand Down Expand Up @@ -183,7 +185,9 @@ <h2 class="stepper-heading">
<option selected="selected" value="" translate="data_import.leave_empty">
Leave empty
</option>
<option ng-repeat="column in csv.columns track by $index" value="{{$index}}" label="{{column}}" >
<option ng-repeat="column in csv.columns track by $index" value="{{$index}}">
{{column}}
</option>
</select>
</div>
</td>
Expand Down
2 changes: 1 addition & 1 deletion app/settings/surveys/attribute-editor.directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function (
};

$scope.canMakePrivate = function () {
return $scope.editAttribute.type !== 'tags';
return $scope.editAttribute.type !== 'tags' && $scope.editAttribute.type !== 'title' && $scope.editAttribute.type !== 'description';
};

$scope.canDisableCaption = function () {
Expand Down
22 changes: 11 additions & 11 deletions app/settings/surveys/attribute-editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,17 @@
</div>
<!-- end: media upload toggle to make caption an optional field-->
<div class="form-field switch" ng-show="canMakePrivate()">
<label translate="survey.make_response_private">Make responses private</label>
<p data-fieldgroup-target="field-private-message-3" class="init active" translate="survey.response_private_desc" ng-show="editAttribute.response_private">
<svg class="iconic">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/img/iconic-sprite.svg#lock-locked"></use>
</svg>
Only people with permission to edit responses will be able to see responses to this field.
</p>
<div class="toggle-switch">
<input class="tgl" id="switchprivateresponse" type="checkbox" ng-model="editAttribute.response_private">
<label class="tgl-btn" for="switchprivateresponse"></label>
</div>
<label translate="survey.make_response_private">Make responses private</label>
<p data-fieldgroup-target="field-private-message-3" class="init active" translate="survey.response_private_desc" ng-show="editAttribute.response_private">
<svg class="iconic">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/img/iconic-sprite.svg#lock-locked"></use>
</svg>
Only people with permission to edit responses will be able to see responses to this field.
</p>
<div class="toggle-switch">
<input class="tgl" id="switchprivateresponse" type="checkbox" ng-model="editAttribute.response_private">
<label class="tgl-btn" for="switchprivateresponse"></label>
</div>
</div>
<div class="form-field switch" ng-if="canDisplay()">
<label translate="app.default_value">Default value (optional):</label>
Expand Down
2 changes: 1 addition & 1 deletion app/settings/surveys/surveys.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function (
};

$scope.deleteSurvey = function (survey) {
Notify.confirmDelete('notify.form.delete_form_confirm', 'notify.form.delete_form_confirm_desc').then(function () {
Notify.deleteWithInput('survey', survey.name).then(function () {
// If we haven't saved the survey
// just go back to the surveys views
if (!survey.id) {
Expand Down
1 change: 1 addition & 0 deletions app/settings/users/users.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ function (
$q.all(calls).then(function () {
Notify.notify('notify.user.bulk_destroy_success');
$scope.getUsersForPagination();
$scope.selectedUsers.length = 0;
}, handleResponseErrors)
.finally($scope.filterRole);
}, function () {});
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"gulp-rename": "^1.4.0",
"gulp-tar": "^3.1.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"html-webpack-plugin": "^4.0.0",
"imports-loader": "^0.8.0",
"is-url": "^1.2.4",
"jasmine-core": "^3.5.0",
Expand Down Expand Up @@ -85,7 +85,7 @@
"sass-loader": "^8.0.0",
"style-loader": "^1.1.2",
"supports-color": "^3.1.2",
"svg-url-loader": "^3.0.3",
"svg-url-loader": "^5.0.0",
"transifex": "^1.6.6",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^4.0.0",
Expand All @@ -111,8 +111,9 @@
"angular-translate-loader-static-files": "^2.11.0",
"angular-ui-bootstrap": "^2.5.0",
"checklist-model": "~0.11.0",
"cross-fetch": "^3.0.4",
"d3": "^3.5.17",
"leaflet.locatecontrol": "^0.70.0",
"leaflet.locatecontrol": "^0.71.1",
"leaflet": "^1.6.0",
"leaflet-easybutton": "^2.4.0",
"leaflet.markercluster": "1.0.5",
Expand Down
15 changes: 15 additions & 0 deletions test/unit/common/notifications/notify.service.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,21 @@ describe('Notify', function () {
});
});

describe('deleteWithInput', function () {
beforeEach(function () {
spyOn(mockModalService, 'openTemplate').and.callThrough();
spyOn(mockSliderService, 'openTemplate').and.callThrough();
});

it('Calls ModalService.openTemplate with error message', function () {
mockModalService.state = false;
Notify.deleteWithInput('survey', 'this is the name of the survey');
$rootScope.$digest();
expect(mockModalService.openTemplate).toHaveBeenCalled();
});
});


describe('limit', function () {
beforeEach(function () {
spyOn(mockSliderService, 'openTemplate').and.callThrough();
Expand Down
Loading

0 comments on commit d9dcc29

Please sign in to comment.