[gnome-maps/wip/osm-edit: 7/16] osmEdit: Implement OSM account dialog
- From: Marcus Lundblad <mlundblad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-maps/wip/osm-edit: 7/16] osmEdit: Implement OSM account dialog
- Date: Mon, 7 Dec 2015 21:46:53 +0000 (UTC)
commit 414519a40cc961204f6d4e88de0a6b0f73872a6e
Author: Marcus Lundblad <ml update uu se>
Date: Sat Nov 7 12:17:07 2015 +0100
osmEdit: Implement OSM account dialog
https://bugzilla.gnome.org/show_bug.cgi?id=726628
data/org.gnome.Maps.data.gresource.xml | 1 +
data/ui/app-menu.ui | 6 +
data/ui/osm-account-dialog.ui | 326 ++++++++++++++++++++++++++++++++
src/application.js | 7 +
src/org.gnome.Maps.src.gresource.xml | 1 +
src/osmAccountDialog.js | 168 ++++++++++++++++
src/osmEdit.js | 7 +
7 files changed, 516 insertions(+), 0 deletions(-)
---
diff --git a/data/org.gnome.Maps.data.gresource.xml b/data/org.gnome.Maps.data.gresource.xml
index ba2c976..225c61a 100644
--- a/data/org.gnome.Maps.data.gresource.xml
+++ b/data/org.gnome.Maps.data.gresource.xml
@@ -14,6 +14,7 @@
<file preprocess="xml-stripblanks">ui/main-window.ui</file>
<file preprocess="xml-stripblanks">ui/map-bubble.ui</file>
<file preprocess="xml-stripblanks">ui/notification.ui</file>
+ <file preprocess="xml-stripblanks">ui/osm-account-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/osm-edit-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/place-bubble.ui</file>
<file preprocess="xml-stripblanks">ui/place-entry.ui</file>
diff --git a/data/ui/app-menu.ui b/data/ui/app-menu.ui
index a40eb08..1dd897e 100644
--- a/data/ui/app-menu.ui
+++ b/data/ui/app-menu.ui
@@ -3,6 +3,12 @@
<menu id="app-menu">
<section>
<item>
+ <attribute name="action">app.osm-account-setup</attribute>
+ <attribute name="label" translatable="yes">Setup OpenStreetMap Account</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
<attribute name="action">win.about</attribute>
<attribute name="label" translatable="yes">About</attribute>
</item>
diff --git a/data/ui/osm-account-dialog.ui b/data/ui/osm-account-dialog.ui
new file mode 100644
index 0000000..48a7f51
--- /dev/null
+++ b/data/ui/osm-account-dialog.ui
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <template class="Gjs_OSMAccountDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="type">popup</property>
+ <property name="type_hint">dialog</property>
+ <property name="width_request">500</property>
+ <property name="title" translatable="yes">OpenStreetMap Account</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="contentArea">
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="row-spacing">10</property>
+ <property name="margin">20</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes"><span weight="bold" size="x-large">Sign
in to edit maps</span></property>
+ <property name="use_markup">True</property>
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Help to improve the map, using an
+OpenStreetMap account.</property>
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="column-spacing">10</property>
+ <property name="row-spacing">10</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Email</property>
+ <property name="halign">GTK_ALIGN_END</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="emailEntry">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Password</property>
+ <property name="halign">GTK_ALIGN_END</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="passwordEntry">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="input-purpose">GTK_INPUT_PURPOSE_PASSWORD</property>
+ <property name="visibility">False</property>
+ <property name="caps-lock-warning">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="signInSpinner">
+ <property name="visible">False</property>
+ <property name="height_request">16</property>
+ <property name="width_request">16</property>
+ <property name="can_focus">False</property>
+ <property name="active">True</property>
+ <property name="halign">GTK_ALIGN_END</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="signInButton">
+ <property name="visible">True</property>
+ <property name="halign">GTK_ALIGN_END</property>
+ <property name="label" translatable="yes">Sign In</property>
+ <property name="sensitive">False</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="signUpLinkButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Don't have an account?</property>
+ <property name="uri">https://www.openstreetmap.org/user/new?referer=gnome-maps</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="resetPasswordLabel">
+ <property name="visible">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes"
+ comments="The label should contain the link to the OSM reset password page with a
translated title">Sorry, that didn't work. Please try again, or visit
+<a href="https://www.openstreetmap.org/user/forgot-password">OpenStreetMap</a> to reset your
password.</property>
+ <property name="use-markup">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="verificationFailedLabel">
+ <property name="visible">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">The verification code didn't match, please try
again.</property>
+ <property name="use-markup">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">sign-in</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="verifyGrid">
+ <property name="visible">True</property>
+ <property name="row-spacing">10</property>
+ <property name="margin">20</property>
+ <child>
+ <object class="WebKitWebView" id="verifyView">
+ <property name="visible">True</property>
+ <property name="halign">GTK_ALIGN_FILL</property>
+ <property name="self-scrolling">True</property>
+ <property name="height-request">250</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="column-spacing">10</property>
+ <property name="row-spacing">10</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Enter verification code shown
above</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="verificationEntry">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="verifyButton">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">Verify</property>
+ <property name="hexpand">False</property>
+ <property name="halign">GTK_ALIGN_END</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">verify</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="row-spacing">10</property>
+ <property name="margin">20</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes"><span weight="bold"
size="x-large">Signed In</span></property>
+ <property name="use_markup">True</property>
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Your OpenStreetMap account is
active.</property>
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">avatar-default-symbolic</property>
+ <property name="pixel-size">64</property>
+ <property name="opacity">0.33</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="signedInUserLabel">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="signOutButton">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Sign Out</property>
+ <property name="halign">GTK_ALIGN_CENTER</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">logged-in</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/application.js b/src/application.js
index d21826d..552d60b 100644
--- a/src/application.js
+++ b/src/application.js
@@ -149,6 +149,10 @@ const Application = new Lang.Class({
this._mainWindow.destroy();
},
+ _onOsmAccountSetupActivate: function() {
+ osmEdit.showAccountDialog(this._mainWindow);
+ },
+
_addContacts: function() {
contactStore.get_contacts().forEach(function(contact) {
contact.geocode(function() {
@@ -207,6 +211,9 @@ const Application = new Lang.Class({
'show-contact': {
paramType: 's',
onActivate: this._onShowContactActivate.bind(this)
+ },
+ 'osm-account-setup': {
+ onActivate: this._onOsmAccountSetupActivate.bind(this)
}
});
diff --git a/src/org.gnome.Maps.src.gresource.xml b/src/org.gnome.Maps.src.gresource.xml
index f375ccf..7d44555 100644
--- a/src/org.gnome.Maps.src.gresource.xml
+++ b/src/org.gnome.Maps.src.gresource.xml
@@ -29,6 +29,7 @@
<file>mapWalker.js</file>
<file>notification.js</file>
<file>notificationManager.js</file>
+ <file>osmAccountDialog.js</file>
<file>osmConnection.js</file>
<file>osmEdit.js</file>
<file>osmEditDialog.js</file>
diff --git a/src/osmAccountDialog.js b/src/osmAccountDialog.js
new file mode 100644
index 0000000..1a97867
--- /dev/null
+++ b/src/osmAccountDialog.js
@@ -0,0 +1,168 @@
+/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
+/* vim: set et ts=4 sw=4: */
+/*
+ * Copyright (c) 2015 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const WebKit = imports.gi.WebKit;
+
+const Application = imports.application;
+
+const OSMAccountDialog = new Lang.Class({
+ Name: 'OSMAccountDialog',
+ Extends: Gtk.Dialog,
+ Template: 'resource:///org/gnome/Maps/ui/osm-account-dialog.ui',
+ InternalChildren: ['stack',
+ 'emailEntry',
+ 'passwordEntry',
+ 'signInButton',
+ 'signInSpinner',
+ 'signUpLinkButton',
+ 'resetPasswordLabel',
+ 'verifyView',
+ 'verificationEntry',
+ 'verifyButton',
+ 'verificationFailedLabel',
+ 'signedInUserLabel',
+ 'signOutButton'],
+
+ _init: function(params) {
+ /* This is a construct-only property and cannot be set by GtkBuilder */
+ params.use_header_bar = true;
+ GObject.type_ensure(WebKit.WebView);
+
+ this.parent(params);
+
+ this._emailEntry.connect('changed',
+ this._onCredentialsChanged.bind(this));
+ this._passwordEntry.connect('changed',
+ this._onCredentialsChanged.bind(this));
+ this._signInButton.connect('clicked',
+ this._onSignInButtonClicked.bind(this));
+ this._verifyButton.connect('clicked',
+ this._onVerifyButtonClicked.bind(this));
+ this._verificationEntry.connect('changed',
+ this._onVerificationEntryChanged.bind(this));
+ this._signOutButton.connect('clicked',
+ this._onSignOutButtonClicked.bind(this));
+
+ /* if the user is logged in, show the logged-in view */
+ if (Application.osmEdit.isSignedIn) {
+ this._signedInUserLabel.label = Application.osmEdit.username;
+ this._stack.visible_child_name = 'logged-in';
+ }
+ },
+
+ _onCredentialsChanged: function() {
+ let email = this._emailEntry.text;
+ let password = this._passwordEntry.text;
+
+ /* make sign in button sensitive if credential have been entered
+ TODO: should we try to validate email addresses? */
+ this._signInButton.sensitive =
+ email && email.length > 0 && password && password.length > 0;
+ },
+
+ _onSignInButtonClicked: function() {
+ /* turn on signing in spinner and desensisize credential entries */
+ this._signInSpinner.visible = true;
+ this._signInButton.sensitive = false;
+ this._emailEntry.sensitive = false;
+ this._passwordEntry.sensitive = false;
+ this._signUpLinkButton.visible = false;
+
+ Application.osmEdit.performOAuthSignIn(this._emailEntry.text,
+ this._passwordEntry.text,
+ this._onOAuthSignInPerformed.bind(this));
+ },
+
+ _onOAuthSignInPerformed: function(success, verificationPage) {
+ if (success) {
+ /* switch to the verification view and show the verification
+ page */
+ this._verifyView.load_html_string(verificationPage,
+ 'https://www.openstreetmap.org/');
+ this._stack.visible_child_name = 'verify';
+ } else {
+ /* clear password entry */
+ this._passwordEntry.text = '';
+ /* show the password reset link */
+ this._resetPasswordLabel.visible = true;
+ }
+
+ this._signInSpinner.visible = false;
+ /* re-sensisize credential entries */
+ this._emailEntry.sensitive = true;
+ this._passwordEntry.sensitive = true;
+ },
+
+ _onVerifyButtonClicked: function() {
+ /* allow copying the leading space between the "The verification is"
+ label and the code */
+ let verificationCode = this._verificationEntry.text.trim();
+
+ /* Since the text shown on OSM's OAuth authorization verification form
+ is a bit unclear with a trailing period after the verification code,
+ let's strip that off if the user copied that over. */
+ if (verificationCode.charAt(verificationCode.length - 1) === '.') {
+ verificationCode =
+ verificationCode.substring(0, verificationCode.length - 1);
+ }
+
+ Application.osmEdit.requestOAuthAccessToken(verificationCode,
+ this._onOAuthAccessTokenRequested.bind(this));
+ },
+
+ _onVerificationEntryChanged: function() {
+ this._verifyButton.sensitive =
+ this._verificationEntry.text &&
+ this._verificationEntry.text.length > 0;
+ },
+
+ _onOAuthAccessTokenRequested: function(success) {
+ if (success) {
+ /* update the username label */
+ this._signedInUserLabel.label = Application.osmEdit.username;
+ /* switch to the logged in view and reset the state in case
+ the user signs out and start over again */
+ this._resetPasswordLabel.visible = false;
+ this._verificationFailedLabel = false;
+ this._signUpLinkButton.visible = true;
+ this._stack.visible_child_name = 'logged-in';
+ } else {
+ /* switch back to the sign-in view, and show a label indicating
+ that verification failed */
+ this._resetPasswordLabel.visible = false;
+ this._signUpLinkButton.visible = false;
+ this._verificationFailedLabel.visible = true;
+ this._signInButton.sensitive = true;
+ this._stack.visible_child_name = 'sign-in';
+ }
+ /* reset verification code entry */
+ this._verificationEntry.text = '';
+ },
+
+ _onSignOutButtonClicked: function() {
+ Application.osmEdit.signOut();
+ this._stack.visible_child_name = 'sign-in';
+ }
+});
diff --git a/src/osmEdit.js b/src/osmEdit.js
index 1ebc7c8..274d51b 100644
--- a/src/osmEdit.js
+++ b/src/osmEdit.js
@@ -56,6 +56,13 @@ const OSMEdit = new Lang.Class({
return response;
},
+ showAccountDialog: function(parentWindow) {
+ let dialog = new OSMAccountDialog.OSMAccountDialog({transient_for: parentWindow });
+ let response = dialog.run();
+ dialog.destroy();
+ return response;
+ },
+
fetchObject: function(place, callback, cancellable) {
let osmType = Utils.osmTypeToString(place.osmType);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]