1 <?xml version="1.0" encoding="utf-8"?>
3 xmlns:fx="http://ns.adobe.com/mxml/2009"
4 xmlns:mx="library://ns.adobe.com/flex/mx"
6 horizontalAlign="center" title="Save Changes"
7 width="350" height="330" verticalGap="0">
10 <mx:ArrayCollection id="changesetTags">
11 <fx:Object k="created_by" v="Potlatch 2"/>
12 <fx:Object k="version" v="{application.version}"/>
13 <fx:Object k="build" v="{application.build_number}"/>
17 <mx:ViewStack id="processSequence" width="100%" height="100%"
18 creationPolicy="all" creationComplete="if (doSkip) skipInput() else comment.setFocus()">
20 <!-- section for entering tags -->
21 <mx:VBox width="100%" height="100%" verticalGap="0">
22 <mx:ViewStack id="tagStack" width="100%" height="100%">
23 <mx:VBox width="100%" height="100%" label="Simple">
24 <mx:Text id="editDescription" width="100%">
26 Please enter a description of your edits. This will be used to give other
27 mappers an idea of what changes you are making.
30 <mx:HBox width="100%">
31 <mx:Image data="@Embed('../../../../embedded/read_this.png')" />
32 <mx:Text id="databaseWarning" width="100%">
34 Your changes are saved to the main OpenStreetMap database for everyone to
35 see. This is not your own private map. Please don't save test changes
36 or edits for personal use only.
40 <mx:Label id="commentLabel" text="Comment:"/>
41 <mx:TextArea id="comment" maxChars="255" width="100%" height="100%" change="commentChanged(event);" textInput="monitorEnter(event);" />
44 <mx:VBox width="100%" height="100%" label="Advanced">
45 <mx:Label text="Changeset tags:"/>
46 <mx:DataGrid editable="true" width="100%" id="advancedTagGrid"
47 dataProvider="{changesetTags}"
48 itemEditBeginning="allowForEdit(event)"
49 itemEditEnd="verifyInput(event)">
51 <mx:DataGridColumn editable="true" dataField="k" headerText="Key">
52 <mx:itemEditor><fx:Component><mx:TextInput restrict=" -" /></fx:Component></mx:itemEditor>
54 <mx:DataGridColumn editable="true" dataField="v" headerText="Value">
55 <mx:itemEditor><fx:Component><mx:TextInput restrict=" -" /></fx:Component></mx:itemEditor>
59 <mx:HBox horizontalAlign="right" width="100%">
60 <mx:LinkButton label="Delete" click="removeTag()" enabled="{advancedTagGrid.selectedItem != null? true : false}"/>
61 <mx:LinkButton label="Add" click="addNewTag()"/>
63 <mx:HRule width="100%" />
66 <mx:LinkBar dataProvider="{tagStack}"/>
69 <mx:VBox width="100%" height="100%" id="createChangesetTab">
70 <mx:VBox width="100%" height="100%" id="infoBox"/>
71 <mx:Spacer height="100%"/>
72 <mx:ProgressBar label="Creating changeset" labelPlacement="bottom" width="100%"
73 indeterminate="true" id="saveProgress"/>
76 <mx:VBox width="100%" height="100%" id="failureTab">
77 <mx:Text width="100%" styleName="failText" text="{failureText}"/>
80 <mx:VBox width="100%" height="100%" id="dataTab">
81 <mx:TextArea width="100%" height="100%" id="dataText"/>
87 <mx:CheckBox id="twitter" selected="{getTwitter()}"
88 label="Post on Twitter"
89 change="setTwitter(twitter.selected)" />
91 <mx:Button id="dataButton" label="View data" visible="false" click="processSequence.selectedChild=dataTab" styleName="titleWindowButton" />
92 <mx:Spacer width="100%"/>
93 <mx:Button id="cancelButton" label="Cancel" click="close();" styleName="titleWindowButton" />
94 <mx:Button id="saveButton" label="Save >" click="startSave();" styleName="titleWindowButton" />
100 import mx.managers.PopUpManager;
101 import mx.core.Application;
102 import mx.core.FlexGlobals;
103 import mx.events.DataGridEvent;
104 import mx.events.DataGridEventReason;
107 import net.systemeD.halcyon.connection.*;
108 import net.systemeD.halcyon.AttentionEvent;
110 private var _connection:Connection;
111 private var doSkip:Boolean = false;
112 private var newChangeset:Boolean = true;
114 [Bindable] private var failureText:String = "";
115 [Bindable] private var application:Object = FlexGlobals.topLevelApplication;
117 public function setConnection(connection:Connection):void {
118 _connection=connection;
122 public function dontPrompt():void {
124 if (processSequence.initialized) { skipInput(); } else { doSkip=true; }
127 private function skipInput():void {
128 processSequence.selectedChild = createChangesetTab;
129 saveButton.enabled = false;
133 private function commentChanged(event:Event):void {
134 for (var i:int=changesetTags.length-1; i>0; i--) {
135 if (changesetTags[i]['k']=='comment') { changesetTags.removeItemAt(i); }
137 if (event.target.text!='') changesetTags.addItem( { k:'comment', v: event.target.text } );
140 private function monitorEnter(event:TextEvent):void {
141 if (event.text=="\n") { event.preventDefault(); startSave(); }
144 private function addNewTag():void {
145 changesetTags.addItem( { k:'(new key)', v:'(new value)' } );
146 advancedTagGrid.editedItemPosition = { rowIndex: changesetTags.length-1, columnIndex: 0 };
149 private function removeTag():void {
150 changesetTags.removeItemAt(advancedTagGrid.selectedIndex);
153 private function startSave():void {
155 // move to next sequence
156 processSequence.selectedChild = createChangesetTab;
157 saveButton.enabled = false;
159 var tags:Object = new Object();
160 for each (var tag:Object in changesetTags) {
161 tags[tag['k']] = tag['v'];
165 _connection.addEventListener(Connection.NEW_CHANGESET, changesetCreated);
166 _connection.addEventListener(Connection.NEW_CHANGESET_ERROR, changesetError);
167 _connection.createChangeset(tags);
170 private function allowForEdit(event:DataGridEvent):void {
171 /* check before editing the tag grid that it's neither created_by nor version tags */
172 var item:Object = ((event.currentTarget as DataGrid).dataProvider as ArrayCollection)[event.rowIndex];
173 if(item.k == 'created_by' || item.k == 'version' || item.k == 'build') {
174 event.preventDefault();
178 private function verifyInput(event:DataGridEvent):void {
179 /* check before saving any change that the new key isn't created_by nor version */
180 // it is OK if the user cancels the edit
181 if( event.reason == DataGridEventReason.CANCELLED ) return;
183 var editor:TextInput = (event.currentTarget as DataGrid).itemEditorInstance as TextInput;
185 if( event.dataField == "k" ) {
186 if( editor.text == 'created_by' || editor.text == 'version' || editor.text == 'build') {
187 event.preventDefault();
192 private function changesetCreated(event:EntityEvent=null):void {
193 var changeset:Changeset = _connection.getActiveChangeset();
194 addStatus("Saving to changeset "+changeset.id);
196 saveProgress.label = "Uploading changes";
197 twitter.visible=false; twitter.includeInLayout=false;
198 _connection.addEventListener(Connection.SAVE_COMPLETED, saveCompleted);
199 var rawData:*=_connection.uploadChanges();
201 dataText.text=rawData.toString();
202 dataButton.visible=true;
206 private function changesetError(event:Event):void {
207 fail("Error creating changeset");
210 private function saveCompleted(event:SaveCompleteEvent):void {
211 if ( event.saveOK ) {
212 _connection.dispatchEvent(new AttentionEvent(AttentionEvent.ALERT, null, "Changes successfully saved"));
213 if (twitter.selected && newChangeset) {
214 var url:String="https://twitter.com/intent/tweet?url=http%3A%2F%2Fwww.openstreetmap.org%2Fbrowse%2Fchangeset%2F";
215 url+=_connection.getActiveChangeset().id;
216 var comment:String=_connection.getActiveChangeset().getTag('comment') || "I just edited OpenStreetMap!";
217 url+="&text="+encodeURIComponent(comment);
218 navigateToURL(new URLRequest(url), "_blank");
220 if (processSequence.selectedChild!=dataTab) close();
222 fail("Failure when uploading data");
224 if (saveButton && saveButton.parent) saveButton.parent.removeChild(saveButton);
225 cancelButton.label = "Close";
228 private function addStatus(text:String):void {
229 var label:Text = new Text();
232 infoBox.addChild(label);
235 private function fail(text:String):void {
236 processSequence.selectedChild = failureTab;
240 private function close():void {
241 _connection.removeEventListener(Connection.NEW_CHANGESET, changesetCreated);
242 _connection.removeEventListener(Connection.NEW_CHANGESET_ERROR, changesetError);
243 _connection.removeEventListener(Connection.SAVE_COMPLETED, saveCompleted);
244 PopUpManager.removePopUp(this);
247 public function getTwitter():Boolean {
248 return SharedObject.getLocal('user_state','/').data['twitter'];
251 public function setTwitter(v:Boolean):void {
252 var obj:SharedObject=SharedObject.getLocal("user_state","/");
253 obj.setProperty('twitter',v);
254 try { obj.flush(); } catch (e:Error) {}