aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.md18
-rw-r--r--README.md3
-rw-r--r--config.xml-example117
-rwxr-xr-xhooks/after_prepare/allow-sd-installation.js8
-rwxr-xr-xhooks/after_prepare/remove-permissions.js12
-rw-r--r--locale/FixMyStreetMobileApp.po24
-rw-r--r--locale/en_GB.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po24
-rw-r--r--locale/es_DO.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po25
-rw-r--r--package-lock.json-example600
-rw-r--r--package.json-example49
-rwxr-xr-xres/ios/icons/Icon-40.pngbin1480 -> 1641 bytes
-rwxr-xr-xres/ios/icons/Icon-40@2x.pngbin3081 -> 3302 bytes
-rwxr-xr-xres/ios/icons/Icon-50.pngbin1844 -> 1884 bytes
-rwxr-xr-xres/ios/icons/Icon-50@2x.pngbin3909 -> 4217 bytes
-rwxr-xr-xres/ios/icons/Icon-60.pngbin2238 -> 2472 bytes
-rwxr-xr-xres/ios/icons/Icon-60@2x.pngbin7144 -> 7042 bytes
-rwxr-xr-xres/ios/icons/Icon-60@3x.pngbin16181 -> 16131 bytes
-rwxr-xr-xres/ios/icons/Icon-72.pngbin2838 -> 3018 bytes
-rwxr-xr-xres/ios/icons/Icon-72@2x.pngbin5944 -> 6219 bytes
-rwxr-xr-xres/ios/icons/Icon-76.pngbin2917 -> 3158 bytes
-rwxr-xr-xres/ios/icons/Icon-76@2x.pngbin10844 -> 10658 bytes
-rw-r--r--res/ios/icons/Icon-83.5@2x.pngbin0 -> 9213 bytes
-rwxr-xr-xres/ios/icons/Icon-Small.pngbin1169 -> 1124 bytes
-rwxr-xr-xres/ios/icons/Icon-Small@2x.pngbin3006 -> 2319 bytes
-rw-r--r--res/ios/icons/Icon-Small@3x.pngbin0 -> 3940 bytes
-rwxr-xr-xres/ios/icons/Icon.pngbin2095 -> 2365 bytes
-rwxr-xr-xres/ios/icons/Icon@2x.pngbin4428 -> 4783 bytes
-rwxr-xr-xres/ios/icons/iTunesArtwork.pngbin23611 -> 23377 bytes
-rwxr-xr-xres/ios/icons/iTunesArtwork@2x.pngbin50691 -> 48938 bytes
-rw-r--r--res/ios/splash/Default-1125@3x~iphonex-portrait_1125x2436.pngbin0 -> 48075 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.pngbin60048 -> 60048 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default-568h@2x~iphone_640x1136.pngbin24453 -> 24453 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.pngbin29917 -> 29917 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default-Portrait@2x~ipad_1536x2008.pngbin55523 -> 55523 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default-Portrait@2x~ipad_1536x2048.pngbin57013 -> 57013 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default-Portrait~ipad_768x1024.pngbin21988 -> 21988 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default@2x~iphone_640x960.pngbin19954 -> 19954 bytes
-rw-r--r--[-rwxr-xr-x]res/ios/splash/Default~iphone.pngbin8610 -> 8610 bytes
-rwxr-xr-xscripts/prepare_index_html.js2
-rw-r--r--templates/around.html1
-rw-r--r--templates/details_extra.html6
-rw-r--r--templates/existing.html4
-rw-r--r--templates/login.html16
-rw-r--r--templates/offline.html35
-rw-r--r--templates/photo.html64
-rw-r--r--templates/reports.html2
-rw-r--r--templates/strings.js5
-rw-r--r--templates/submit_confirm.html2
-rw-r--r--templates/submit_set_password.html2
-rw-r--r--www/cobrands/cuidomiciudad/css/style.css6
-rw-r--r--www/cobrands/cuidomiciudad/css/style.scss6
-rw-r--r--www/cobrands/makemyisland/css/style.css6
-rw-r--r--www/cobrands/makemyisland/css/style.scss6
-rw-r--r--www/css/fms.css106
-rw-r--r--www/images/hide-pins-link.pngbin0 -> 734 bytes
-rw-r--r--www/images/hide-pins-link.svg1
-rw-r--r--www/index.html2
-rw-r--r--www/js/app.js84
-rw-r--r--www/js/config.js-example45
-rw-r--r--www/js/files.js14
-rw-r--r--www/js/map-OpenLayers.js10
-rw-r--r--www/js/models/draft.js26
-rw-r--r--www/js/models/report.js122
-rw-r--r--www/js/router.js2
-rw-r--r--www/js/strings.en.js5
-rw-r--r--www/js/strings.es.js5
-rw-r--r--www/js/views/around.js31
-rw-r--r--www/js/views/details.js35
-rw-r--r--www/js/views/details_extra.js8
-rw-r--r--www/js/views/fms.js30
-rw-r--r--www/js/views/home.js5
-rw-r--r--www/js/views/login.js28
-rw-r--r--www/js/views/offline.js93
-rw-r--r--www/js/views/photo.js67
-rw-r--r--www/js/views/submit.js110
-rw-r--r--www/templates/en/around.html1
-rw-r--r--www/templates/en/details_extra.html6
-rw-r--r--www/templates/en/existing.html4
-rw-r--r--www/templates/en/help.html2
-rw-r--r--www/templates/en/login.html16
-rw-r--r--www/templates/en/offline.html35
-rw-r--r--www/templates/en/photo.html64
-rw-r--r--www/templates/en/reports.html2
-rw-r--r--www/templates/en/submit_confirm.html2
-rw-r--r--www/templates/en/submit_set_password.html2
-rw-r--r--www/templates/es/around.html1
-rw-r--r--www/templates/es/details_extra.html6
-rw-r--r--www/templates/es/existing.html4
-rw-r--r--www/templates/es/login.html16
-rw-r--r--www/templates/es/offline.html35
-rw-r--r--www/templates/es/photo.html64
-rw-r--r--www/templates/es/reports.html2
-rw-r--r--www/templates/es/submit_confirm.html2
-rw-r--r--www/templates/es/submit_set_password.html2
95 files changed, 1624 insertions, 515 deletions
diff --git a/.gitignore b/.gitignore
index 4e4534c..37db34d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ locale/lang_list
/config.xml
/node_modules
/package.json
+/package-lock.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..735c921
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,18 @@
+## Releases
+
+* v2.1 (3rd May 2018)
+ - New features
+ - Multiple photo support. #107
+ - iPhone X support. #259
+ - Button to hide pins on map. #175
+ - Bugfixes
+ - Skip empty report details screen.
+ - Correctly set user title. #156
+ - Show more helpful error if server rejects password. #156
+ - Allow mailto: links to be followed. #263
+ - Stop keyboard obscuring report details text field. #222
+ - Development improvements
+ - CONFIG.SKIP_CONFIRM_REPORT flag to skip confirmation screen.
+ - Ensure compatibility with latest Cordova versions.
+ - CONFIG.PASSWORD_MIN_LENGTH key to validate user password.
+ - CONFIG.PASSWORD_CHECK_COMMON flag to test password against server.
diff --git a/README.md b/README.md
index 4d33b6f..1b2e584 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,9 @@ You should also create a `config.xml` file based on `config.xml-example`.
The only change you should need to make is to add the hostname of your FMS installation
in an `<access origin=""/>` tag.
+You'll also need `package.json` and `package-lock.json` which can be similarly
+created from the `-example` files.
+
Setup
-----
This project uses Apache Cordova to produce Android and iOS apps. There is
diff --git a/config.xml-example b/config.xml-example
index db64ef0..22c5332 100644
--- a/config.xml-example
+++ b/config.xml-example
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
-<widget android-versionCode="42" id="org.mysociety.FixMyStreet" version="2.0.7" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+<widget id="org.mysociety.FixMyStreet" version="2.1" ios-CFBundleVersion="2.1.20180503.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>FixMyStreet</name>
<description>
Report problems on FixMyStreet
@@ -8,7 +8,7 @@
mySociety
</author>
<content src="index.html" />
-
+ <allow-intent href="mailto:*" />
<access origin="http://127.0.0.1*" />
<access origin="*://*.openstreetmap.org" />
<access origin="*://*.opencyclemap.org" />
@@ -35,7 +35,7 @@
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<!-- If you change the background colour of the app, change this value to match. -->
<preference name="StatusBarBackgroundColor" value="#F6BE41" />
- <preference name="deployment-target" value="6.0" />
+ <preference name="deployment-target" value="9.0" />
<platform name="android">
<icon density="ldpi" src="res/android/drawable-ldpi/icon.png" />
@@ -51,60 +51,65 @@
<splash density="xxhdpi" src="res/android/drawable-xxhdpi/screen.9.png" />
<splash density="xxxhdpi" src="res/android/drawable-xxxhdpi/screen.9.png" />
</platform>
-
<platform name="ios">
- <!-- iOS 8.0+ -->
- <!-- iPhone 6 Plus -->
- <icon src="res/ios/icons/Icon-60@3x.png" width="180" height="180" />
- <!-- iOS 7.0+ -->
- <!-- iPhone / iPod Touch -->
- <icon src="res/ios/icons/Icon-60.png" width="60" height="60" />
- <icon src="res/ios/icons/Icon-60@2x.png" width="120" height="120" />
- <!-- iPad -->
- <icon src="res/ios/icons/Icon-76.png" width="76" height="76" />
- <icon src="res/ios/icons/Icon-76@2x.png" width="152" height="152" />
- <!-- iOS 6.1 -->
- <!-- Spotlight Icon -->
- <icon src="res/ios/icons/Icon-40.png" width="40" height="40" />
- <icon src="res/ios/icons/Icon-40@2x.png" width="80" height="80" />
- <!-- iPhone / iPod Touch -->
- <icon src="res/ios/icons/Icon.png" width="57" height="57" />
- <icon src="res/ios/icons/Icon@2x.png" width="114" height="114" />
- <!-- iPad -->
- <icon src="res/ios/icons/Icon-72.png" width="72" height="72" />
- <icon src="res/ios/icons/Icon-72@2x.png" width="144" height="144" />
- <!-- iPhone Spotlight and Settings Icon -->
- <icon src="res/ios/icons/Icon-Small.png" width="29" height="29" />
- <icon src="res/ios/icons/Icon-Small@2x.png" width="58" height="58" />
- <!-- iPad Spotlight and Settings Icon -->
- <icon src="res/ios/icons/Icon-50.png" width="50" height="50" />
- <icon src="res/ios/icons/Icon-50@2x.png" width="100" height="100" />
- <splash src="res/ios/splash/Default~iphone.png" width="320" height="480"/>
- <splash src="res/ios/splash/Default@2x~iphone_640x960.png" width="640" height="960"/>
- <splash src="res/ios/splash/Default-Portrait~ipad_768x1024.png" width="768" height="1024"/>
- <splash src="res/ios/splash/Default-Portrait@2x~ipad_1536x2048.png" width="1536" height="2048"/>
- <splash src="res/ios/splash/Default-Portrait@2x~ipad_1536x2008.png" width="1536" height="2008"/>
- <splash src="res/ios/splash/Default-568h@2x~iphone_640x1136.png" width="640" height="1136"/>
- <splash src="res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.png" width="750" height="1334"/>
- <splash src="res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png" width="1242" height="2208"/>
+ <icon height="180" src="res/ios/icons/Icon-60@3x.png" width="180" />
+ <icon height="60" src="res/ios/icons/Icon-60.png" width="60" />
+ <icon height="120" src="res/ios/icons/Icon-60@2x.png" width="120" />
+ <icon height="76" src="res/ios/icons/Icon-76.png" width="76" />
+ <icon height="152" src="res/ios/icons/Icon-76@2x.png" width="152" />
+ <icon height="40" src="res/ios/icons/Icon-40.png" width="40" />
+ <icon height="80" src="res/ios/icons/Icon-40@2x.png" width="80" />
+ <icon height="57" src="res/ios/icons/Icon.png" width="57" />
+ <icon height="114" src="res/ios/icons/Icon@2x.png" width="114" />
+ <icon height="72" src="res/ios/icons/Icon-72.png" width="72" />
+ <icon height="144" src="res/ios/icons/Icon-72@2x.png" width="144" />
+ <icon height="29" src="res/ios/icons/Icon-Small.png" width="29" />
+ <icon height="58" src="res/ios/icons/Icon-Small@2x.png" width="58" />
+ <icon height="87" src="res/ios/icons/Icon-Small@3x.png" width="87" />
+ <icon height="50" src="res/ios/icons/Icon-50.png" width="50" />
+ <icon height="100" src="res/ios/icons/Icon-50@2x.png" width="100" />
+ <icon height="167" src="res/ios/icons/Icon-83.5@2x.png" width="167" />
+ <icon height="1024" src="res/ios/icons/iTunesArtwork@2x.png" width="1024" />
+ <splash height="480" src="res/ios/splash/Default~iphone.png" width="320" />
+ <splash height="960" src="res/ios/splash/Default@2x~iphone_640x960.png" width="640" />
+ <splash height="1024" src="res/ios/splash/Default-Portrait~ipad_768x1024.png" width="768" />
+ <splash height="2048" src="res/ios/splash/Default-Portrait@2x~ipad_1536x2048.png" width="1536" />
+ <splash height="2008" src="res/ios/splash/Default-Portrait@2x~ipad_1536x2008.png" width="1536" />
+ <splash height="1136" src="res/ios/splash/Default-568h@2x~iphone_640x1136.png" width="640" />
+ <splash height="1334" src="res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.png" width="750" />
+ <splash height="2208" src="res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png" width="1242" />
+ <splash height="2208" src="res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png" width="1242" />
+ <splash src="res/ios/splash/Default-1125@3x~iphonex-portrait_1125x2436.png" width="1125" height="2436"/>
</platform>
-
- <engine name="ios" spec="~4.1.1" />
- <plugin name="cordova-plugin-camera" spec="~2.1.1" />
- <plugin name="cordova-plugin-device" spec="~1.1.1" />
- <plugin name="cordova-plugin-dialogs" spec="~1.2.0" />
- <plugin name="cordova-plugin-file" spec="~4.1.1" />
- <plugin name="cordova-plugin-file-transfer" spec="~1.5.0" />
- <plugin name="cordova-plugin-geolocation" spec="~2.1.0" />
- <plugin name="cordova-plugin-inappbrowser" spec="~1.3.0" />
- <plugin name="cordova-plugin-media" spec="~2.2.0" />
- <plugin name="cordova-plugin-media-capture" spec="~1.2.0" />
- <plugin name="cordova-plugin-network-information" spec="~1.2.0" />
- <plugin name="cordova-plugin-splashscreen" spec="~3.2.1" />
- <plugin name="cordova-plugin-statusbar" spec="~2.1.2" />
- <plugin name="cordova-plugin-whitelist" spec="~1.2.1" />
- <plugin name="ionic-plugin-keyboard" spec="~2.0.1" />
- <engine name="android" spec="~5.1.1" />
<hook src="scripts/prepare_index_html.js" type="after_prepare" />
+ <plugin name="cordova-plugin-camera" spec="^4.0.3" />
+ <plugin name="cordova-plugin-compat" spec="^1.2.0" />
+ <plugin name="cordova-plugin-device" spec="^2.0.2" />
+ <plugin name="cordova-plugin-dialogs" spec="^2.0.1" />
+ <plugin name="cordova-plugin-file" spec="^6.0.1" />
+ <plugin name="cordova-plugin-file-transfer" spec="^1.7.1" />
+ <plugin name="cordova-plugin-geolocation" spec="^4.0.1" />
+ <plugin name="cordova-plugin-inappbrowser" spec="^3.0.0" />
+ <plugin name="cordova-plugin-media" spec="^5.0.2">
+ <variable name="KEEP_AVAUDIOSESSION_ALWAYS_ACTIVE" value="NO" />
+ </plugin>
+ <plugin name="cordova-plugin-media-capture" spec="^3.0.2" />
+ <plugin name="cordova-plugin-network-information" spec="^2.0.1" />
+ <plugin name="cordova-plugin-splashscreen" spec="^5.0.2" />
+ <plugin name="cordova-plugin-statusbar" spec="^2.4.2" />
+ <plugin name="cordova-plugin-whitelist" spec="^1.3.3" />
+ <plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
+ <engine name="ios" spec="^4.5.4" />
+ <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
+ <string>To take photos of problems.</string>
+ </edit-config>
+ <edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
+ <string>To attach photos of problems to your report.</string>
+ </edit-config>
+ <edit-config file="*-Info.plist" mode="merge" target="NSLocationWhenInUseUsageDescription">
+ <string>To create accurately positioned reports.</string>
+ </edit-config>
+ <edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryAddUsageDescription">
+ <string>To save photos of problems.</string>
+ </edit-config>
</widget>
-
diff --git a/hooks/after_prepare/allow-sd-installation.js b/hooks/after_prepare/allow-sd-installation.js
index 4a5af5e..d6d24d9 100755
--- a/hooks/after_prepare/allow-sd-installation.js
+++ b/hooks/after_prepare/allow-sd-installation.js
@@ -2,11 +2,13 @@
var fs = require('fs');
-if (fs.existsSync('platforms/android')) {
- var filename = 'platforms/android/AndroidManifest.xml',
- manifest = fs.readFileSync(filename).toString();
+var filename = 'platforms/android/app/src/main/AndroidManifest.xml';
+if (fs.existsSync(filename)) {
+ var manifest = fs.readFileSync(filename).toString();
if (manifest.indexOf('android:installLocation="auto"') == -1) {
manifest = manifest.replace(/<manifest/, '<manifest android:installLocation="auto"');
fs.writeFileSync(filename, manifest);
}
+} else {
+ console.log("file didn't exist: ", filename);
}
diff --git a/hooks/after_prepare/remove-permissions.js b/hooks/after_prepare/remove-permissions.js
index 5628647..9ae133b 100755
--- a/hooks/after_prepare/remove-permissions.js
+++ b/hooks/after_prepare/remove-permissions.js
@@ -1,15 +1,15 @@
#!/usr/bin/env node
var fs = require('fs');
-if(fs.existsSync('platforms/android')) {
+var filename = 'platforms/android/app/src/main/AndroidManifest.xml';
+if (fs.existsSync(filename)) {
var PERMISSIONS_TO_REMOVE = [
'READ_PHONE_STATE',
'RECORD_AUDIO',
'MODIFY_AUDIO_SETTINGS',
'RECORD_VIDEO'
];
- var MANIFEST = 'platforms/android/AndroidManifest.xml';
- var manifestLines = fs.readFileSync(MANIFEST).toString().split('\n');
+ var manifestLines = fs.readFileSync(filename).toString().split('\n');
var newManifestLines = [];
var PERMISSIONS_REGEX = PERMISSIONS_TO_REMOVE.join('|');
@@ -19,5 +19,7 @@ if(fs.existsSync('platforms/android')) {
}
});
- fs.writeFileSync(MANIFEST, newManifestLines.join('\n'));
-} \ No newline at end of file
+ fs.writeFileSync(filename, newManifestLines.join('\n'));
+} else {
+ console.log("file didn't exist: ", filename);
+}
diff --git a/locale/FixMyStreetMobileApp.po b/locale/FixMyStreetMobileApp.po
index 2f162fc..7dd7b39 100644
--- a/locale/FixMyStreetMobileApp.po
+++ b/locale/FixMyStreetMobileApp.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: struan@mysociety.org\n"
-"POT-Creation-Date: 2017-06-27 19:15+0200\n"
+"POT-Creation-Date: 2017-06-23 17:59+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <team@fixmystreet.com>\n"
@@ -21,7 +21,11 @@ msgstr ""
msgid "(optional)"
msgstr ""
-#: templates/existing.html:12 templates/strings.js:43
+#: templates/photo.html:20
+msgid "(required)"
+msgstr ""
+
+#: templates/existing.html:12 templates/strings.js:42
msgid "-- Pick a category --"
msgstr ""
@@ -38,10 +42,10 @@ msgid "Account"
msgstr ""
#: templates/photo.html:3
-msgid "Add Photo"
+msgid "Add Photos"
msgstr ""
-#: templates/photo.html:18
+#: templates/photo.html:16
msgid "Add a Photo"
msgstr ""
@@ -49,7 +53,7 @@ msgstr ""
msgid "Add a Photo "
msgstr ""
-#: templates/offline.html:56 templates/photo.html:34
+#: templates/offline.html:56 templates/photo.html:45
msgid "Add an existing photo"
msgstr ""
@@ -209,7 +213,7 @@ msgstr ""
msgid "New Report Here"
msgstr ""
-#: templates/details.html:4 templates/details_extra.html:4 templates/photo.html:7 templates/strings.js:23
+#: templates/details.html:4 templates/details_extra.html:4 templates/photo.html:9 templates/strings.js:23
msgid "Next"
msgstr ""
@@ -249,8 +253,8 @@ msgstr ""
msgid "Photo added"
msgstr ""
-#: templates/photo.html:21
-msgid "Photo for report"
+#: templates/photo.html:25
+msgid "Photos for report"
msgstr ""
#: templates/strings.js:11
@@ -393,7 +397,7 @@ msgstr ""
msgid "Signed out!"
msgstr ""
-#: templates/offline.html:4 templates/photo.html:5
+#: templates/offline.html:4 templates/photo.html:6
msgid "Skip"
msgstr ""
@@ -413,7 +417,7 @@ msgstr ""
msgid "Submit"
msgstr ""
-#: templates/offline.html:55 templates/photo.html:35
+#: templates/offline.html:55 templates/photo.html:46
msgid "Take a new photo"
msgstr ""
diff --git a/locale/en_GB.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po b/locale/en_GB.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po
index 73047be..50ddb36 100644
--- a/locale/en_GB.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po
+++ b/locale/en_GB.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: struan@mysociety.org\n"
-"POT-Creation-Date: 2017-06-27 19:15+0200\n"
+"POT-Creation-Date: 2017-06-23 17:59+0100\n"
"PO-Revision-Date: 2013-09-18 18:01+0100\n"
"Last-Translator: Struan <struan@mysociety.org>\n"
"Language-Team: LANGUAGE <team@fixmystreet.com>\n"
@@ -21,7 +21,11 @@ msgstr ""
msgid "(optional)"
msgstr ""
-#: templates/existing.html:12 templates/strings.js:43
+#: templates/photo.html:20
+msgid "(required)"
+msgstr ""
+
+#: templates/existing.html:12 templates/strings.js:42
msgid "-- Pick a category --"
msgstr ""
@@ -38,10 +42,10 @@ msgid "Account"
msgstr ""
#: templates/photo.html:3
-msgid "Add Photo"
+msgid "Add Photos"
msgstr ""
-#: templates/photo.html:18
+#: templates/photo.html:16
msgid "Add a Photo"
msgstr ""
@@ -49,7 +53,7 @@ msgstr ""
msgid "Add a Photo "
msgstr ""
-#: templates/offline.html:56 templates/photo.html:34
+#: templates/offline.html:56 templates/photo.html:45
msgid "Add an existing photo"
msgstr ""
@@ -215,7 +219,7 @@ msgid "New Report Here"
msgstr ""
#: templates/details.html:4 templates/details_extra.html:4
-#: templates/photo.html:7 templates/strings.js:23
+#: templates/photo.html:9 templates/strings.js:23
msgid "Next"
msgstr ""
@@ -255,8 +259,8 @@ msgstr ""
msgid "Photo added"
msgstr ""
-#: templates/photo.html:21
-msgid "Photo for report"
+#: templates/photo.html:25
+msgid "Photos for report"
msgstr ""
#: templates/strings.js:11
@@ -403,7 +407,7 @@ msgstr ""
msgid "Signed out!"
msgstr ""
-#: templates/offline.html:4 templates/photo.html:5
+#: templates/offline.html:4 templates/photo.html:6
msgid "Skip"
msgstr ""
@@ -423,7 +427,7 @@ msgstr ""
msgid "Submit"
msgstr ""
-#: templates/offline.html:55 templates/photo.html:35
+#: templates/offline.html:55 templates/photo.html:46
msgid "Take a new photo"
msgstr ""
diff --git a/locale/es_DO.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po b/locale/es_DO.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po
index 1275d70..fc441c7 100644
--- a/locale/es_DO.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po
+++ b/locale/es_DO.UTF-8/LC_MESSAGES/FixMyStreetMobileApp.po
@@ -25,7 +25,12 @@ msgstr ""
msgid "(optional)"
msgstr "(opcional)"
-#: templates/existing.html:12 templates/strings.js:43
+#: templates/photo.html:20
+#, fuzzy
+msgid "(required)"
+msgstr "requerido(a)"
+
+#: templates/existing.html:12 templates/strings.js:42
msgid "-- Pick a category --"
msgstr "-- Seleccione una categoría --"
@@ -42,10 +47,11 @@ msgid "Account"
msgstr "Cuenta"
#: templates/photo.html:3
-msgid "Add Photo"
+#, fuzzy
+msgid "Add Photos"
msgstr "Añadir foto"
-#: templates/photo.html:18
+#: templates/photo.html:16
msgid "Add a Photo"
msgstr "Añadir una foto"
@@ -53,7 +59,7 @@ msgstr "Añadir una foto"
msgid "Add a Photo "
msgstr "Añadir una foto "
-#: templates/offline.html:56 templates/photo.html:34
+#: templates/offline.html:56 templates/photo.html:45
msgid "Add an existing photo"
msgstr "Añadir una foto existente"
@@ -219,7 +225,7 @@ msgid "New Report Here"
msgstr "Nuevo informe aquí"
#: templates/details.html:4 templates/details_extra.html:4
-#: templates/photo.html:7 templates/strings.js:23
+#: templates/photo.html:9 templates/strings.js:23
msgid "Next"
msgstr "Siguiente"
@@ -259,8 +265,9 @@ msgstr "Número de teléfono"
msgid "Photo added"
msgstr "Foto añadida"
-#: templates/photo.html:21
-msgid "Photo for report"
+#: templates/photo.html:25
+#, fuzzy
+msgid "Photos for report"
msgstr "Foto para el informe"
#: templates/strings.js:11
@@ -407,7 +414,7 @@ msgstr "¡Sesión abierta!"
msgid "Signed out!"
msgstr "¡Sesión cerrada!"
-#: templates/offline.html:4 templates/photo.html:5
+#: templates/offline.html:4 templates/photo.html:6
msgid "Skip"
msgstr "Saltar"
@@ -427,7 +434,7 @@ msgstr "Título"
msgid "Submit"
msgstr "Enviar"
-#: templates/offline.html:55 templates/photo.html:35
+#: templates/offline.html:55 templates/photo.html:46
msgid "Take a new photo"
msgstr "Tomar una nueva foto"
diff --git a/package-lock.json-example b/package-lock.json-example
new file mode 100644
index 0000000..ab66fd7
--- /dev/null
+++ b/package-lock.json-example
@@ -0,0 +1,600 @@
+{
+ "name": "org.mysociety.groundcontrolapp",
+ "version": "1.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "cordova-android": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-6.2.3.tgz",
+ "integrity": "sha1-JJ8hts5fHxyEenq4OxaQnb7Vqig=",
+ "requires": {
+ "cordova-common": "2.0.2",
+ "elementtree": "0.1.6",
+ "nopt": "3.0.6",
+ "properties-parser": "0.2.3",
+ "q": "1.5.0",
+ "shelljs": "0.5.3"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "ansi": {
+ "version": "0.3.1",
+ "bundled": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true
+ },
+ "base64-js": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "big-integer": {
+ "version": "1.6.22",
+ "bundled": true
+ },
+ "bplist-parser": {
+ "version": "0.1.1",
+ "bundled": true,
+ "requires": {
+ "big-integer": "1.6.22"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "0.4.2",
+ "concat-map": "0.0.1"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "cordova-common": {
+ "version": "2.0.2",
+ "bundled": true,
+ "requires": {
+ "ansi": "0.3.1",
+ "bplist-parser": "0.1.1",
+ "cordova-registry-mapper": "1.1.15",
+ "elementtree": "0.1.6",
+ "glob": "5.0.15",
+ "minimatch": "3.0.3",
+ "osenv": "0.1.4",
+ "plist": "1.2.0",
+ "q": "1.5.0",
+ "semver": "5.3.0",
+ "shelljs": "0.5.3",
+ "underscore": "1.8.3",
+ "unorm": "1.4.1"
+ }
+ },
+ "cordova-registry-mapper": {
+ "version": "1.1.15",
+ "bundled": true
+ },
+ "elementtree": {
+ "version": "0.1.6",
+ "bundled": true,
+ "requires": {
+ "sax": "0.3.5"
+ }
+ },
+ "glob": {
+ "version": "5.0.15",
+ "bundled": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.3",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "lodash": {
+ "version": "3.10.1",
+ "bundled": true
+ },
+ "minimatch": {
+ "version": "3.0.3",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "1.1.7"
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "bundled": true,
+ "requires": {
+ "abbrev": "1.1.0"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "plist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "base64-js": "0.0.8",
+ "util-deprecate": "1.0.2",
+ "xmlbuilder": "4.0.0",
+ "xmldom": "0.1.27"
+ }
+ },
+ "properties-parser": {
+ "version": "0.2.3",
+ "bundled": true
+ },
+ "q": {
+ "version": "1.5.0",
+ "bundled": true
+ },
+ "sax": {
+ "version": "0.3.5",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true
+ },
+ "shelljs": {
+ "version": "0.5.3",
+ "bundled": true
+ },
+ "underscore": {
+ "version": "1.8.3",
+ "bundled": true
+ },
+ "unorm": {
+ "version": "1.4.1",
+ "bundled": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "xmlbuilder": {
+ "version": "4.0.0",
+ "bundled": true,
+ "requires": {
+ "lodash": "3.10.1"
+ }
+ },
+ "xmldom": {
+ "version": "0.1.27",
+ "bundled": true
+ }
+ }
+ },
+ "cordova-ios": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-4.5.4.tgz",
+ "integrity": "sha1-yAZIBYlyloVw3BXalzFP+S0H3+c=",
+ "requires": {
+ "cordova-common": "2.1.0",
+ "ios-sim": "6.1.2",
+ "nopt": "3.0.6",
+ "plist": "1.2.0",
+ "q": "1.5.1",
+ "shelljs": "0.5.3",
+ "xcode": "0.9.3",
+ "xml-escape": "1.1.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true
+ },
+ "ansi": {
+ "version": "0.3.1",
+ "bundled": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "base64-js": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "big-integer": {
+ "version": "1.6.25",
+ "bundled": true
+ },
+ "bplist-creator": {
+ "version": "0.0.7",
+ "bundled": true,
+ "requires": {
+ "stream-buffers": "2.2.0"
+ }
+ },
+ "bplist-parser": {
+ "version": "0.1.1",
+ "bundled": true,
+ "requires": {
+ "big-integer": "1.6.25"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "cordova-common": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "ansi": "0.3.1",
+ "bplist-parser": "0.1.1",
+ "cordova-registry-mapper": "1.1.15",
+ "elementtree": "0.1.6",
+ "glob": "5.0.15",
+ "minimatch": "3.0.4",
+ "osenv": "0.1.4",
+ "plist": "1.2.0",
+ "q": "1.5.1",
+ "semver": "5.4.1",
+ "shelljs": "0.5.3",
+ "underscore": "1.8.3",
+ "unorm": "1.4.1"
+ }
+ },
+ "cordova-registry-mapper": {
+ "version": "1.1.15",
+ "bundled": true
+ },
+ "elementtree": {
+ "version": "0.1.6",
+ "bundled": true,
+ "requires": {
+ "sax": "0.3.5"
+ }
+ },
+ "glob": {
+ "version": "5.0.15",
+ "bundled": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "ios-sim": {
+ "version": "6.1.2",
+ "bundled": true,
+ "requires": {
+ "bplist-parser": "0.0.6",
+ "nopt": "1.0.9",
+ "plist": "1.2.0",
+ "simctl": "1.1.1"
+ },
+ "dependencies": {
+ "bplist-parser": {
+ "version": "0.0.6",
+ "bundled": true
+ },
+ "nopt": {
+ "version": "1.0.9",
+ "bundled": true,
+ "requires": {
+ "abbrev": "1.1.1"
+ }
+ }
+ }
+ },
+ "lodash": {
+ "version": "3.10.1",
+ "bundled": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "bundled": true,
+ "requires": {
+ "abbrev": "1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "pegjs": {
+ "version": "0.10.0",
+ "bundled": true
+ },
+ "plist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "base64-js": "0.0.8",
+ "util-deprecate": "1.0.2",
+ "xmlbuilder": "4.0.0",
+ "xmldom": "0.1.27"
+ }
+ },
+ "q": {
+ "version": "1.5.1",
+ "bundled": true
+ },
+ "sax": {
+ "version": "0.3.5",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.4.1",
+ "bundled": true
+ },
+ "shelljs": {
+ "version": "0.5.3",
+ "bundled": true
+ },
+ "simctl": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "shelljs": "0.2.6",
+ "tail": "0.4.0"
+ },
+ "dependencies": {
+ "shelljs": {
+ "version": "0.2.6",
+ "bundled": true
+ }
+ }
+ },
+ "simple-plist": {
+ "version": "0.2.1",
+ "bundled": true,
+ "requires": {
+ "bplist-creator": "0.0.7",
+ "bplist-parser": "0.1.1",
+ "plist": "2.0.1"
+ },
+ "dependencies": {
+ "base64-js": {
+ "version": "1.1.2",
+ "bundled": true
+ },
+ "plist": {
+ "version": "2.0.1",
+ "bundled": true,
+ "requires": {
+ "base64-js": "1.1.2",
+ "xmlbuilder": "8.2.2",
+ "xmldom": "0.1.27"
+ }
+ },
+ "xmlbuilder": {
+ "version": "8.2.2",
+ "bundled": true
+ }
+ }
+ },
+ "stream-buffers": {
+ "version": "2.2.0",
+ "bundled": true
+ },
+ "tail": {
+ "version": "0.4.0",
+ "bundled": true
+ },
+ "underscore": {
+ "version": "1.8.3",
+ "bundled": true
+ },
+ "unorm": {
+ "version": "1.4.1",
+ "bundled": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "xcode": {
+ "version": "0.9.3",
+ "bundled": true,
+ "requires": {
+ "pegjs": "0.10.0",
+ "simple-plist": "0.2.1",
+ "uuid": "3.0.1"
+ }
+ },
+ "xml-escape": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "xmlbuilder": {
+ "version": "4.0.0",
+ "bundled": true,
+ "requires": {
+ "lodash": "3.10.1"
+ }
+ },
+ "xmldom": {
+ "version": "0.1.27",
+ "bundled": true
+ }
+ }
+ },
+ "cordova-plugin-camera": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-camera/-/cordova-plugin-camera-2.4.1.tgz",
+ "integrity": "sha1-GV404S22TxxJ52T31OPyYao9lME="
+ },
+ "cordova-plugin-compat": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-compat/-/cordova-plugin-compat-1.1.0.tgz",
+ "integrity": "sha1-kr3xaf62EgUyPcyWo/+DSON+h/w="
+ },
+ "cordova-plugin-device": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-device/-/cordova-plugin-device-1.1.7.tgz",
+ "integrity": "sha1-/JQRG+aTJijGaGiTjd89yCyfv+Y="
+ },
+ "cordova-plugin-dialogs": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-dialogs/-/cordova-plugin-dialogs-1.3.4.tgz",
+ "integrity": "sha1-XMlm7nyZsvW1s934SQAmKLDacVc="
+ },
+ "cordova-plugin-file": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-4.3.3.tgz",
+ "integrity": "sha1-AS6Xqhr7kfhJFuY0G1SDZtI96bk="
+ },
+ "cordova-plugin-file-transfer": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-file-transfer/-/cordova-plugin-file-transfer-1.7.1.tgz",
+ "integrity": "sha1-p12L4uvDu5sjxbG70ZkhTsJnWGs="
+ },
+ "cordova-plugin-geolocation": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-geolocation/-/cordova-plugin-geolocation-2.4.3.tgz",
+ "integrity": "sha1-HdAAI9Hxos4zD4dn7Qj3tzj+cYQ="
+ },
+ "cordova-plugin-inappbrowser": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-inappbrowser/-/cordova-plugin-inappbrowser-1.7.2.tgz",
+ "integrity": "sha1-ZHY0lb6H6y562xoI8CCblupc7uA="
+ },
+ "cordova-plugin-media": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-media/-/cordova-plugin-media-2.4.1.tgz",
+ "integrity": "sha1-kEcG76alns95awXBar4o/Jic1Wk="
+ },
+ "cordova-plugin-media-capture": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-media-capture/-/cordova-plugin-media-capture-1.4.3.tgz",
+ "integrity": "sha1-IOO74zT7uJ9iSwIYjqxTcnQ5IPo="
+ },
+ "cordova-plugin-network-information": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-network-information/-/cordova-plugin-network-information-1.3.4.tgz",
+ "integrity": "sha1-KPQmzCZZF03GIqBxgPm6DYVfc4M="
+ },
+ "cordova-plugin-splashscreen": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-splashscreen/-/cordova-plugin-splashscreen-3.2.2.tgz",
+ "integrity": "sha1-1WOL+wi9vJqz59owwhdL5kzwJ7A="
+ },
+ "cordova-plugin-statusbar": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-statusbar/-/cordova-plugin-statusbar-2.4.1.tgz",
+ "integrity": "sha1-IiYop4qlTTTUySeZACDQo7rOVUU="
+ },
+ "cordova-plugin-whitelist": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.3.tgz",
+ "integrity": "sha1-tehezbv+Wu3tQKG/TuI3LmfZb7Q="
+ },
+ "ionic-plugin-keyboard": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ionic-plugin-keyboard/-/ionic-plugin-keyboard-2.1.0.tgz",
+ "integrity": "sha1-EOVAuYg9XHhuZXv/gXIDGmMtC2Q="
+ }
+ }
+}
diff --git a/package.json-example b/package.json-example
new file mode 100644
index 0000000..439a306
--- /dev/null
+++ b/package.json-example
@@ -0,0 +1,49 @@
+{
+ "name": "org.mysociety.fixmystreet",
+ "version": "2.1",
+ "displayName": "FixMyStreet",
+ "cordova": {
+ "platforms": [
+ "android",
+ "ios"
+ ],
+ "plugins": {
+ "cordova-plugin-camera": {},
+ "cordova-plugin-compat": {},
+ "cordova-plugin-device": {},
+ "cordova-plugin-dialogs": {},
+ "cordova-plugin-file": {},
+ "cordova-plugin-file-transfer": {},
+ "cordova-plugin-geolocation": {},
+ "cordova-plugin-inappbrowser": {},
+ "cordova-plugin-media": {
+ "KEEP_AVAUDIOSESSION_ALWAYS_ACTIVE": "NO"
+ },
+ "cordova-plugin-media-capture": {},
+ "cordova-plugin-network-information": {},
+ "cordova-plugin-splashscreen": {},
+ "cordova-plugin-statusbar": {},
+ "cordova-plugin-whitelist": {},
+ "ionic-plugin-keyboard": {}
+ }
+ },
+ "dependencies": {
+ "cordova-android": "^7.1.0",
+ "cordova-ios": "^4.5.4",
+ "cordova-plugin-camera": "^4.0.3",
+ "cordova-plugin-compat": "^1.2.0",
+ "cordova-plugin-device": "^2.0.2",
+ "cordova-plugin-dialogs": "^2.0.1",
+ "cordova-plugin-file": "^6.0.1",
+ "cordova-plugin-file-transfer": "^1.7.1",
+ "cordova-plugin-geolocation": "^4.0.1",
+ "cordova-plugin-inappbrowser": "^3.0.0",
+ "cordova-plugin-media": "^5.0.2",
+ "cordova-plugin-media-capture": "^3.0.2",
+ "cordova-plugin-network-information": "^2.0.1",
+ "cordova-plugin-splashscreen": "^5.0.2",
+ "cordova-plugin-statusbar": "^2.4.2",
+ "cordova-plugin-whitelist": "^1.3.3",
+ "ionic-plugin-keyboard": "^2.2.1"
+ }
+} \ No newline at end of file
diff --git a/res/ios/icons/Icon-40.png b/res/ios/icons/Icon-40.png
index 0f7be76..edaa501 100755
--- a/res/ios/icons/Icon-40.png
+++ b/res/ios/icons/Icon-40.png
Binary files differ
diff --git a/res/ios/icons/Icon-40@2x.png b/res/ios/icons/Icon-40@2x.png
index 5fbf89a..a4889cb 100755
--- a/res/ios/icons/Icon-40@2x.png
+++ b/res/ios/icons/Icon-40@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-50.png b/res/ios/icons/Icon-50.png
index d5ae255..d59ebcb 100755
--- a/res/ios/icons/Icon-50.png
+++ b/res/ios/icons/Icon-50.png
Binary files differ
diff --git a/res/ios/icons/Icon-50@2x.png b/res/ios/icons/Icon-50@2x.png
index 5727ab8..602ef2d 100755
--- a/res/ios/icons/Icon-50@2x.png
+++ b/res/ios/icons/Icon-50@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-60.png b/res/ios/icons/Icon-60.png
index 8670077..d4b20c3 100755
--- a/res/ios/icons/Icon-60.png
+++ b/res/ios/icons/Icon-60.png
Binary files differ
diff --git a/res/ios/icons/Icon-60@2x.png b/res/ios/icons/Icon-60@2x.png
index fe9f27b..047f807 100755
--- a/res/ios/icons/Icon-60@2x.png
+++ b/res/ios/icons/Icon-60@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-60@3x.png b/res/ios/icons/Icon-60@3x.png
index 3936bab..9f48cfc 100755
--- a/res/ios/icons/Icon-60@3x.png
+++ b/res/ios/icons/Icon-60@3x.png
Binary files differ
diff --git a/res/ios/icons/Icon-72.png b/res/ios/icons/Icon-72.png
index d4cbd78..8b9f485 100755
--- a/res/ios/icons/Icon-72.png
+++ b/res/ios/icons/Icon-72.png
Binary files differ
diff --git a/res/ios/icons/Icon-72@2x.png b/res/ios/icons/Icon-72@2x.png
index 99d7ccd..4e3af31 100755
--- a/res/ios/icons/Icon-72@2x.png
+++ b/res/ios/icons/Icon-72@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-76.png b/res/ios/icons/Icon-76.png
index 8aee2db..388029c 100755
--- a/res/ios/icons/Icon-76.png
+++ b/res/ios/icons/Icon-76.png
Binary files differ
diff --git a/res/ios/icons/Icon-76@2x.png b/res/ios/icons/Icon-76@2x.png
index c46bddb..0e27d9a 100755
--- a/res/ios/icons/Icon-76@2x.png
+++ b/res/ios/icons/Icon-76@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-83.5@2x.png b/res/ios/icons/Icon-83.5@2x.png
new file mode 100644
index 0000000..fe096a0
--- /dev/null
+++ b/res/ios/icons/Icon-83.5@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-Small.png b/res/ios/icons/Icon-Small.png
index 85f4601..e7ed4b3 100755
--- a/res/ios/icons/Icon-Small.png
+++ b/res/ios/icons/Icon-Small.png
Binary files differ
diff --git a/res/ios/icons/Icon-Small@2x.png b/res/ios/icons/Icon-Small@2x.png
index 08e9bcb..61a5dc4 100755
--- a/res/ios/icons/Icon-Small@2x.png
+++ b/res/ios/icons/Icon-Small@2x.png
Binary files differ
diff --git a/res/ios/icons/Icon-Small@3x.png b/res/ios/icons/Icon-Small@3x.png
new file mode 100644
index 0000000..f1dbf68
--- /dev/null
+++ b/res/ios/icons/Icon-Small@3x.png
Binary files differ
diff --git a/res/ios/icons/Icon.png b/res/ios/icons/Icon.png
index 465a1d1..31e72f8 100755
--- a/res/ios/icons/Icon.png
+++ b/res/ios/icons/Icon.png
Binary files differ
diff --git a/res/ios/icons/Icon@2x.png b/res/ios/icons/Icon@2x.png
index cd028d4..f3a67db 100755
--- a/res/ios/icons/Icon@2x.png
+++ b/res/ios/icons/Icon@2x.png
Binary files differ
diff --git a/res/ios/icons/iTunesArtwork.png b/res/ios/icons/iTunesArtwork.png
index 01a2163..30dac6d 100755
--- a/res/ios/icons/iTunesArtwork.png
+++ b/res/ios/icons/iTunesArtwork.png
Binary files differ
diff --git a/res/ios/icons/iTunesArtwork@2x.png b/res/ios/icons/iTunesArtwork@2x.png
index c166da1..0fc5d36 100755
--- a/res/ios/icons/iTunesArtwork@2x.png
+++ b/res/ios/icons/iTunesArtwork@2x.png
Binary files differ
diff --git a/res/ios/splash/Default-1125@3x~iphonex-portrait_1125x2436.png b/res/ios/splash/Default-1125@3x~iphonex-portrait_1125x2436.png
new file mode 100644
index 0000000..bdf6d12
--- /dev/null
+++ b/res/ios/splash/Default-1125@3x~iphonex-portrait_1125x2436.png
Binary files differ
diff --git a/res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png b/res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png
index e60610d..e60610d 100755..100644
--- a/res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png
+++ b/res/ios/splash/Default-1242@3x~iphone6s-portrait_1242x2208.png
Binary files differ
diff --git a/res/ios/splash/Default-568h@2x~iphone_640x1136.png b/res/ios/splash/Default-568h@2x~iphone_640x1136.png
index a9acffc..a9acffc 100755..100644
--- a/res/ios/splash/Default-568h@2x~iphone_640x1136.png
+++ b/res/ios/splash/Default-568h@2x~iphone_640x1136.png
Binary files differ
diff --git a/res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.png b/res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.png
index 4926f98..4926f98 100755..100644
--- a/res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.png
+++ b/res/ios/splash/Default-750@2x~iphone6-portrait_750x1334.png
Binary files differ
diff --git a/res/ios/splash/Default-Portrait@2x~ipad_1536x2008.png b/res/ios/splash/Default-Portrait@2x~ipad_1536x2008.png
index 6504a06..6504a06 100755..100644
--- a/res/ios/splash/Default-Portrait@2x~ipad_1536x2008.png
+++ b/res/ios/splash/Default-Portrait@2x~ipad_1536x2008.png
Binary files differ
diff --git a/res/ios/splash/Default-Portrait@2x~ipad_1536x2048.png b/res/ios/splash/Default-Portrait@2x~ipad_1536x2048.png
index 33a18fc..33a18fc 100755..100644
--- a/res/ios/splash/Default-Portrait@2x~ipad_1536x2048.png
+++ b/res/ios/splash/Default-Portrait@2x~ipad_1536x2048.png
Binary files differ
diff --git a/res/ios/splash/Default-Portrait~ipad_768x1024.png b/res/ios/splash/Default-Portrait~ipad_768x1024.png
index 20c5109..20c5109 100755..100644
--- a/res/ios/splash/Default-Portrait~ipad_768x1024.png
+++ b/res/ios/splash/Default-Portrait~ipad_768x1024.png
Binary files differ
diff --git a/res/ios/splash/Default@2x~iphone_640x960.png b/res/ios/splash/Default@2x~iphone_640x960.png
index facda8e..facda8e 100755..100644
--- a/res/ios/splash/Default@2x~iphone_640x960.png
+++ b/res/ios/splash/Default@2x~iphone_640x960.png
Binary files differ
diff --git a/res/ios/splash/Default~iphone.png b/res/ios/splash/Default~iphone.png
index 50741df..50741df 100755..100644
--- a/res/ios/splash/Default~iphone.png
+++ b/res/ios/splash/Default~iphone.png
Binary files differ
diff --git a/scripts/prepare_index_html.js b/scripts/prepare_index_html.js
index 379b0d9..f1aa5c5 100755
--- a/scripts/prepare_index_html.js
+++ b/scripts/prepare_index_html.js
@@ -20,7 +20,7 @@ module.exports = function(context) {
var CONFIG = require("../www/js/config.js");
var files = [
- "platforms/android/assets/www/index.html",
+ "platforms/android/app/src/main/assets/www/index.html",
"platforms/ios/www/index.html",
];
files.forEach(function(file) {
diff --git a/templates/around.html b/templates/around.html
index 6419d6c..d5ff4f3 100644
--- a/templates/around.html
+++ b/templates/around.html
@@ -33,6 +33,7 @@
<% } %>
</form>
<a data-role="none" id="relocate" class="nodisplay"></a>
+ <a data-role="none" id="hidepins" class="nodisplay"></a>
<div class="nodisplay" id="front-howto"></div>
</div>
diff --git a/templates/details_extra.html b/templates/details_extra.html
index 6ef02b3..22d18b2 100644
--- a/templates/details_extra.html
+++ b/templates/details_extra.html
@@ -1,7 +1,11 @@
<div data-role="header" data-position="fixed">
<a data-rel="back" data-icon="arrow-l" class="ui-btn-left">[% loc('Back') %]</a>
<h1>[% loc('Further Details') %]</h1>
- <a id="next" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">[% loc('Next') %]</a>
+ <% if (CONFIG.SKIP_CONFIRM_REPORT) { %>
+ <a id="next" class="ui-btn-right">[% loc('Submit') %]</a>
+ <% } else { %>
+ <a id="next" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">[% loc('Next') %]</a>
+ <% } %>
</div>
<div data-role="content" data-enhance="false">
<%= category_extras %>
diff --git a/templates/existing.html b/templates/existing.html
index 1c326b8..ef9effb 100644
--- a/templates/existing.html
+++ b/templates/existing.html
@@ -17,8 +17,8 @@
<p><% print( moment( created ).fromNow() ) %></p>
</div>
- <% if ( file ) { %>
- <div class="photo" style="background-image: url(<%= file %>)"></div>
+ <% if ( files.length > 0 ) { %>
+ <div class="photo" style="background-image: url(<%= files[0] %>)"></div>
<% } %>
<% if ( details ) { %>
diff --git a/templates/login.html b/templates/login.html
index 43e93d9..0cc7c51 100644
--- a/templates/login.html
+++ b/templates/login.html
@@ -12,13 +12,9 @@
<input type="button" id="logout" name="logout" value="[% loc('Sign Out') %]" data-theme="a">
</div>
</div>
- <div id="password_row" class="nodisplay">
- <p class="notopmargin">
- [% loc('Signed out!') %]
- </p>
<% } else { %>
<div id="password_row">
- <% } %>
+ <p class="notopmargin">[% loc('You are not signed in.') %]</p>
<form name="signinForm" class="inputcard" id="signinForm">
<div>
<input data-role="none" type="email" value="" name="email" id="form_email" placeholder="[% loc('Your Email') %]" required>
@@ -31,13 +27,5 @@
</div>
</form>
</div>
- <div id="success_row" class="nodisplay">
- <p class="notopmargin">
- [% loc('Signed in!') %]
- </p>
- <div id="err" class="nodisplay"></div>
- <div class="bottom-btn">
- <input type="button" id="logout" name="logout" value="[% loc('Sign Out') %]" data-theme="a">
- </div>
- </div>
+ <% } %>
</div>
diff --git a/templates/offline.html b/templates/offline.html
index 432fb09..214170e 100644
--- a/templates/offline.html
+++ b/templates/offline.html
@@ -1,7 +1,7 @@
<div data-role="header" data-position="fixed">
<a id="offline-prev-btn" class="ui-btn-left">[% loc('Try Again') %]</a>
<h1>[% loc('Offline') %]</h1>
- <a id="offline-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">[% loc('Skip') %]</a>
+ <a id="offline-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right"><%= files.length == 0 ? "[% loc('Skip') %]" : "[% loc('Next') %]" %></a>
</div>
<div id="locating" class="nodisplay">
<div class="radar"></div>
@@ -42,30 +42,25 @@
</div>
<div>
- <textarea data-role="none" rows="7" cols="26" name="detail" id="form_detail" placeholder="Please fill in details of the problem." required><%= details %></textarea>
+ <textarea data-role="none" rows="2" cols="26" name="detail" id="form_detail" placeholder="Please fill in details of the problem." required><%= details %></textarea>
</div>
</div>
- <% if ( file != '' ) { %>
- <div id="add_photo" style="display: none">
- <% } else { %>
- <div id="add_photo">
+ <% if ( files.length < CONFIG.MAX_PHOTOS ) { %>
+ <div id="add_photo">
+ <input data-icon="fms-photo-new" value="[% loc('Take a new photo') %]" type="button" name="photo_button" id="id_photo_button" data-role="button" data-theme="a">
+ <input data-icon="fms-photo-existing" value="[% loc('Add an existing photo') %]" type="button" name="existing" id="id_existing" data-role="button" data-theme="c">
+ </div>
<% } %>
- <label>[% loc('Add a Photo ') %]<em>[% loc('(optional)') %]</em></label>
- <input data-icon="fms-photo-new" value="[% loc('Take a new photo') %]" type="button" name="photo_button" id="id_photo_button" data-role="button" data-theme="a">
- <input data-icon="fms-photo-existing" value="[% loc('Add an existing photo') %]" type="button" name="existing" id="id_existing" data-role="button" data-theme="c">
- </div>
- <% if ( file == '' ) { %>
- <div id="display_photo" style="display: none">
- <% } else { %>
- <div id="display_photo">
- <% } %>
- <label>[% loc('Your Photo') %]</label>
- <div class="photo">
- <img class="small" id="photo" src="<%= file %>" />
+ <% if ( files.length > 0 ) { %>
+ <div class="photo-wrapper">
+ <% _.each(files, function(file, index) { %>
+ <div class="photo" style="background-image: url('<%= file %>');">
+ <a data-role="none" class="photo-corner-button del_photo_button" data-file-index="<%= index %>">X</a>
+ </div>
+ <% }); %>
</div>
- <input value="[% loc('Remove Photo') %]" type="button" name="del_photo_button" id="id_del_photo_button" data-role="button" data-theme="a">
- </div>
+ <% } %>
</div>
</div>
diff --git a/templates/photo.html b/templates/photo.html
index 286dac3..0646b4a 100644
--- a/templates/photo.html
+++ b/templates/photo.html
@@ -1,37 +1,49 @@
<div data-role="header">
<a data-rel="back" data-icon="arrow-l" class="ui-btn-left">[% loc('Back') %]</a>
- <h1>[% loc('Add Photo') %]</h1>
- <% if ( file == '' ) { %>
- <a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">[% loc('Skip') %]</a>
+ <h1>[% loc('Add Photos') %]</h1>
+ <% if ( files.length == 0 ) { %>
+ <% if ( !CONFIG.PHOTO_REQUIRED ) { %>
+ <a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">[% loc('Skip') %]</a>
+ <% } %>
<% } else { %>
<a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">[% loc('Next') %]</a>
<% } %>
</div>
+
<div data-role="content">
- <% var photoClass = 'nodisplay', nophotoClass = 'nodisplay';
- if ( file != '' ) {
- photoClass = '';
- } else {
- nophotoClass = '';
- } %>
- <h2 id="nophoto_title" class="<% print( nophotoClass ); %>">
- [% loc('Add a Photo') %] <em>[% loc('(optional)') %]</em>
- </h2>
- <h2 id="photo_title" class="<% print( photoClass ); %>">
- [% loc('Photo for report') %]
- </h2>
- <div class="photo-wrapper">
- <div class="photo">
- <% if ( file == '' ) { %>
- <img class="placeholder" src="images/placeholder-photo.png" alt="" id="photo">
+ <% if ( files.length == 0 ) { %>
+ <h2 id="nophoto_title">
+ [% loc('Add a Photo') %]
+ <% if ( !CONFIG.PHOTO_REQUIRED ) { %>
+ <em>[% loc('(optional)') %]</em>
+ <% } else if ( files.length == 0) { %>
+ <em>[% loc('(required)') %]</em>
+ <%} %>
+ </h2>
<% } else { %>
- <img class="small" id="photo" src="<%= file %>" />
+ <h2 id="photo_title">
+ [% loc('Photos for report') %]
+ </h2>
<% } %>
- <a data-role="none" id="id_del_photo_button" class="photo-corner-button">X</a>
- </div>
- </div>
- <div class="bottom-btn">
- <input data-icon="fms-photo-existing" type="button" id="id_existing" data-theme="c" value="[% loc('Add an existing photo') %]" >
- <input data-icon="fms-photo-new" id="id_photo_button" type="button" data-theme="a" value="[% loc('Take a new photo') %]">
+
+ <div class="photo-wrapper">
+ <% if ( files.length == 0 ) { %>
+ <div class="photo">
+ <img class="placeholder" src="images/placeholder-photo.png" alt="">
+ </div>
+ <% } else { %>
+ <% _.each(files, function(file, index) { %>
+ <div class="photo" style="background-image: url('<%= file %>');">
+ <a data-role="none" class="photo-corner-button del_photo_button" data-file-index="<%= index %>">X</a>
+ </div>
+ <% });%>
+ <% } %>
</div>
+
+ <% if ( files.length < CONFIG.MAX_PHOTOS ) { %>
+ <div class="bottom-btn">
+ <input data-icon="fms-photo-existing" type="button" id="id_existing" data-theme="c" value="[% loc('Add an existing photo') %]" >
+ <input data-icon="fms-photo-new" id="id_photo_button" type="button" data-theme="a" value="[% loc('Take a new photo') %]">
+ </div>
+ <% } %>
</div>
diff --git a/templates/reports.html b/templates/reports.html
index e70dd3d..a08ffc6 100644
--- a/templates/reports.html
+++ b/templates/reports.html
@@ -15,7 +15,7 @@
if ( draft.get('lat') ) {
classes.push('with_location');
}
- if ( draft.get('file') ) {
+ if ( draft.get('files').length > 0 ) {
classes.push('with_photo');
}
var draftClass = '';
diff --git a/templates/strings.js b/templates/strings.js
index 55f68d4..b7b2388 100644
--- a/templates/strings.js
+++ b/templates/strings.js
@@ -17,7 +17,10 @@
required: '[% loc('Please enter your email') %]',
email: '[% loc('Please enter a valid email') %]'
},
- password: '[% loc('Please enter a password') %]'
+ password: {
+ required: '[% loc('Please enter a password') %]',
+ short: '[% loc('Please enter a password at least %d characters long') %]'
+ }
},
strings: {
next: '[% loc('Next') %]',
diff --git a/templates/submit_confirm.html b/templates/submit_confirm.html
index bca55fc..1d3e862 100644
--- a/templates/submit_confirm.html
+++ b/templates/submit_confirm.html
@@ -3,7 +3,7 @@
<h1>[% loc('Your details') %]</h1>
</div>
-<div data-role="content">
+<div data-role="content"<% if (CONFIG.SKIP_CONFIRM_REPORT) { %> class="hidden"<% } %>>
<p class="notopmargin">
[% tprintf(loc('You are logged in as %s'), '<%= user.email %>') %].
</p>
diff --git a/templates/submit_set_password.html b/templates/submit_set_password.html
index ee681cc..ef06040 100644
--- a/templates/submit_set_password.html
+++ b/templates/submit_set_password.html
@@ -12,7 +12,7 @@
</p>
<div class="inputcard">
<div>
- <input data-role="none" type="password" value="" name="password" id="form_password" placeholder="[% loc('Your password') %]" required>
+ <input data-role="none" type="password" value="<%= FMS.currentUser.get('password') %>" name="password" id="form_password" placeholder="[% loc('Your password') %]" required>
</div>
</div>
<div class="noborder">
diff --git a/www/cobrands/cuidomiciudad/css/style.css b/www/cobrands/cuidomiciudad/css/style.css
index b50f822..db3112f 100644
--- a/www/cobrands/cuidomiciudad/css/style.css
+++ b/www/cobrands/cuidomiciudad/css/style.css
@@ -1,11 +1,11 @@
/* line 8, style.scss */
-.ios7 .ui-bar-a,
-body.ios7 {
+.ios .ui-bar-a,
+body.ios {
background-color: #005cb9;
}
/* line 13, style.scss */
-.ios7 .ui-bar-a {
+.ios .ui-bar-a {
border-color: #005cb9;
}
diff --git a/www/cobrands/cuidomiciudad/css/style.scss b/www/cobrands/cuidomiciudad/css/style.scss
index 3976a23..71cb081 100644
--- a/www/cobrands/cuidomiciudad/css/style.scss
+++ b/www/cobrands/cuidomiciudad/css/style.scss
@@ -5,12 +5,12 @@ $color-cmc-yellow: #eed11c;
$color-cmc-green: #00ad68;
$text-color: #eee;
-.ios7 .ui-bar-a,
-body.ios7 {
+.ios .ui-bar-a,
+body.ios {
background-color: $color-cmc-blue;
}
-.ios7 .ui-bar-a {
+.ios .ui-bar-a {
border-color: $color-cmc-blue;
}
diff --git a/www/cobrands/makemyisland/css/style.css b/www/cobrands/makemyisland/css/style.css
index e0ee20c..106d6e0 100644
--- a/www/cobrands/makemyisland/css/style.css
+++ b/www/cobrands/makemyisland/css/style.css
@@ -1,8 +1,8 @@
-.ios7 .ui-bar-a,
-body.ios7 {
+.ios .ui-bar-a,
+body.ios {
background-color: #9fd9ea; }
-.ios7 .ui-bar-a {
+.ios .ui-bar-a {
border-color: #9fd9ea; }
#load-screen,
diff --git a/www/cobrands/makemyisland/css/style.scss b/www/cobrands/makemyisland/css/style.scss
index ea8c43c..195d7f1 100644
--- a/www/cobrands/makemyisland/css/style.scss
+++ b/www/cobrands/makemyisland/css/style.scss
@@ -3,12 +3,12 @@
$yellow: rgb(249, 255, 198);
$blue: rgb(159, 217, 234);
-.ios7 .ui-bar-a,
-body.ios7 {
+.ios .ui-bar-a,
+body.ios {
background-color: $blue;
}
-.ios7 .ui-bar-a {
+.ios .ui-bar-a {
border-color: $blue;
}
diff --git a/www/css/fms.css b/www/css/fms.css
index aa93acc..d800619 100644
--- a/www/css/fms.css
+++ b/www/css/fms.css
@@ -160,38 +160,37 @@
background-color: rgba(0,0,0,0);
}
-/* ios 7 tweaks to deal with different status bar behaviour */
- .ios7 .ui-mobile-viewport {
+/* ios tweaks to deal with different status bar behaviour */
+ .ios .ui-mobile-viewport {
background-color: none;
background-image: none;
}
- .ios7 .ui-bar-a,
- body.ios7 {
+ .ios .ui-bar-a,
+ body.ios {
background-color: #F6BE41;
background-image: none;
}
- .ios7 .ui-bar-a {
+ .ios .ui-bar-a {
border-color: #F6BE41;
}
- .ios7 .ui-header-fixed .ui-btn-left,
- .ios7 .ui-header-fixed .ui-btn-right {
+ .ios .ui-header-fixed .ui-btn-left,
+ .ios .ui-header-fixed .ui-btn-right {
top: 4px;
}
- .ios7 #map_box {
- top: 20px;
+ .ios #map_box {
background-color: #534741;
background-image: url('../images/mapbg.png');
}
- .ios7 #around-page #locating {
- bottom: -22px;
+ .ios #around-page #locating {
+ bottom: -2px;
}
- .ios7 #map_box .olLayerDiv div {
+ .ios #map_box .olLayerDiv div {
display: block !important;
}
@@ -210,7 +209,7 @@
#drafts,
div[data-role='content'] {
position: relative;
- margin: 20px 10px;
+ margin: 10px 10px 20px 10px;
background-color: rgba(255, 255, 255, 0.9);
}
@@ -401,6 +400,10 @@
text-align: center;
}
+ #offline textarea {
+ min-height: 0;
+ }
+
/* home screen */
#front-page div[data-role='content'] {
@@ -424,6 +427,9 @@
-webkit-filter: blur(3px);
opacity: 0.9;
}
+ #map_box.background-map .olControlAttribution{
+ display: none;
+ }
#map{
opacity: 0.85;
@@ -592,19 +598,31 @@
}
- #relocate {
- display: block;
+ #relocate, #hidepins {
+ display: inline-block;
height: 30px;
width: 30px;
padding: 5px;
margin: 0px;
background-color: rgba(248,248,248,0.9);
+ }
+
+ #relocate {
background-image: url(../images/location@x2.png);
background-repeat: no-repeat;
background-position: center center;
background-size: 50%;
}
+ #hidepins {
+ background-image: url(../images/hide-pins-link.png);
+ background-image: url(../images/hide-pins-link.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-size: 80%;
+ margin-left: .3em;
+ }
+
#pc {
padding-left: 0.2em;
border-left: 1px solid #F6BE41;
@@ -726,11 +744,29 @@
div.photo {
position: relative;
display: inline-block;
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: top center;
+ width: 100%;
+ margin: 0 0 1em 0;
+ -webkit-box-flex: 1;
+ flex: 1;
+ }
+
+ div.photo:nth-child(3) {
+ margin-bottom: 0;
}
div.photo-wrapper {
margin: auto;
text-align: center;
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ flex-direction: column;
+ -webkit-box-align: center;
+ align-items: center;
}
img.small {
@@ -744,9 +780,9 @@
width: 270px;
}
- #id_del_photo_button.photo-corner-button {
+ .del_photo_button.photo-corner-button {
position: absolute;
- bottom: -15px;
+ top: -15px;
right: 0px;
-webkit-border-radius: 50%;
border-radius: 50%;
@@ -758,6 +794,12 @@
font-size: 30px;
}
+ /* On the offline page the UI is ordered differently, so we want
+ to stop the button overlapping the 'add another photo' butto' */
+ #offline .del_photo_button.photo-corner-button {
+ top: 0;
+ }
+
@media only screen and (max-width: 800px) and (min-width: 600px) {
img.placeholder {
height: 398px;
@@ -814,6 +856,11 @@
}
#category_meta {
margin: 0px 15px 15px 15px;
+ padding: 1em 0;
+ }
+
+ #category_meta h2 {
+ line-height: 1em;
}
#category_meta h4 {
@@ -931,3 +978,28 @@
top: 5px;
right: 5px;
}
+
+ .ui-content.hidden {
+ visibility: hidden;
+ }
+
+/* iPhone X has an 'unsafe' area occupied by the home
+indicator at the bottom of screen, which we need to stop UI controls
+clashing with. */
+body.iphone-x {
+ /* iOS 11–11.1 use constant(), 11.2 uses env() - assign whatever one is valid
+ to a CSS variable as this makes things simpler (e.g. with calc()) */
+ --safe-area-inset-bottom: constant(safe-area-inset-bottom);
+ --safe-area-inset-bottom: env(safe-area-inset-bottom);
+}
+
+/* The OpenLayers attribution control */
+body.iphone-x .olControlAttribution {
+ padding-bottom: var(--safe-area-inset-bottom);
+}
+
+/* The "new report here" button */
+body.iphone-x .map-bottom-btn {
+ /* Can't use env() inside calc(), so assign value to a CSS variable instead */
+ bottom: calc(20px + var(--safe-area-inset-bottom));
+}
diff --git a/www/images/hide-pins-link.png b/www/images/hide-pins-link.png
new file mode 100644
index 0000000..d2b48ac
--- /dev/null
+++ b/www/images/hide-pins-link.png
Binary files differ
diff --git a/www/images/hide-pins-link.svg b/www/images/hide-pins-link.svg
new file mode 100644
index 0000000..1c8ed76
--- /dev/null
+++ b/www/images/hide-pins-link.svg
@@ -0,0 +1 @@
+<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg"><g fill="#000" fill-rule="evenodd"><path d="M25.4 21.1l-3.7-3.6A4 4 0 0 0 18 12a4 4 0 0 0-1.5.3L13 8.6a9 9 0 0 1 12.5 12.5zm-4.5 4l-3 6-3.4-6.8a9 9 0 0 1-5.2-10.7L21 25.2zM7.4 6L30 28.6 28.6 30 6 7.4z"/></g></svg> \ No newline at end of file
diff --git a/www/index.html b/www/index.html
index aae1e71..b60ab56 100644
--- a/www/index.html
+++ b/www/index.html
@@ -8,7 +8,7 @@
-->
<head>
<title></title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<meta charset="utf-8">
<script type="text/javascript" src="jslib/jquery-1.9.1.min.js"></script>
diff --git a/www/js/app.js b/www/js/app.js
index 282e921..8b7432c 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -100,6 +100,11 @@ var tpl = {
printDebug: function(msg) {
if ( CONFIG.DEBUG ) {
console.log(msg);
+
+ // Some messages get logged before we've had a chance to
+ // attach the debugger, so keep them all for later reference.
+ FMS.debug_messages = FMS.debug_messages || [];
+ FMS.debug_messages.push(msg);
}
},
@@ -113,21 +118,28 @@ var tpl = {
},
checkLoggedInStatus: function() {
+ var p = $.Deferred();
+
if ( FMS.isOffline ) {
+ p.resolve();
} else {
$.ajax( {
url: CONFIG.FMS_URL + '/auth/ajax/check_auth',
type: 'GET',
dataType: 'json',
timeout: 30000,
- success: function( data, status ) {
- FMS.isLoggedIn = 1;
- },
- error: function() {
- FMS.isLoggedIn = 0;
- }
- } );
+ })
+ .done(function() {
+ FMS.isLoggedIn = 1;
+ p.resolve();
+ })
+ .fail(function() {
+ FMS.isLoggedIn = 0;
+ p.resolve();
+ })
}
+
+ return p;
},
saveCurrentDraft: function(force) {
@@ -151,12 +163,12 @@ var tpl = {
removeDraft: function(draftID, removePhoto) {
var draft = FMS.allDrafts.get(draftID);
- var uri = draft.get('file');
+ var files = draft.get('files');
FMS.allDrafts.remove(draft);
draft.destroy();
- if ( removePhoto && uri ) {
- return FMS.files.deleteURI( uri );
+ if ( removePhoto && files.length ) {
+ return FMS.files.deleteURIs( files );
}
var p = $.Deferred();
p.resolve();
@@ -266,6 +278,13 @@ var tpl = {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(false);
}
$('#load-screen').height( $(window).height() );
+
+ // Rough-and-ready iPhone X detection so CSS can stop things
+ // obscuring the home indicator at the bottom of the screen.
+ if (window.screen.width == 375 && window.screen.height == 812) {
+ $("body").addClass("iphone-x");
+ }
+
FMS.initialized = 1;
if ( navigator && navigator.splashscreen ) {
navigator.splashscreen.hide();
@@ -283,11 +302,7 @@ var tpl = {
if ( typeof device !== 'undefined' && device.platform === 'iOS' ) {
var model = parseInt(device.model.replace('iPhone',''), 10);
FMS.iPhoneModel = model;
-
- // fix overlap of status bar in ios7
- if (parseFloat(window.device.version) >= 7.0) {
- $('body').addClass('ios7');
- }
+ $('body').addClass('ios');
}
_.extend(FMS, {
@@ -306,9 +321,6 @@ var tpl = {
}
FMS.windowHeight = $(window).height();
- if ( $('body').hasClass('ios7') ) {
- FMS.windowHeight -= 20;
- }
if ( localStorage.usedBefore ) {
FMS.usedBefore = 1;
@@ -327,23 +339,37 @@ var tpl = {
$(document).on('ajaxStart', function() { $.mobile.loading('show'); } );
$(document).on('ajaxStop', function() { $.mobile.loading('hide'); } );
- $('#display-help').on('vclick', function(e) { FMS.helpShow(e); } );
+ $('#display-help').on('vclick', function(e) {
+ // Avoid a problem with input cursors being visible through
+ // the help layer on Web View, by unfocusing the element
+ if (device.platform === 'iOS') {
+ $('input').blur();
+ }
+
+ FMS.helpShow(e);
+ });
+
$('#dismiss').on('vclick', function(e) { FMS.helpHide(e); } );
FMS.allDrafts.comparator = function(a,b) { var a_date = a.get('created'), b_date = b.get('created'); return a_date === b_date ? 0 : a_date < b_date ? 1 : -1; };
FMS.allDrafts.fetch();
FMS.checkOnlineStatus();
FMS.loadCurrentDraft();
- FMS.checkLoggedInStatus();
- FMS.setupHelp();
-
- Backbone.history.start();
- if ( navigator && navigator.splashscreen ) {
- navigator.splashscreen.hide();
- } else {
- $('#load-screen').hide();
- }
- $('#display-help').show();
+ FMS.checkLoggedInStatus().done(function() {
+ if (!CONFIG.HELP_DISABLED) {
+ FMS.setupHelp();
+ }
+
+ Backbone.history.start();
+ if ( navigator && navigator.splashscreen ) {
+ navigator.splashscreen.hide();
+ } else {
+ $('#load-screen').hide();
+ }
+ if (!CONFIG.HELP_DISABLED) {
+ $('#display-help').show();
+ }
+ });
});
}
});
diff --git a/www/js/config.js-example b/www/js/config.js-example
index 2fceda7..1f1eef1 100644
--- a/www/js/config.js-example
+++ b/www/js/config.js-example
@@ -43,7 +43,50 @@ var CONFIG = {
image_svg: 'images/pin.svg',
background_svg: 'images/pin_shadow.svg'
}
- }
+ },
+
+ // Set this to true if you want to disable the help button on the right hand
+ // side of the screen. NB you'll also need to hide #display-help and #help
+ // elements in your CSS.
+ HELP_DISABLED: false,
+
+ // Set this to true if the user must provide at least one photo when making
+ // a report. If this is true the 'skip' button on the photo page is removed
+ // and 'next' doesn't appear until at least one photo is attached.
+ PHOTO_REQUIRED: false,
+
+ // The maximum number of photos the user can attach to a report.
+ MAX_PHOTOS: 3,
+
+ // If this is true then the user must login as the first step after
+ // installing the app, and before making any reports.
+ LOGIN_REQUIRED: false,
+
+ // The ratio of the data bounds to the viewport bounds (in each dimension).
+ // See http://dev.openlayers.org/releases/OpenLayers-2.13.1/doc/apidocs/files/OpenLayers/Strategy/BBOX-js.html
+ MAP_LOADING_RATIO: 2,
+
+ // If the user is logged in and this setting is true, the 'Your details'
+ // page is skipped and the report is sent immediately after the report
+ // details have been entered.
+ SKIP_CONFIRM_REPORT: false,
+
+ // You can optionally enforce a minimum password length if the user is
+ // registering an account when submitting a report. This should match the
+ // same minimum length required by your FixMyStreet server.
+ // Set this to 0 if you wish to disable this check. NB: If the check is
+ // active on the server the user's password may still be rejected if it's
+ // too short.
+ PASSWORD_MIN_LENGTH: 6,
+
+ // FMS provides a mechanism for rejecting passwords that are too common.
+ // Set this flag to true if the password should be checked against the
+ // server when a user registers an account via the app.
+ // NB: If this flag is false here but the check is active on the FMS server,
+ // common passwords will still be rejected at the point the report is sent
+ // from the app to the server - which may be a large POST if the report has
+ // photos attached.
+ PASSWORD_CHECK_COMMON: true
};
diff --git a/www/js/files.js b/www/js/files.js
index eea38c3..0725323 100644
--- a/www/js/files.js
+++ b/www/js/files.js
@@ -57,6 +57,16 @@
},
+ deleteURIs: function(uris) {
+ console.log("deleteURIs", uris);
+ var deferred = $.Deferred();
+ deferred.resolve();
+ uris.forEach(function(uri) {
+ deferred = deferred.then(FMS.files.deleteURI(uri));
+ });
+ return deferred;
+ },
+
// Delete a file from the filesystem
deleteFile: function (path) {
@@ -124,7 +134,7 @@
function moveFile (src, dest, newName) {
- FMS.printDebug( 'moveing file ' + src.fullPath + ' to ' + dest.fullPath );
+ FMS.printDebug( 'moving file ' + src.fullPath + ' to ' + dest.fullPath );
var move = $.Deferred();
@@ -166,7 +176,7 @@
var file = $.Deferred();
- window.resolveLocalFileSystemURI( uri, file.resolve, file.reject);
+ window.resolveLocalFileSystemURL( uri, file.resolve, file.reject);
return file.promise();
}
diff --git a/www/js/map-OpenLayers.js b/www/js/map-OpenLayers.js
index d458641..1de220d 100644
--- a/www/js/map-OpenLayers.js
+++ b/www/js/map-OpenLayers.js
@@ -128,7 +128,7 @@ function fixmystreet_onload() {
fixmystreet.map.addLayer(fixmystreet.report_location);
if (fixmystreet.page == 'around') {
- fixmystreet.bbox_strategy = new OpenLayers.Strategy.BBOX({ ratio: 1 });
+ fixmystreet.bbox_strategy = new OpenLayers.Strategy.BBOX({ ratio: CONFIG.MAP_LOADING_RATIO });
pin_layer_options.strategies = [ fixmystreet.bbox_strategy ];
pin_layer_options.protocol = new OpenLayers.Protocol.HTTP({
url: CONFIG.FMS_URL + '/ajax',
@@ -202,13 +202,9 @@ OpenLayers.Map.prototype.getCurrentSize = function() {
function show_map(event) {
if (typeof fixmystreet !== 'undefined' && fixmystreet.page == 'around') {
// Immediately go full screen map if on around page
- var mapTop = 0;
- if ( $('body').hasClass('ios7') ) {
- mapTop = 20;
- }
$('#map_box').css({
position: 'fixed',
- top: mapTop, left: 0, right: 0, bottom: 0,
+ top: 0, left: 0, right: 0, bottom: 0,
height: FMS.windowHeight,
margin: 0
});
@@ -408,7 +404,7 @@ OpenLayers.Control.ActionAfterDrag = OpenLayers.Class(OpenLayers.Control, {
if ( $('#confirm-map').css('display') == 'block' ) {
$('#reposition').show();
} else {
- $('#relocate').show();
+ $('#relocate, #hidepins').removeClass('nodisplay');
$('#front-howto').hide();
}
}
diff --git a/www/js/models/draft.js b/www/js/models/draft.js
index 56d8111..e517f1b 100644
--- a/www/js/models/draft.js
+++ b/www/js/models/draft.js
@@ -3,17 +3,19 @@
Draft: Backbone.Model.extend({
localStorage: new Backbone.LocalStorage(CONFIG.NAMESPACE + '-drafts'),
- defaults: {
- lat: 0,
- lon: 0,
- title: '',
- details: '',
- may_show_name: '',
- category: '',
- phone: '',
- pc: '',
- file: '',
- created: moment.utc()
+ defaults: function() {
+ return {
+ lat: 0,
+ lon: 0,
+ title: '',
+ details: '',
+ may_show_name: '',
+ category: '',
+ phone: '',
+ pc: '',
+ files: [],
+ created: moment.utc()
+ };
},
description: function() {
@@ -33,7 +35,7 @@
this.get('title') ||
this.get('details') ||
this.get('category') ||
- this.get('file')
+ this.get('files').length
) {
return true;
}
diff --git a/www/js/models/report.js b/www/js/models/report.js
index 1a72e73..6926980 100644
--- a/www/js/models/report.js
+++ b/www/js/models/report.js
@@ -3,16 +3,18 @@
Report: Backbone.Model.extend({
urlRoot: CONFIG.FMS_URL + '/report/ajax',
- defaults: {
- lat: 0,
- lon: 0,
- title: '',
- details: '',
- may_show_name: '',
- category: '',
- phone: '',
- pc: '',
- file: ''
+ defaults: function() {
+ return {
+ lat: 0,
+ lon: 0,
+ title: '',
+ details: '',
+ may_show_name: '',
+ category: '',
+ phone: '',
+ pc: '',
+ files: []
+ };
},
sync: function(method, model, options) {
@@ -51,6 +53,74 @@
return false;
},
+ _readFileAsBase64String: function(file, success, error) {
+ return this._readFileAsBinaryString(file, function(data) {
+ var b64 = btoa(data);
+ success(b64);
+ }, error);
+ },
+
+ _readFileAsBinaryString: function(file, success, error) {
+ var reader = new FileReader();
+ reader.onloadend = function() {
+ success(this.result);
+ };
+ reader.onerror = error;
+ return reader.readAsBinaryString(file);
+ },
+
+ _getParamName: function(field, encoding, length) {
+ // The FileTransfer plugin technically only supports a single
+ // file in each upload. However, we can force other files to
+ // be added with a little workaround.
+ // FileTransfer allows extra parameters to be sent with the
+ // HTTP POST request, each of which is its own part of the
+ // multipart-encoded request.
+ // For a part to be treated as a file by the backend we need
+ // to provide a 'filename' value in the Content-Disposition
+ // header. The FileTransfer code doesn't escape the names of
+ // extra POST parameters[0][1], so we can take advantage of this
+ // and essentially inject our own header lines and filename
+ // value with a carefully-crafted HTTP POST field name that's
+ // passed to FileTransfer.upload.
+ // FIXME: This is basically a hack, and needs a better
+ // solution at some point.
+ // [0]: https://github.com/apache/cordova-plugin-file-transfer/blob/49c21f951f51381d887646b38823222ed11c60c1/src/ios/CDVFileTransfer.m#L208
+ // [1]: https://github.com/apache/cordova-plugin-file-transfer/blob/49c21f951f51381d887646b38823222ed11c60c1/src/android/FileTransfer.java#L369
+ var name = field + '"; filename="' + field + '.jpg"\r\n';
+ name += "Content-Type: image/jpeg\r\n";
+ name += "Content-Transfer-Encoding: " + encoding + "\r\n";
+ name += "Content-Length: " + length + "\r\n";
+ name += 'X-Ignore-This-Header: "'; // to close the open quotes
+ return name;
+ },
+
+ _addExtraPhotos: function(files, options, success, error) {
+ var photos = [];
+ for (var i = 0; i < files.length; i++) {
+ var uri = files[i];
+ photos.push({field: "photo"+(i+2), uri: uri});
+ }
+ this._addNextExtraPhoto(photos, options, success, error);
+ },
+
+ _addNextExtraPhoto: function(photos, options, success, error) {
+ var photo = photos.shift();
+ if (photo === undefined) {
+ success();
+ return;
+ }
+ var self = this;
+ resolveLocalFileSystemURL(photo.uri, function(fileentry) {
+ fileentry.file(function(file) {
+ self._readFileAsBase64String(file, function(data) {
+ options.params[self._getParamName(photo.field, "base64", data.length)] = data;
+ self._addNextExtraPhoto(photos, options, success, error);
+ }, error);
+ }, error);
+ }, error);
+ },
+
post: function(model,options) {
var params = {
@@ -86,7 +156,7 @@
}
var that = this;
- if ( model.get('file') && model.get('file') !== '' ) {
+ if ( model.get('files') && model.get('files').length > 0 ) {
var fileUploadSuccess = function(r) {
FMS.uploading = false;
$.mobile.loading('hide');
@@ -122,7 +192,8 @@
}
};
- fileURI = model.get('file');
+ var files = model.get('files').slice();
+ fileURI = files.shift();
var fileOptions = new FileUploadOptions();
fileOptions.fileKey="photo";
@@ -169,14 +240,25 @@
uploadPcnt++;
}
};
- $.mobile.loading('show', {
- text: FMS.strings.photo_loading,
- textVisible: true,
- html: '<span class="ui-icon ui-icon-loading"></span><h1>' + FMS.strings.photo_loading + '</h1><span id="progress"></span>'
- });
- window.setTimeout( checkUpload, 15000 );
- FMS.uploading = true;
- ft.upload(fileURI, CONFIG.FMS_URL + "/report/new/mobile", fileUploadSuccess, fileUploadFail, fileOptions);
+
+ // If file2 or file3 have been set on this model we need to
+ // add the photos to the file upload request manually
+ // as FileTransfer only supports a single file upload.
+ that._addExtraPhotos(
+ files,
+ fileOptions,
+ function() {
+ $.mobile.loading('show', {
+ text: FMS.strings.photo_loading,
+ textVisible: true,
+ html: '<span class="ui-icon ui-icon-loading"></span><h1>' + FMS.strings.photo_loading + '</h1><span id="progress"></span>'
+ });
+ window.setTimeout( checkUpload, 15000 );
+ FMS.uploading = true;
+ ft.upload(fileURI, CONFIG.FMS_URL + "/report/new/mobile", fileUploadSuccess, fileUploadFail, fileOptions);
+ },
+ fileUploadFail
+ );
};
setupChecker();
} else {
diff --git a/www/js/router.js b/www/js/router.js
index c691abb..2a23708 100644
--- a/www/js/router.js
+++ b/www/js/router.js
@@ -159,7 +159,7 @@
// any transitions as they just add visual distraction to no end
// likewise displaying the offline page
var options = { changeHash: false };
- if ( !this.currentView || this.currentView.id == 'front-page' || view.id == 'offline' ) {
+ if ( !this.currentView || this.currentView.id == 'front-page' || view.id == 'offline' || view.id === this.currentView.id) {
options.transition = 'none';
}
if ( this.reverse ) {
diff --git a/www/js/strings.en.js b/www/js/strings.en.js
index 1dabd30..bf67b14 100644
--- a/www/js/strings.en.js
+++ b/www/js/strings.en.js
@@ -17,7 +17,10 @@
required: 'Please enter your email',
email: 'Please enter a valid email'
},
- password: 'Please enter a password'
+ password: {
+ required: 'Please enter a password',
+ short: 'Please enter a password at least %d characters long'
+ }
},
strings: {
next: 'Next',
diff --git a/www/js/strings.es.js b/www/js/strings.es.js
index 9c8b950..5b2481b 100644
--- a/www/js/strings.es.js
+++ b/www/js/strings.es.js
@@ -17,7 +17,10 @@
required: 'Por favor, introduzca su email',
email: 'Por favor, introduzca un email válido'
},
- password: 'Por favor, introduzca la contraseña'
+ password: {
+ required: 'Por favor, introduzca la contraseña',
+ short: 'Please enter a password at least %d characters long'
+ }
},
strings: {
next: 'Siguiente',
diff --git a/www/js/views/around.js b/www/js/views/around.js
index f0b8692..4afc5bb 100644
--- a/www/js/views/around.js
+++ b/www/js/views/around.js
@@ -15,6 +15,7 @@
'vclick .ui-input-clear': 'clearSearchErrors',
'blur #pc': 'clearSearchErrors',
'vclick #relocate': 'centerMapOnPosition',
+ 'vclick #hidepins': 'toggleMarkersVisibility',
'vclick #cancel': 'onClickCancel',
'vclick #confirm-map': 'onClickReport',
'vclick #mark-here': 'onClickMark',
@@ -45,7 +46,7 @@
$('#view-my-reports').hide();
$('#login-options').hide();
$('#postcodeForm').hide();
- $('#relocate').hide();
+ $('#relocate, #hidepins').addClass("nodisplay");
$('#cancel').hide();
$('#map_box').removeClass('background-map');
this.fixPageHeight();
@@ -101,7 +102,7 @@
},
gotLocation: function( info ) {
- $('#relocate').show();
+ $('#relocate, #hidepins').removeClass("nodisplay");
this.finishedLocating();
this.listenTo(FMS.locator, 'gps_current_position', this.positionUpdate);
@@ -121,7 +122,7 @@
positionUpdate: function( info ) {
if ( $('#front-howto').is(':hidden') ) {
- $('#relocate').show();
+ $('#relocate, #hidepins').removeClass("nodisplay");
}
FMS.currentPosition = info.coordinates;
var centre = this.projectCoords( info.coordinates );
@@ -182,7 +183,7 @@
msg = FMS.strings.location_problem;
}
if ( !fixmystreet.map ) {
- $('#relocate').hide();
+ $('#relocate, #hidepins').addClass("nodisplay");
$('#mark-here').hide();
// if we are going to display the help then we don't want to focus on
// the search box as it will show through the help
@@ -197,7 +198,7 @@
},
displayHelpIfFirstTime: function() {
- if ( !FMS.usedBefore ) {
+ if ( !FMS.usedBefore && !CONFIG.HELP_DISABLED ) {
FMS.helpShow();
}
},
@@ -267,7 +268,6 @@
onClickCancel: function(e) {
e.preventDefault();
- fixmystreet.markers.removeAllFeatures();
fixmystreet_activate_drag();
// force pins to be refetched and displayed
fixmystreet.bbox_strategy.update({force: true});
@@ -352,7 +352,7 @@
},
goAddress: function(e) {
- $('#relocate').show();
+ $('#relocate, #hidepins').removeClass("nodisplay");
$('#front-howto').html('').hide();
var t = $(e.target);
var lat = t.attr('data-lat');
@@ -371,7 +371,7 @@
$('#pc').attr('placeholder', msg).addClass('error');;
} else {
$('#front-howto').html(msg);
- $('#relocate').hide();
+ $('#relocate, #hidepins').addClass("nodisplay");
$('#front-howto').show();
}
},
@@ -380,7 +380,7 @@
$('#pc').attr('placeholder', this.origPcPlaceholder).removeClass('error');;
if ( fixmystreet.map ) {
$('#front-howto').hide();
- $('#relocate').show();
+ $('#relocate, #hidepins').removeClass("nodisplay");
}
},
@@ -400,7 +400,7 @@
}
$('#front-howto').html('<p>' + FMS.strings.multiple_matches + '</p><ul data-role="listview" data-inset="true">' + multiple + '</ul>');
$('.ui-page').trigger('create');
- $('#relocate').hide();
+ $('#relocate, #hidepins').addClass("nodisplay");
$('#front-howto').show();
} else {
this.searchError( FMS.strings.location_problem );
@@ -410,9 +410,7 @@
pauseMap: function() {
this.stopListening(FMS.locator);
FMS.locator.stopTracking();
- if ( FMS.iPhoneModel > 3 ) {
- $('#map_box').addClass('background-map');
- }
+ $('#map_box').addClass('background-map');
$('#map_box').off('touchend');
if ( fixmystreet.map ) {
fixmystreet.nav.deactivate();
@@ -442,7 +440,7 @@
e.preventDefault();
if ( !fixmystreet.map ) {
this.$('#mark-here').hide();
- this.$('#relocate').hide();
+ this.$('#relocate, #hidepins').addClass("nodisplay");
$('#front-howto').html('<p>' + FMS.strings.locate_dismissed + '</p>');
$('#front-howto').show();
}
@@ -497,6 +495,11 @@
);
return centre;
+ },
+
+ toggleMarkersVisibility: function(e) {
+ e.preventDefault();
+ fixmystreet.markers.setVisibility(!fixmystreet.markers.getVisibility());
}
})
});
diff --git a/www/js/views/details.js b/www/js/views/details.js
index 9f03d58..84b6ac2 100644
--- a/www/js/views/details.js
+++ b/www/js/views/details.js
@@ -18,6 +18,16 @@
'blur input': 'updateCurrentReport'
},
+ initialize: function() {
+ var that = this;
+ window.addEventListener('native.keyboardshow', function(e) {
+ that.fixDetailTextAreaHeight(e.keyboardHeight);
+ });
+ window.addEventListener('native.keyboardhide', function(e) {
+ that.fixDetailTextAreaHeight();
+ });
+ },
+
afterRender: function() {
this.$('#form_category').attr('data-role', 'none');
@@ -28,13 +38,18 @@
},
- beforeDisplay: function() {
- this.fixPageHeight();
+ beforeDisplay: function(extra) {
+ this.fixDetailTextAreaHeight();
+ },
+
+ fixDetailTextAreaHeight: function(extra) {
+ extra = extra || 0;
+ this.fixPageHeight(extra);
var header = this.$("div[data-role='header']:visible"),
detail = this.$('#form_detail'),
top = detail.position().top,
viewHeight = $(window).height(),
- contentHeight = viewHeight - header.outerHeight() + 15;
+ contentHeight = viewHeight - header.outerHeight() + 15 - extra;
detail.height( contentHeight - top );
},
@@ -87,8 +102,18 @@
timeout: 30000,
success: function( data, status ) {
if ( data && data.category_extra && data.category_extra.length > 0 ) {
- that.model.set('category_extras', data.category_extra);
- that.navigate('details_extra');
+ // Some categories have only hidden fields - in that case we
+ // don't want to navigate to the details_extra view.
+ var all_hidden = data.category_extra_json.reduce(function(accumulator, field) {
+ return accumulator && (field.automated === "hidden_field");
+ }, true);
+
+ if (all_hidden) {
+ that.navigate( that.next );
+ } else {
+ that.model.set('category_extras', data.category_extra);
+ that.navigate('details_extra');
+ }
} else {
that.navigate( that.next );
}
diff --git a/www/js/views/details_extra.js b/www/js/views/details_extra.js
index 160ff11..e5f63ba 100644
--- a/www/js/views/details_extra.js
+++ b/www/js/views/details_extra.js
@@ -19,15 +19,19 @@
afterRender: function() {
this.populateFields();
+ this.enableScrolling();
},
- onClickButtonPrev: function() {
+ onClickButtonPrev: function(e) {
+ e.preventDefault();
+ this.disableScrolling();
this.model.set('hasExtras', 0);
this.updateCurrentReport();
this.navigate( this.prev, true );
},
onClickButtonNext: function() {
+ this.disableScrolling();
this.clearValidationErrors();
var valid = 1;
var that = this;
@@ -49,6 +53,8 @@
this.clearValidationErrors();
this.updateCurrentReport();
this.navigate( this.next );
+ } else {
+ this.enableScrolling();
}
},
diff --git a/www/js/views/fms.js b/www/js/views/fms.js
index 6ff569b..ae1174f 100644
--- a/www/js/views/fms.js
+++ b/www/js/views/fms.js
@@ -2,7 +2,7 @@
_.extend( FMS, {
FMSView: Backbone.View.extend({
tag: 'div',
- bottomMargin: 20,
+ bottomMargin: 0,
contentSelector: '[data-role="content"]',
events: {
@@ -45,12 +45,21 @@
return this;
},
- fixPageHeight: function() {
+ fixPageHeight: function(extra) {
+ extra = extra || 0;
var header = this.$("div[data-role='header']:visible"),
content = this.$(this.contentSelector),
top = content.position().top,
viewHeight = $(window).height(),
- contentHeight = FMS.windowHeight - header.outerHeight() - this.bottomMargin;
+ contentHeight = FMS.windowHeight - header.outerHeight() - this.bottomMargin - extra;
+
+ if ($("body").hasClass("iphone-x")) {
+ var body = $("body").get(0);
+ var inset = window.getComputedStyle(body).getPropertyValue("--safe-area-inset-bottom");
+ // We want the pixel value, not the CSS string
+ inset = parseInt(inset.replace(/[^\d]*/g, ''));
+ contentHeight -= inset;
+ }
this.setHeight( content, contentHeight - top );
},
@@ -107,7 +116,20 @@
$('.form-error').removeClass('form-error');
},
- destroy: function() { FMS.printDebug('destory for ' + this.id); this._destroy(); this.remove(); },
+ disableScrolling: function() {
+ if ( typeof cordova !== 'undefined' ) {
+ cordova.plugins.Keyboard.disableScroll(true);
+ $('body').scrollTop(0);
+ }
+ },
+
+ enableScrolling: function() {
+ if ( typeof cordova !== 'undefined' ) {
+ cordova.plugins.Keyboard.disableScroll(false);
+ }
+ },
+
+ destroy: function() { FMS.printDebug('destroy for ' + this.id); this._destroy(); this.remove(); },
_destroy: function() {}
})
diff --git a/www/js/views/home.js b/www/js/views/home.js
index 998af1c..d82b874 100644
--- a/www/js/views/home.js
+++ b/www/js/views/home.js
@@ -24,11 +24,14 @@
afterDisplay: function() {
$('#load-screen').hide();
+
if ( FMS.isOffline ) {
this.navigate( 'offline' );
+ } else if ( !FMS.isLoggedIn && CONFIG.LOGIN_REQUIRED ) {
+ this.navigate( 'login' );
} else if ( FMS.currentDraft && (
FMS.currentDraft.get('title') || FMS.currentDraft.get('lat') ||
- FMS.currentDraft.get('details') || FMS.currentDraft.get('file') )
+ FMS.currentDraft.get('details') || FMS.currentDraft.get('files').length > 0 )
) {
this.navigate( 'existing' );
} else {
diff --git a/www/js/views/login.js b/www/js/views/login.js
index c0f16ba..9225c18 100644
--- a/www/js/views/login.js
+++ b/www/js/views/login.js
@@ -40,8 +40,7 @@
that.model.set('name', data.name);
that.model.save();
FMS.isLoggedIn = 1;
- that.$('#password_row').hide();
- that.$('#success_row').show();
+ that.rerender();
} else {
that.validationError('signinForm', FMS.strings.login_details_error);
}
@@ -65,11 +64,7 @@
FMS.isLoggedIn = 0;
that.model.set('password', '');
that.model.save();
- that.$('#form_email').val('');
- that.$('#form_password').val('');
- that.$('#success_row').hide();
- that.$('#signed_in_row').hide();
- that.$('#password_row').show();
+ that.rerender();
},
error: function() {
that.validationError('err', FMS.strings.logout_error);
@@ -83,7 +78,7 @@
if ( !$('#form_password').val() ) {
isValid = 0;
- this.validationError('form_password', FMS.validationStrings.password );
+ this.validationError('form_password', FMS.validationStrings.password.required);
}
var email = $('#form_email').val();
@@ -102,6 +97,23 @@
}
return isValid;
+ },
+
+ beforeDisplay: function() {
+ this.fixPageHeight();
+ if ( !FMS.isLoggedIn && CONFIG.LOGIN_REQUIRED ) {
+ this.$("#reports-next-btn").hide();
+ }
+ },
+
+ rerender: function() {
+ // Simply calling this.render() breaks the DOM in a weird and
+ // interesting way - somehow the main view element is duplicated
+ // instead of replaced and none of the event handlers are
+ // hooked up so you end up with a blank screen.
+ // This is a convenience wrapper around the correct router call
+ // which works around the problem.
+ FMS.router.login();
}
})
});
diff --git a/www/js/views/offline.js b/www/js/views/offline.js
index ac007d1..3ce94a9 100644
--- a/www/js/views/offline.js
+++ b/www/js/views/offline.js
@@ -9,17 +9,18 @@
events: {
'pagehide': 'destroy',
- 'pagebeforeshow': 'beforeShow',
+ 'pagebeforeshow': 'beforeDisplay',
'pageshow': 'afterDisplay',
'vclick .ui-btn-left': 'onClickButtonPrev',
'vclick .ui-btn-right': 'onClickButtonNext',
'vclick #id_photo_button': 'takePhoto',
'vclick #id_existing': 'addPhoto',
- 'vclick #id_del_photo_button': 'deletePhoto',
+ 'vclick .del_photo_button': 'deletePhoto',
'vclick #locate': 'onClickLocate',
'vclick #locate_cancel': 'onClickCancel',
'blur input': 'toggleNextButton',
- 'blur textarea': 'toggleNextButton'
+ 'blur textarea': 'blurTextArea',
+ 'focus textarea': 'focusTextArea'
},
_back: function() {
@@ -30,7 +31,7 @@
var hasContent = false;
if ( $('#form_title').val() || $('#form_detail').val() ||
- this.model.get('lat') || this.model.get('file') ) {
+ this.model.get('lat') || this.model.get('files').length > 0 ) {
hasContent = true;
}
@@ -39,11 +40,22 @@
afterDisplay: function() {
$('body')[0].scrollTop = 0;
- $('div[data-role="content"]').show();
- },
- beforeShow: function() {
- $('div[data-role="content"]').hide();
+ // The height of the photos container needs to be adjusted
+ // depending on the number of photos - if the max number of
+ // photos have already been added then the 'add photo' UI isn't
+ // shown so we should use all the vertical space for the
+ // thumbnails.
+ var wrapperHeight = $(".ui-content").height();
+ wrapperHeight -= $(".ui-content .notopmargin").outerHeight(true);
+ wrapperHeight -= $(".ui-content #locate_result").outerHeight(true);
+ wrapperHeight -= $(".ui-content .inputcard").outerHeight(true);
+ wrapperHeight -= $(".ui-content #add_photo").outerHeight(true);
+ $(".photo-wrapper").height(wrapperHeight);
+ },
+
+ beforeDisplay: function() {
+ this.fixPageHeight();
this.toggleNextButton();
},
@@ -55,6 +67,15 @@
}
},
+ focusTextArea: function() {
+ $("textarea#form_detail").get(0).rows = 7;
+ },
+
+ blurTextArea: function(e) {
+ $("textarea#form_detail").get(0).rows = 2;
+ this.toggleNextButton();
+ },
+
failedLocation: function(details) {
this.finishedLocating();
this.locateCount = 21;
@@ -73,32 +94,47 @@
takePhoto: function() {
var that = this;
+ $.mobile.loading('show');
navigator.camera.getPicture( function(imgURI) { that.addPhotoSuccess(imgURI); }, function(error) { that.addPhotoFail(error); }, { saveToPhotoAlbum: true, quality: 49, destinationType: Camera.DestinationType.FILE_URI, sourceType: navigator.camera.PictureSourceType.CAMERA, correctOrientation: true });
},
addPhoto: function() {
var that = this;
+ $.mobile.loading('show');
navigator.camera.getPicture( function(imgURI) { that.addPhotoSuccess(imgURI); }, function(error) { that.addPhotoFail(error); }, { saveToPhotoAlbum: false, quality: 49, destinationType: Camera.DestinationType.FILE_URI, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY, correctOrientation: true });
},
addPhotoSuccess: function(imgURI) {
- var move = FMS.files.moveURI( imgURI );
+ var move;
+ // on iOS the photos go into a temp folder in the apps own filespace so we
+ // can move them, and indeed have to as the tmp space is cleaned out by the OS
+ // so draft reports might have their images removed. on android you access the
+ // images where they are stored on the filesystem so if you move, and then delete
+ // them, you are moving and deleting the only copy of them which is likely to be
+ // surprising and unwelcome so we copy them instead.
+ var fileName = CONFIG.NAMESPACE + '_' + this.model.cid + '_' + moment().unix() + '.jpg';
+ if ( FMS.isAndroid ) {
+ move = FMS.files.copyURI( imgURI, fileName );
+ } else {
+ move = FMS.files.moveURI( imgURI, fileName );
+ }
var that = this;
move.done( function( file ) {
- $('#photo').attr('src', file.toURL());
- that.model.set('file', file.toURL());
- FMS.saveCurrentDraft();
+ var files = that.model.get('files');
+ files.push(file.toURL());
+ that.model.set('files', files);
+ that.updateCurrentReport();
- $('#photo-next-btn .ui-btn-text').text(FMS.strings.next);
- $('#display_photo').show();
- $('#add_photo').hide();
+ $.mobile.loading('hide');
+ that.rerender();
});
move.fail( function() { that.addPhotoFail(); } );
},
addPhotoFail: function(message) {
+ $.mobile.loading('hide');
if ( message != 'no image selected' &&
message != 'Selection cancelled.' &&
message != 'Camera cancelled.' ) {
@@ -106,18 +142,22 @@
}
},
- deletePhoto: function() {
- var that = this;
- var del = FMS.files.deleteURI( this.model.get('file') );
+ deletePhoto: function(e) {
+ e.preventDefault();
+ $.mobile.loading('show');
+ var files = this.model.get('files');
+ var index = parseInt($(e.target).data('fileIndex'));
+ var deleted_file = files.splice(index, 1)[0];
+ var del = FMS.files.deleteURI( deleted_file );
+
+ var that = this;
del.done( function() {
- that.model.set('file', '');
- FMS.saveCurrentDraft();
- $('#photo').attr('src', '');
+ that.model.set('files', files);
+ that.updateCurrentReport();
- $('#photo-next-btn .ui-btn-text').text(FMS.strings.skip);
- $('#display_photo').hide();
- $('#add_photo').show();
+ $.mobile.loading('hide');
+ that.rerender();
});
},
@@ -154,7 +194,12 @@
this.model.set('title', $('#form_title').val());
this.model.set('details', $('#form_detail').val());
FMS.saveCurrentDraft();
+ },
+
+ rerender: function() {
+ FMS.router.offline();
}
+
})
});
})(FMS, Backbone, _, $);
diff --git a/www/js/views/photo.js b/www/js/views/photo.js
index 485b74c..0b0c5e9 100644
--- a/www/js/views/photo.js
+++ b/www/js/views/photo.js
@@ -14,17 +14,23 @@
'vclick .ui-btn-right': 'onClickButtonNext',
'vclick #id_photo_button': 'takePhoto',
'vclick #id_existing': 'addPhoto',
- 'vclick #id_del_photo_button': 'deletePhoto'
+ 'vclick .del_photo_button': 'deletePhoto'
},
beforeDisplay: function() {
this.fixPageHeight();
- this.$('#id_del_photo_button').hide();
- if ( this.model.get('file') ) {
- $('#id_photo_button').parents('.ui-btn').hide();
- $('#id_existing').parents('.ui-btn').hide();
- window.setTimeout( function() { $('#id_del_photo_button').show(); }, 250 );
- }
+ },
+
+ afterDisplay: function() {
+ // The height of the photos container needs to be adjusted
+ // depending on the number of photos - if the max number of
+ // photos have already been added then the 'add photo' UI isn't
+ // shown so we should use all the vertical space for the
+ // thumbnails.
+ var wrapperHeight = $(".ui-content").height();
+ wrapperHeight -= $(".ui-content h2").outerHeight(true);
+ wrapperHeight -= $(".ui-content .bottom-btn").outerHeight(true)
+ $(".photo-wrapper").height(wrapperHeight);
},
getOptions: function(isFromAlbum) {
@@ -52,7 +58,7 @@
takePhoto: function(e) {
e.preventDefault();
$.mobile.loading('show');
- $('#photo').hide();
+ $('.photo-wrapper .photo img').hide();
var that = this;
var options = this.getOptions();
@@ -63,7 +69,7 @@
addPhoto: function(e) {
e.preventDefault();
$.mobile.loading('show');
- $('#photo').hide();
+ $('.photo-wrapper .photo img').hide();
var that = this;
var options = this.getOptions(true);
navigator.camera.getPicture( function(imgURI) { that.addPhotoSuccess(imgURI); }, function(error) { that.addPhotoFail(error); }, options);
@@ -86,25 +92,19 @@
var that = this;
move.done( function( file ) {
- $('#nophoto_title').hide();
- $('#photo_title').html(FMS.strings.photo_added).show();
- $('#photo').attr('src', file.toURL()).addClass('small').removeClass('placeholder');
- that.model.set('file', file.toURL());
+ var files = that.model.get('files');
+ files.push(file.toURL());
+ that.model.set('files', files);
FMS.saveCurrentDraft();
-
- $('#photo-next-btn .ui-btn-text').text(FMS.strings.next);
- $('#id_photo_button').parents('.ui-btn').hide();
- $('#id_existing').parents('.ui-btn').hide();
- $('#photo').show();
- window.setTimeout(function() { $('#id_del_photo_button').show() }, 500);
- window.setTimeout(function() { $.mobile.loading('hide') }, 100);
+ $.mobile.loading('hide');
+ that.rerender();
});
move.fail( function() { that.addPhotoFail(); } );
},
addPhotoFail: function(message) {
- $('#photo').show();
+ $('.photo-wrapper .photo img').show();
$.mobile.loading('hide');
if ( message != 'no image selected' &&
message != 'Selection cancelled.' &&
@@ -115,22 +115,25 @@
deletePhoto: function(e) {
e.preventDefault();
- var that = this;
- var del = FMS.files.deleteURI( this.model.get('file') );
+ var files = this.model.get('files');
+ var index = parseInt($(e.target).data('fileIndex'));
+ var deleted_file = files.splice(index, 1)[0];
+ var del = FMS.files.deleteURI( deleted_file );
+
+ var that = this;
del.done( function() {
- $('#photo_title').hide();
- $('#nophoto_title').show();
- $('#id_del_photo_button').hide();
- that.model.set('file', '');
+ that.model.set('files', files);
FMS.saveCurrentDraft(true);
- $('#photo').attr('src', 'images/placeholder-photo.png').addClass('placeholder').removeClass('small');
-
- $('#photo-next-btn .ui-btn-text').text(FMS.strings.skip);
- $('#id_photo_button').parents('.ui-btn').show();
- $('#id_existing').parents('.ui-btn').show();
+ that.rerender();
});
+ },
+ rerender: function() {
+ // Simply calling this.render() breaks the DOM in a weird and
+ // interesting way, so this is a convenience wrapper around
+ // the correct router call.
+ FMS.router.photo();
}
})
});
diff --git a/www/js/views/submit.js b/www/js/views/submit.js
index 6a7c946..4a92fe3 100644
--- a/www/js/views/submit.js
+++ b/www/js/views/submit.js
@@ -86,7 +86,7 @@
if ( !this._handleInvalid( model, err, options ) ) {
var errors = err.errors;
var errorList = '<ul><li class="plain">' + FMS.strings.invalid_report + '</li>';
- var validErrors = [ 'password', 'category', 'name' ];
+ var validErrors = [ 'password', 'password_register', 'category', 'name' ];
for ( var k in errors ) {
if ( validErrors.indexOf(k) >= 0 || errors[k].match(/required/) ) {
if ( k === 'password' ) {
@@ -128,6 +128,22 @@
}
},
+ validateUserTitle: function() {
+ if ( this.model.get('titles_list') && this.model.get('titles_list').length > 0 ) {
+ if ( $('#form_title').val() === '' ) {
+ this.validationError('form_title', FMS.strings.required);
+ return false;
+ }
+ }
+ return true;
+ },
+
+ setUserTitle: function() {
+ if ( this.model.get('titles_list') && this.model.get('titles_list').length > 0 ) {
+ FMS.currentUser.set('title', $('#form_title').val());
+ }
+ },
+
beforeSubmit: function() {},
afterSubmit: function() {},
@@ -145,7 +161,8 @@
(function (FMS, Backbone, _, $) {
_.extend( FMS, {
SubmitInitialPageView: FMS.SubmitView.extend({
- onClickButtonPrev: function() {
+ onClickButtonPrev: function(e) {
+ e.preventDefault();
if ( this.model.get('hasExtras') == 1 ) {
this.navigate( 'details_extra', true );
} else {
@@ -264,11 +281,8 @@
}
}
- if ( this.model.get('titles_list') && this.model.get('titles_list').length > 0 ) {
- if ( $('#form_title').val() === '' ) {
- this.validationError('form_title', FMS.strings.required);
- isValid = 0;
- }
+ if (!this.validateUserTitle()) {
+ isValid = 0;
}
return isValid;
@@ -282,10 +296,7 @@
this.model.set('may_show_name', $('#form_may_show_name').is(':checked'));
FMS.currentUser.set('name', $('#form_name').val());
FMS.currentUser.set('may_show_name', $('#form_may_show_name').is(':checked'));
-
- if ( this.model.get('titles_list') && this.model.get('titles_list').length > 0 ) {
- FMS.currentUser.set('title', $('#form_title').val());
- }
+ this.setUserTitle();
if ( FMS.currentUser ) {
FMS.currentUser.save();
@@ -329,20 +340,21 @@
},
validate: function() {
+ this.clearValidationErrors();
var isValid = 1;
if ( !$('#form_password').val() ) {
isValid = 0;
- this.validationError('form_password', FMS.validationStrings.password );
+ this.validationError('form_password', FMS.validationStrings.password.required );
+ } else if ( CONFIG.PASSWORD_MIN_LENGTH && $('#form_password').val().length < CONFIG.PASSWORD_MIN_LENGTH ) {
+ isValid = 0;
+ var msg = FMS.validationStrings.password.short.replace('%d', CONFIG.PASSWORD_MIN_LENGTH);
+ this.validationError('form_password', msg);
}
- if ( $('#form_name').val() && this.model.get('titles_list') && this.model.get('titles_list').length > 0 ) {
- if ( $('#form_title').val() === '' ) {
- this.validationError('form_title', FMS.strings.required);
- isValid = 0;
- }
+ if ($('#form_name').val() && !this.validateUserTitle()) {
+ isValid = 0;
}
-
return isValid;
},
@@ -357,9 +369,7 @@
this.model.set('may_show_name', $('#form_may_show_name').is(':checked'));
FMS.currentUser.set('name', $('#form_name').val());
FMS.currentUser.set('may_show_name', $('#form_may_show_name').is(':checked'));
- if ( this.model.get('titles_list') && this.model.get('titles_list').length > 0 ) {
- FMS.currentUser.set('title', $('#form_title').val());
- }
+ this.setUserTitle();
FMS.currentUser.save();
} else {
// if this is set then we are registering a password
@@ -408,14 +418,43 @@
onClickContinue: function(e) {
e.preventDefault();
- if ( this.validate() ) {
- $('#continue').focus();
- if ( ! this.model.get('submit_clicked') ) {
- this.model.set('submit_clicked', 'submit_sign_in');
+ if (this.validate()) {
+ // The password may be long enough, but is it going to be
+ // accepted by the server? Check before proceeding.
+ if (CONFIG.PASSWORD_CHECK_COMMON) {
+ var that = this;
+ $.post(
+ CONFIG.FMS_URL + "/auth/common_password",
+ { password_register: $('#form_password').val() },
+ null,
+ 'json'
+ )
+ .done(function(result) {
+ if (result === true) {
+ that.savePasswordAndContinue();
+ } else {
+ that.validationError('form_password', result);
+ }
+ })
+ .fail(function() {
+ // If this failed for whatever reason (e.g. network
+ // error etc), don't worry about it as it'll be
+ // resubmitted with the report.
+ that.savePasswordAndContinue();
+ });
+ } else {
+ this.savePasswordAndContinue();
}
- FMS.currentUser.set('password', $('#form_password').val());
- this.navigate( this.next );
}
+ },
+
+ savePasswordAndContinue: function() {
+ $('#continue').focus();
+ if ( ! this.model.get('submit_clicked') ) {
+ this.model.set('submit_clicked', 'submit_sign_in');
+ }
+ FMS.currentUser.set('password', $('#form_password').val());
+ this.navigate( this.next );
}
})
});
@@ -462,18 +501,33 @@
this.model.set('submit_clicked', 'submit_register');
FMS.currentUser.set('name', $('#form_name').val());
FMS.currentUser.set('may_show_name', $('#form_may_show_name').is(':checked'));
+ this.setUserTitle();
},
onReportError: function(model, err, options) {
// TODO: this is a temporary measure which should be replaced by a more
// sensible login mechanism
if ( err.check_name ) {
- this.onClickSubmit();
+ this.doSubmit();
} else {
if ( err.errors && err.errors.password ) {
this.validationError('form_password', err.errors.password );
}
}
+ },
+
+ afterRender: function() {
+ console.log("SubmitConfirmView.afterRender");
+ if (CONFIG.SKIP_CONFIRM_REPORT) {
+ var that = this;
+ setTimeout(function() {
+ // This needs to be in a setTimeout call otherwise
+ // the app gets stuck on an empty "Your Details" page.
+ // This is something to do with the way Backbone routes
+ // between views, I believe.
+ that.doSubmit();
+ }, 10);
+ }
}
})
});
diff --git a/www/templates/en/around.html b/www/templates/en/around.html
index 7c64fe5..8328a95 100644
--- a/www/templates/en/around.html
+++ b/www/templates/en/around.html
@@ -33,6 +33,7 @@
<% } %>
</form>
<a data-role="none" id="relocate" class="nodisplay"></a>
+ <a data-role="none" id="hidepins" class="nodisplay"></a>
<div class="nodisplay" id="front-howto"></div>
</div>
diff --git a/www/templates/en/details_extra.html b/www/templates/en/details_extra.html
index 339cc9d..c4390b4 100644
--- a/www/templates/en/details_extra.html
+++ b/www/templates/en/details_extra.html
@@ -1,7 +1,11 @@
<div data-role="header" data-position="fixed">
<a data-rel="back" data-icon="arrow-l" class="ui-btn-left">Back</a>
<h1>Further Details</h1>
- <a id="next" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Next</a>
+ <% if (CONFIG.SKIP_CONFIRM_REPORT) { %>
+ <a id="next" class="ui-btn-right">Submit</a>
+ <% } else { %>
+ <a id="next" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Next</a>
+ <% } %>
</div>
<div data-role="content" data-enhance="false">
<%= category_extras %>
diff --git a/www/templates/en/existing.html b/www/templates/en/existing.html
index 5e27785..c0a90ec 100644
--- a/www/templates/en/existing.html
+++ b/www/templates/en/existing.html
@@ -17,8 +17,8 @@
<p><% print( moment( created ).fromNow() ) %></p>
</div>
- <% if ( file ) { %>
- <div class="photo" style="background-image: url(<%= file %>)"></div>
+ <% if ( files.length > 0 ) { %>
+ <div class="photo" style="background-image: url(<%= files[0] %>)"></div>
<% } %>
<% if ( details ) { %>
diff --git a/www/templates/en/help.html b/www/templates/en/help.html
index 3722544..2917c67 100644
--- a/www/templates/en/help.html
+++ b/www/templates/en/help.html
@@ -40,7 +40,7 @@
<dt>Is it free?</dt>
<dd>The site and app are free to use, yes. <% print( CONFIG.APP_NAME ) %> is run
by a registered charity, though, so if you want to make a contribution, <a
- onclick="FMS.openExternal(event); return false;" href="https://secure.mysociety.org/donate/">please do</a>.
+ onclick="FMS.openExternal(event); return false;" href="https://www.mysociety.org/donate/">please do</a>.
For more information see the <a onclick="FMS.openExternal(event); return false;" href="http://www.fixmystreet.com/faq/">website</a>.
</dd>
diff --git a/www/templates/en/login.html b/www/templates/en/login.html
index 13944e8..bbe6267 100644
--- a/www/templates/en/login.html
+++ b/www/templates/en/login.html
@@ -12,13 +12,9 @@
<input type="button" id="logout" name="logout" value="Sign Out" data-theme="a">
</div>
</div>
- <div id="password_row" class="nodisplay">
- <p class="notopmargin">
- Signed out!
- </p>
<% } else { %>
<div id="password_row">
- <% } %>
+ <p class="notopmargin">You are not signed in.</p>
<form name="signinForm" class="inputcard" id="signinForm">
<div>
<input data-role="none" type="email" value="" name="email" id="form_email" placeholder="Your Email" required>
@@ -31,13 +27,5 @@
</div>
</form>
</div>
- <div id="success_row" class="nodisplay">
- <p class="notopmargin">
- Signed in!
- </p>
- <div id="err" class="nodisplay"></div>
- <div class="bottom-btn">
- <input type="button" id="logout" name="logout" value="Sign Out" data-theme="a">
- </div>
- </div>
+ <% } %>
</div>
diff --git a/www/templates/en/offline.html b/www/templates/en/offline.html
index 10e87d9..4fde64f 100644
--- a/www/templates/en/offline.html
+++ b/www/templates/en/offline.html
@@ -1,7 +1,7 @@
<div data-role="header" data-position="fixed">
<a id="offline-prev-btn" class="ui-btn-left">Try Again</a>
<h1>Offline</h1>
- <a id="offline-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Skip</a>
+ <a id="offline-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right"><%= files.length == 0 ? "Skip" : "Next" %></a>
</div>
<div id="locating" class="nodisplay">
<div class="radar"></div>
@@ -42,30 +42,25 @@
</div>
<div>
- <textarea data-role="none" rows="7" cols="26" name="detail" id="form_detail" placeholder="Please fill in details of the problem." required><%= details %></textarea>
+ <textarea data-role="none" rows="2" cols="26" name="detail" id="form_detail" placeholder="Please fill in details of the problem." required><%= details %></textarea>
</div>
</div>
- <% if ( file != '' ) { %>
- <div id="add_photo" style="display: none">
- <% } else { %>
- <div id="add_photo">
+ <% if ( files.length < CONFIG.MAX_PHOTOS ) { %>
+ <div id="add_photo">
+ <input data-icon="fms-photo-new" value="Take a new photo" type="button" name="photo_button" id="id_photo_button" data-role="button" data-theme="a">
+ <input data-icon="fms-photo-existing" value="Add an existing photo" type="button" name="existing" id="id_existing" data-role="button" data-theme="c">
+ </div>
<% } %>
- <label>Add a Photo <em>(optional)</em></label>
- <input data-icon="fms-photo-new" value="Take a new photo" type="button" name="photo_button" id="id_photo_button" data-role="button" data-theme="a">
- <input data-icon="fms-photo-existing" value="Add an existing photo" type="button" name="existing" id="id_existing" data-role="button" data-theme="c">
- </div>
- <% if ( file == '' ) { %>
- <div id="display_photo" style="display: none">
- <% } else { %>
- <div id="display_photo">
- <% } %>
- <label>Your Photo</label>
- <div class="photo">
- <img class="small" id="photo" src="<%= file %>" />
+ <% if ( files.length > 0 ) { %>
+ <div class="photo-wrapper">
+ <% _.each(files, function(file, index) { %>
+ <div class="photo" style="background-image: url('<%= file %>');">
+ <a data-role="none" class="photo-corner-button del_photo_button" data-file-index="<%= index %>">X</a>
+ </div>
+ <% }); %>
</div>
- <input value="Remove Photo" type="button" name="del_photo_button" id="id_del_photo_button" data-role="button" data-theme="a">
- </div>
+ <% } %>
</div>
</div>
diff --git a/www/templates/en/photo.html b/www/templates/en/photo.html
index 8dac456..3221192 100644
--- a/www/templates/en/photo.html
+++ b/www/templates/en/photo.html
@@ -1,37 +1,49 @@
<div data-role="header">
<a data-rel="back" data-icon="arrow-l" class="ui-btn-left">Back</a>
- <h1>Add Photo</h1>
- <% if ( file == '' ) { %>
- <a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Skip</a>
+ <h1>Add Photos</h1>
+ <% if ( files.length == 0 ) { %>
+ <% if ( !CONFIG.PHOTO_REQUIRED ) { %>
+ <a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Skip</a>
+ <% } %>
<% } else { %>
<a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Next</a>
<% } %>
</div>
+
<div data-role="content">
- <% var photoClass = 'nodisplay', nophotoClass = 'nodisplay';
- if ( file != '' ) {
- photoClass = '';
- } else {
- nophotoClass = '';
- } %>
- <h2 id="nophoto_title" class="<% print( nophotoClass ); %>">
- Add a Photo <em>(optional)</em>
- </h2>
- <h2 id="photo_title" class="<% print( photoClass ); %>">
- Photo for report
- </h2>
- <div class="photo-wrapper">
- <div class="photo">
- <% if ( file == '' ) { %>
- <img class="placeholder" src="images/placeholder-photo.png" alt="" id="photo">
+ <% if ( files.length == 0 ) { %>
+ <h2 id="nophoto_title">
+ Add a Photo
+ <% if ( !CONFIG.PHOTO_REQUIRED ) { %>
+ <em>(optional)</em>
+ <% } else if ( files.length == 0) { %>
+ <em>(required)</em>
+ <%} %>
+ </h2>
<% } else { %>
- <img class="small" id="photo" src="<%= file %>" />
+ <h2 id="photo_title">
+ Photos for report
+ </h2>
<% } %>
- <a data-role="none" id="id_del_photo_button" class="photo-corner-button">X</a>
- </div>
- </div>
- <div class="bottom-btn">
- <input data-icon="fms-photo-existing" type="button" id="id_existing" data-theme="c" value="Add an existing photo" >
- <input data-icon="fms-photo-new" id="id_photo_button" type="button" data-theme="a" value="Take a new photo">
+
+ <div class="photo-wrapper">
+ <% if ( files.length == 0 ) { %>
+ <div class="photo">
+ <img class="placeholder" src="images/placeholder-photo.png" alt="">
+ </div>
+ <% } else { %>
+ <% _.each(files, function(file, index) { %>
+ <div class="photo" style="background-image: url('<%= file %>');">
+ <a data-role="none" class="photo-corner-button del_photo_button" data-file-index="<%= index %>">X</a>
+ </div>
+ <% });%>
+ <% } %>
</div>
+
+ <% if ( files.length < CONFIG.MAX_PHOTOS ) { %>
+ <div class="bottom-btn">
+ <input data-icon="fms-photo-existing" type="button" id="id_existing" data-theme="c" value="Add an existing photo" >
+ <input data-icon="fms-photo-new" id="id_photo_button" type="button" data-theme="a" value="Take a new photo">
+ </div>
+ <% } %>
</div>
diff --git a/www/templates/en/reports.html b/www/templates/en/reports.html
index 047fa76..e04f5f6 100644
--- a/www/templates/en/reports.html
+++ b/www/templates/en/reports.html
@@ -15,7 +15,7 @@
if ( draft.get('lat') ) {
classes.push('with_location');
}
- if ( draft.get('file') ) {
+ if ( draft.get('files').length > 0 ) {
classes.push('with_photo');
}
var draftClass = '';
diff --git a/www/templates/en/submit_confirm.html b/www/templates/en/submit_confirm.html
index 5d2e6a0..f41e71c 100644
--- a/www/templates/en/submit_confirm.html
+++ b/www/templates/en/submit_confirm.html
@@ -3,7 +3,7 @@
<h1>Your details</h1>
</div>
-<div data-role="content">
+<div data-role="content"<% if (CONFIG.SKIP_CONFIRM_REPORT) { %> class="hidden"<% } %>>
<p class="notopmargin">
You are logged in as <%= user.email %>.
</p>
diff --git a/www/templates/en/submit_set_password.html b/www/templates/en/submit_set_password.html
index 1a24eae..75baf7a 100644
--- a/www/templates/en/submit_set_password.html
+++ b/www/templates/en/submit_set_password.html
@@ -12,7 +12,7 @@
</p>
<div class="inputcard">
<div>
- <input data-role="none" type="password" value="" name="password" id="form_password" placeholder="Your password" required>
+ <input data-role="none" type="password" value="<%= FMS.currentUser.get('password') %>" name="password" id="form_password" placeholder="Your password" required>
</div>
</div>
<div class="noborder">
diff --git a/www/templates/es/around.html b/www/templates/es/around.html
index 8686933..5f47ed4 100644
--- a/www/templates/es/around.html
+++ b/www/templates/es/around.html
@@ -33,6 +33,7 @@
<% } %>
</form>
<a data-role="none" id="relocate" class="nodisplay"></a>
+ <a data-role="none" id="hidepins" class="nodisplay"></a>
<div class="nodisplay" id="front-howto"></div>
</div>
diff --git a/www/templates/es/details_extra.html b/www/templates/es/details_extra.html
index 2d782c8..0f302fe 100644
--- a/www/templates/es/details_extra.html
+++ b/www/templates/es/details_extra.html
@@ -1,7 +1,11 @@
<div data-role="header" data-position="fixed">
<a data-rel="back" data-icon="arrow-l" class="ui-btn-left">Atrás</a>
<h1>Detalles adicionales</h1>
- <a id="next" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Siguiente</a>
+ <% if (CONFIG.SKIP_CONFIRM_REPORT) { %>
+ <a id="next" class="ui-btn-right">Enviar</a>
+ <% } else { %>
+ <a id="next" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Siguiente</a>
+ <% } %>
</div>
<div data-role="content" data-enhance="false">
<%= category_extras %>
diff --git a/www/templates/es/existing.html b/www/templates/es/existing.html
index b45b3d8..baecd89 100644
--- a/www/templates/es/existing.html
+++ b/www/templates/es/existing.html
@@ -17,8 +17,8 @@
<p><% print( moment( created ).fromNow() ) %></p>
</div>
- <% if ( file ) { %>
- <div class="photo" style="background-image: url(<%= file %>)"></div>
+ <% if ( files.length > 0 ) { %>
+ <div class="photo" style="background-image: url(<%= files[0] %>)"></div>
<% } %>
<% if ( details ) { %>
diff --git a/www/templates/es/login.html b/www/templates/es/login.html
index 4dff7a6..3fcaa99 100644
--- a/www/templates/es/login.html
+++ b/www/templates/es/login.html
@@ -12,13 +12,9 @@
<input type="button" id="logout" name="logout" value="Cerrar sesión" data-theme="a">
</div>
</div>
- <div id="password_row" class="nodisplay">
- <p class="notopmargin">
- ¡Sesión cerrada!
- </p>
<% } else { %>
<div id="password_row">
- <% } %>
+ <p class="notopmargin">You are not signed in.</p>
<form name="signinForm" class="inputcard" id="signinForm">
<div>
<input data-role="none" type="email" value="" name="email" id="form_email" placeholder="Su email" required>
@@ -31,13 +27,5 @@
</div>
</form>
</div>
- <div id="success_row" class="nodisplay">
- <p class="notopmargin">
- ¡Sesión abierta!
- </p>
- <div id="err" class="nodisplay"></div>
- <div class="bottom-btn">
- <input type="button" id="logout" name="logout" value="Cerrar sesión" data-theme="a">
- </div>
- </div>
+ <% } %>
</div>
diff --git a/www/templates/es/offline.html b/www/templates/es/offline.html
index 1051f57..35190df 100644
--- a/www/templates/es/offline.html
+++ b/www/templates/es/offline.html
@@ -1,7 +1,7 @@
<div data-role="header" data-position="fixed">
<a id="offline-prev-btn" class="ui-btn-left">Inténtelo nuevamente</a>
<h1>Sin conexión</h1>
- <a id="offline-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Saltar</a>
+ <a id="offline-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right"><%= files.length == 0 ? "Saltar" : "Siguiente" %></a>
</div>
<div id="locating" class="nodisplay">
<div class="radar"></div>
@@ -42,30 +42,25 @@
</div>
<div>
- <textarea data-role="none" rows="7" cols="26" name="detail" id="form_detail" placeholder="Please fill in details of the problem." required><%= details %></textarea>
+ <textarea data-role="none" rows="2" cols="26" name="detail" id="form_detail" placeholder="Please fill in details of the problem." required><%= details %></textarea>
</div>
</div>
- <% if ( file != '' ) { %>
- <div id="add_photo" style="display: none">
- <% } else { %>
- <div id="add_photo">
+ <% if ( files.length < CONFIG.MAX_PHOTOS ) { %>
+ <div id="add_photo">
+ <input data-icon="fms-photo-new" value="Tomar una nueva foto" type="button" name="photo_button" id="id_photo_button" data-role="button" data-theme="a">
+ <input data-icon="fms-photo-existing" value="Añadir una foto existente" type="button" name="existing" id="id_existing" data-role="button" data-theme="c">
+ </div>
<% } %>
- <label>Añadir una foto <em>(opcional)</em></label>
- <input data-icon="fms-photo-new" value="Tomar una nueva foto" type="button" name="photo_button" id="id_photo_button" data-role="button" data-theme="a">
- <input data-icon="fms-photo-existing" value="Añadir una foto existente" type="button" name="existing" id="id_existing" data-role="button" data-theme="c">
- </div>
- <% if ( file == '' ) { %>
- <div id="display_photo" style="display: none">
- <% } else { %>
- <div id="display_photo">
- <% } %>
- <label>Su foto</label>
- <div class="photo">
- <img class="small" id="photo" src="<%= file %>" />
+ <% if ( files.length > 0 ) { %>
+ <div class="photo-wrapper">
+ <% _.each(files, function(file, index) { %>
+ <div class="photo" style="background-image: url('<%= file %>');">
+ <a data-role="none" class="photo-corner-button del_photo_button" data-file-index="<%= index %>">X</a>
+ </div>
+ <% }); %>
</div>
- <input value="Eliminar foto" type="button" name="del_photo_button" id="id_del_photo_button" data-role="button" data-theme="a">
- </div>
+ <% } %>
</div>
</div>
diff --git a/www/templates/es/photo.html b/www/templates/es/photo.html
index 62f36dc..75de686 100644
--- a/www/templates/es/photo.html
+++ b/www/templates/es/photo.html
@@ -1,37 +1,49 @@
<div data-role="header">
<a data-rel="back" data-icon="arrow-l" class="ui-btn-left">Atrás</a>
- <h1>Añadir foto</h1>
- <% if ( file == '' ) { %>
- <a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Saltar</a>
+ <h1>Add Photos</h1>
+ <% if ( files.length == 0 ) { %>
+ <% if ( !CONFIG.PHOTO_REQUIRED ) { %>
+ <a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Saltar</a>
+ <% } %>
<% } else { %>
<a id="photo-next-btn" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Siguiente</a>
<% } %>
</div>
+
<div data-role="content">
- <% var photoClass = 'nodisplay', nophotoClass = 'nodisplay';
- if ( file != '' ) {
- photoClass = '';
- } else {
- nophotoClass = '';
- } %>
- <h2 id="nophoto_title" class="<% print( nophotoClass ); %>">
- Añadir una foto <em>(opcional)</em>
- </h2>
- <h2 id="photo_title" class="<% print( photoClass ); %>">
- Foto para el informe
- </h2>
- <div class="photo-wrapper">
- <div class="photo">
- <% if ( file == '' ) { %>
- <img class="placeholder" src="images/placeholder-photo.png" alt="" id="photo">
+ <% if ( files.length == 0 ) { %>
+ <h2 id="nophoto_title">
+ Añadir una foto
+ <% if ( !CONFIG.PHOTO_REQUIRED ) { %>
+ <em>(opcional)</em>
+ <% } else if ( files.length == 0) { %>
+ <em>(required)</em>
+ <%} %>
+ </h2>
<% } else { %>
- <img class="small" id="photo" src="<%= file %>" />
+ <h2 id="photo_title">
+ Photos for report
+ </h2>
<% } %>
- <a data-role="none" id="id_del_photo_button" class="photo-corner-button">X</a>
- </div>
- </div>
- <div class="bottom-btn">
- <input data-icon="fms-photo-existing" type="button" id="id_existing" data-theme="c" value="Añadir una foto existente" >
- <input data-icon="fms-photo-new" id="id_photo_button" type="button" data-theme="a" value="Tomar una nueva foto">
+
+ <div class="photo-wrapper">
+ <% if ( files.length == 0 ) { %>
+ <div class="photo">
+ <img class="placeholder" src="images/placeholder-photo.png" alt="">
+ </div>
+ <% } else { %>
+ <% _.each(files, function(file, index) { %>
+ <div class="photo" style="background-image: url('<%= file %>');">
+ <a data-role="none" class="photo-corner-button del_photo_button" data-file-index="<%= index %>">X</a>
+ </div>
+ <% });%>
+ <% } %>
</div>
+
+ <% if ( files.length < CONFIG.MAX_PHOTOS ) { %>
+ <div class="bottom-btn">
+ <input data-icon="fms-photo-existing" type="button" id="id_existing" data-theme="c" value="Añadir una foto existente" >
+ <input data-icon="fms-photo-new" id="id_photo_button" type="button" data-theme="a" value="Tomar una nueva foto">
+ </div>
+ <% } %>
</div>
diff --git a/www/templates/es/reports.html b/www/templates/es/reports.html
index cbd2acf..05772a5 100644
--- a/www/templates/es/reports.html
+++ b/www/templates/es/reports.html
@@ -15,7 +15,7 @@
if ( draft.get('lat') ) {
classes.push('with_location');
}
- if ( draft.get('file') ) {
+ if ( draft.get('files').length > 0 ) {
classes.push('with_photo');
}
var draftClass = '';
diff --git a/www/templates/es/submit_confirm.html b/www/templates/es/submit_confirm.html
index a9dd90a..224195b 100644
--- a/www/templates/es/submit_confirm.html
+++ b/www/templates/es/submit_confirm.html
@@ -3,7 +3,7 @@
<h1>Sus detalles</h1>
</div>
-<div data-role="content">
+<div data-role="content"<% if (CONFIG.SKIP_CONFIRM_REPORT) { %> class="hidden"<% } %>>
<p class="notopmargin">
Estas registrado como <%= user.email %>.
</p>
diff --git a/www/templates/es/submit_set_password.html b/www/templates/es/submit_set_password.html
index a9d9b46..39403cb 100644
--- a/www/templates/es/submit_set_password.html
+++ b/www/templates/es/submit_set_password.html
@@ -12,7 +12,7 @@
</p>
<div class="inputcard">
<div>
- <input data-role="none" type="password" value="" name="password" id="form_password" placeholder="Su contraseña" required>
+ <input data-role="none" type="password" value="<%= FMS.currentUser.get('password') %>" name="password" id="form_password" placeholder="Su contraseña" required>
</div>
</div>
<div class="noborder">