Skip to content

Commit

Permalink
Merge pull request #509 from Esri/develop
Browse files Browse the repository at this point in the history
Sync Develop with Master after AGOL 9.2 release
  • Loading branch information
azizaparveen authored Jul 12, 2021
2 parents 7c1969d + 2f5c8fe commit 95a2491
Show file tree
Hide file tree
Showing 16 changed files with 539 additions and 103 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@

Crowdsource Reporter is a configurable group application template that allows users to submit problems or observations.

The Crowdsource Reporter application presents one, or more, maps that can be used to report a problem or observation. Users can anonymously submit new reports, review existing reports, and comment and vote on reports or observations submitted by other users. They can also authenticate with their social media or ArcGIS Online credentials and track the status of problems or observations they have reported.
The Crowdsource Reporter application presents one, or more, maps that can be used to report a problem or observation. Users can anonymously submit new reports, review existing reports, and comment and vote on reports or observations submitted by other users. They can also authenticate with their ArcGIS Online credentials and track the status of problems or observations they have reported.

[![Image of the Constituent Engagement app][Thumbnail]][Preview]

## Features

* Presents editable layers from one or more maps that have been shared with the ArcGIS Online/Portal group configured in the application.
* Users can submit new reports, review existing reports, and comment and vote on reports or observations submitted by other users.
* Users can access the content anonymously, or authenticate using their Twitter, or ArcGIS credentials. Authenticated users gain access to additional functionality, such as My Issues - a list of all reports they have submitted.
* Users can access the content anonymously, or authenticate using their ArcGIS credentials. Authenticated users gain access to additional functionality, such as My Issues - a list of all reports they have submitted.
* The application has been optimized for smartphones but is responsively designed and can also be used in browsers on smartphones, tablets, and desktops using [all browsers supported by ArcGIS Online][supported browsers].

## Requirements
Expand Down
3 changes: 2 additions & 1 deletion config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,6 @@ define({
"commentEndTime": "", // Comment end time
"commentsSuccessMessage": "Comments Submitted Successfully.",
"commentSortingOrder": "DESC", // To sort comment in ascending(ASC) or descending(DESC) order.
"commentSortingField": "comments" // Field on which ascending or descending sorting needs to be applied
"commentSortingField": "comments", // Field on which ascending or descending sorting needs to be applied
"maxImageSize": "actualSize"
});
Binary file modified images/signinbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/signinbg_new.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
<!-- Bootstrap TouchSpinner CSS -->
<link rel="stylesheet" type="text/css" href="js/vendor/touch-spinner/jquery.bootstrap-touchspin.min.css" />
<!--Dojo and Esri CSS-->
<link rel="stylesheet" href="https://js.arcgis.com/3.36/dijit/themes/claro/claro.css" />
<link rel="stylesheet" href="https://js.arcgis.com/3.36/esri/css/esri.css" />
<link rel="stylesheet" href="https://js.arcgis.com/3.37/dijit/themes/claro/claro.css" />
<link rel="stylesheet" href="https://js.arcgis.com/3.37/esri/css/esri.css" />
<!-- Load any application specific styles -->
<link rel="stylesheet" href="css/main.css" type="text/css" />
<link rel="stylesheet" href="css/common.css" type="text/css" />
Expand Down Expand Up @@ -113,7 +113,7 @@
<script type="text/javascript" src="js/vendor/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js"></script>
<script type="text/javascript" src="js/vendor/touch-spinner/jquery.bootstrap-touchspin.min.js"></script>
<script type="text/javascript" src="js/vendor/exif/exif.js"></script>
<script type="text/javascript" src="https://js.arcgis.com/3.36"></script>
<script type="text/javascript" src="https://js.arcgis.com/3.37"></script>
<script type="text/javascript">
require([
"application/bootstrapper"
Expand Down
4 changes: 4 additions & 0 deletions js/bootstrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ define([
// Remove access to Facebook and Google Plus due to unsupportable changes in its API
config.enableFacebook = false;
config.enableGoogleplus = false;

// Remove access to Twitter due to retirement of Twitter proxy at 9.2
config.enableTwitter = false;

// The config object contains the following properties: helper services, (optionally)
// i18n, appid, webmap and any custom values defined by the application.
// Load Application if valid group-id is configured, if not show error message.
Expand Down
3 changes: 2 additions & 1 deletion js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ define([

//Populate location field after the address is validated
aspect.after(this.mapSearch, "_validateAddress", lang.hitch(this, function () {
if (this.geoformInstance && this.selectedLayer.geometryType === "esriGeometryPoint" && !domClass.contains(dom.byId('geoformContainer'), "esriCTHidden")) {
if (this.geoformInstance && this.selectedLayer.geometryType === "esriGeometryPoint" && !domClass.contains(dom.byId('geoformContainer'), "esriCTHidden")
&& this.config.locationField) {
this.geoformInstance._populateLocationField(this.mapSearch.locatorSearch.txtSearch.value);
}
}));
Expand Down
28 changes: 28 additions & 0 deletions js/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -663,5 +663,33 @@ define([
.replace(/\<edge\-link\>(.+)\<\/edge\-link\>/, '<a class="browser-message-link" href="https://www.microsoft.com/edge/">$1</a>')
.replace(/\<feedback\-link\>(.+)\<\/feedback\-link\>/, '<a class="browser-message-link" href="https://community.esri.com/community/gis/web-gis/arcgisonline">$1</a>');
},

/**
* Returns the image data to blob
* @memberOf utils/utils
*/
dataURLToBlob: function (dataURL) {
var BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = parts[1];

return new Blob([raw], { type: contentType });
}

var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;

var uInt8Array = new Uint8Array(rawLength);

for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}

return new Blob([uInt8Array], { type: "image/jpg" });
}
});
});
21 changes: 17 additions & 4 deletions js/widgets/app-header/app-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ define([
"dojo/text!./templates/app-header.html",
"widgets/mobile-menu/mobile-menu",
"widgets/help/help",
"esri/IdentityManager",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin"
], function (declare, domConstruct, lang, dom, domAttr, domClass, domStyle, esriRequest, on, query, template, MobileMenu, Help, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin) {
], function (declare, domConstruct, lang, dom, domAttr, domClass, domStyle, esriRequest, on, query, template, MobileMenu, Help, IdentityManager, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin) {
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: template,
mobileMenu: null,
Expand Down Expand Up @@ -373,10 +374,22 @@ define([
}
// user is logged in via AGOL portal login
if (this.config.portalObject) {
var portalURL = this.config.portalObject.url;
//If the portal url do not have forward slash
//at the end, add to make it a valid url once
//it is merged with oauth sign out url
if (portalURL[portalURL.length - 1] !== "/") {
portalURL = portalURL + "/";
}
if (this.config.portalObject.getPortalUser()) {
this.config.portalObject.signOut().then(lang.hitch(this, function () {
location.reload();
}));
esriRequest({
url: portalURL + "sharing/oauth2/signout",
handleAs: "xml",
load: lang.hitch(this, function () {
IdentityManager.destroyCredentials();
location.reload();
})
});
} else {
location.reload();
}
Expand Down
2 changes: 1 addition & 1 deletion js/widgets/app-header/templates/app-header.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
title="${i18n.myReportTooltip}" aria-label="${i18n.myReportTooltip}">
${i18n.myReport}
</div>
<div role="menuitem" tabindex="0" data-dojo-attach-point="signOutButton" onclick="location.reload();" class="esriCTHidden esriCTItems esriCTPointerCursor"
<div role="menuitem" tabindex="0" data-dojo-attach-point="signOutButton" onclick="" class="esriCTHidden esriCTItems esriCTPointerCursor"
title="${i18n.signOutTooltip}" aria-label="${i18n.signOutTooltip}">
${i18n.signOut}
</div>
Expand Down
104 changes: 103 additions & 1 deletion js/widgets/comment-form/comment-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ define([
_fileAttachedCounter: 0, // to store number of files that is been attached
_fileFailedCounter: 0, // to store number of files that is been failed to attached
_deletedAttachmentsArr: [], // to store deleted attachments
_resizedFiles: [],

/**
* This function is called when widget is constructed.
Expand All @@ -90,6 +91,7 @@ define([
postCreate: function () {
var submitCommentText;
this.inherited(arguments);
this._resizedFiles = [];
this._initializeCommentForm();
if (this.addComments) {
submitCommentText = this.config.i18n.comment.commentsFormSubmitButton;
Expand Down Expand Up @@ -140,6 +142,7 @@ define([
if (!this.appUtils.validateEvent(evt)) {
return;
}
this._resizedFiles = [];
this.appUtils.showLoadingIndicator();
this.onCancelButtonClick(evt);
this.appUtils.hideLoadingIndicator();
Expand Down Expand Up @@ -349,6 +352,13 @@ define([
$('#' + target.parentNode.id + "_Close").bind('closed.bs.alert', lang.hitch(this, function (evt) {
domClass.replace(dom.byId(evt.target.id.split("_")[0]), "esriCTHideFileInputUI", "esriCTFileToSubmit");
this._updateAttachmentCount();
//Check if the resized image is being deleted by the user
//if yes then delete the same image from the array
var indexToMatch = domAttr.get(dom.byId(target.parentNode.id), "indexToMatch");
if (indexToMatch) {
var indexToDelete = parseInt(indexToMatch, 10);
this._resizedFiles.splice(indexToDelete, 1, null);
}
}));
//once filename is shown, update file attachments count
this._updateAttachmentCount();
Expand All @@ -363,16 +373,75 @@ define([
"name": "attachment",
"style": { "height": dojo.coords(this._fileInputIcon).h + "px", "width": dojo.coords(this._fileInputIcon).w + "px" }
}, newFormControl);
var _this = this;
//place the newly created file-input control after file selection icon
domConstruct.place(newFormControl, this._fileInputIcon, "after");
//handle change event for file control if file size is
fileChange = on(fileInput, "change", lang.hitch(this, function (evt) {
fileChange.remove();
this._onFileSelected(evt);
}));
//If max size parameter exist and it is configured
//then validate and reduce the image size
if (this.config.hasOwnProperty("maxImageSize") &&
this.config.maxImageSize !== "actualSize") {
this._validateAndReduceImageDimension(evt, target, _this, fileName);
}
}
},

/**
* validate and reduce the image size
* @param{object} evt - Event object which will be generated on file input change event
* @param{object} evt - Target node
* @param{object} _this - Scope object
* @param{string} fileName - File name of attachment
* @memberOf widgets/geo-form/geo-form
*/
_validateAndReduceImageDimension: function (evt, target, _this, fileName) {
var reader;
reader = new FileReader();
reader.onload = function (readerEvent) {
var image, formNode, formData, canvas;
image = new Image();
image.onload = function () {
// Resize the image
canvas = domConstruct.create('canvas'),
max_size = _this.config.maxImageSize,
width = image.width,
height = image.height;
if (max_size < height || max_size < width) {
if (width > height) {
if (width > max_size) {
height *= max_size / width;
width = max_size;
}
} else {
if (height > max_size) {
width *= max_size / height;
height = max_size;
}
}
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
imageDataUrl = canvas.toDataURL('image/jpeg');
imageResized = _this.appUtils.dataURLToBlob(imageDataUrl);

formNode = domConstruct.create("form", { "enctype": "multipart/form-data" });
formData = new FormData(formNode);
formData.append("attachment", imageResized, fileName);
_this._resizedFiles.push(formData);
domAttr.set(dom.byId(target.parentNode.id), "indexToMatch", _this._resizedFiles.length - 1);
domClass.remove(target.parentNode, "esriCTFileToSubmit");
}
};
image.src = readerEvent.target.result;
evt.target.files[0] = readerEvent.target.result;
};
reader.readAsDataURL(evt.currentTarget.files[0]);
},

/**
* Clear previous attachment count and hide the message
* @memberOf widgets/comment-form/comment-form
Expand Down Expand Up @@ -591,13 +660,29 @@ define([
if (results[0].success) {
var fileList, i, userFormNode;
userFormNode = dom.byId("addCommentAttachmentsWrapperContainer");
//Filter file array
if (this._resizedFiles && this._resizedFiles.length > 0) {
this._resizedFiles = this._resizedFiles.filter(function (fileIndex) {
return fileIndex !== null;
});
}
// if layer has attachments then add those attachments
if (this.commentTable.hasAttachments && query(".esriCTFileToSubmit", userFormNode).length > 0) {
if (this.commentTable.hasAttachments && query(".esriCTFileToSubmit", userFormNode).length > 0 ||
this._resizedFiles.length > 0) {
// get all the attachments
fileList = query(".esriCTFileToSubmit", userFormNode);
// reset fileAttached and failed counter
this._fileAttachedCounter = 0;
this._fileFailedCounter = 0;
//If new attachments which are reduced in the quality are added
//add them to the fileList array so that they are processed
if (this._resizedFiles.length > 0) {
array.forEach(this._resizedFiles, lang.hitch(this, function (formNode) {
if (formNode) {
fileList.push(formNode);
}
}));
}
// set total file attached counter
this._totalFileAttachedCounter = fileList.length;
for (i = 0; i < fileList.length; i++) {
Expand Down Expand Up @@ -641,6 +726,22 @@ define([
// if layer has attachments then add those attachments
// get all the attachments
fileList = query(".esriCTFileToSubmit", userFormNode);
//Filter file array
if (this._resizedFiles && this._resizedFiles.length > 0) {
this._resizedFiles = this._resizedFiles.filter(function (fileIndex) {
return fileIndex !== null;
});
}
//check new images are being added and they are resized as per the
//configured dimensions
//Add them to the file list, so they will be considered while adding attachments
if (this._resizedFiles.length > 0) {
array.forEach(this._resizedFiles, lang.hitch(this, function (formNode) {
if (formNode) {
fileList.push(formNode);
}
}));
}
if (this.commentTable.hasAttachments && (fileList.length > 0 || this._deletedAttachmentsArr.length > 0)) {
if (fileList.length > 0) {
// reset fileAttached and failed counter
Expand Down Expand Up @@ -753,6 +854,7 @@ define([
} else {
this.onCommentFormSubmitted(this.item, true);
}
this._resizedFiles = [];
},

/**
Expand Down
Loading

0 comments on commit 95a2491

Please sign in to comment.