package esri.mrm.mobile.activity; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; import android.os.Parcelable; import android.preference.PreferenceManager; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.Spinner; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import android.widget.ToggleButton; import com.esri.android.map.ags.ArcGISFeatureLayer; import com.esri.core.map.CallbackListener; import com.esri.core.map.FeatureEditResult; import com.esri.core.map.Field; import com.esri.core.map.Graphic; import esri.mrm.mobile.AGSObjects; import esri.mrm.mobile.NonServiceWorkOrderType; import esri.mrm.mobile.PropertyDefinition; import esri.mrm.mobile.R; import esri.mrm.mobile.StopsConfiguration; import esri.mrm.mobile.StopsConfigurations; import esri.mrm.mobile.WorkOrder; import esri.mrm.mobile.WorkOrderStatus; public class WorkOrderDetailActivity extends Activity implements OnSharedPreferenceChangeListener { private String baseURL; Map<String, View> updates; StopsConfigurations stopsConfigurations; StopsConfiguration stopsConfiguration; private String updateUrlPrefix; private Context context; private WorkOrder workOrder; private ArcGISFeatureLayer stopLayer; private ArcGISFeatureLayer stopPendingLayer; private AGSObjects agsObjects; private ProgressDialog progressDialog; private SharedPreferences sharedPrefs; private boolean needToClose; private List<WorkOrder> workOrders; private View viewToLoad; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.workorder_detail); needToClose = false; sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); sharedPrefs.registerOnSharedPreferenceChangeListener(this); viewToLoad = LayoutInflater.from(this.getParent()).inflate(R.layout.workorder_detail, null); this.setContentView(viewToLoad); setContext(viewToLoad.getContext()); WorkOrder workorder; Bundle b = this.getIntent().getExtras(); if (b != null) { Parcelable[] parcelable = b.getParcelableArray("WorkOrders"); if (parcelable != null) { workOrders = new ArrayList<WorkOrder>(); for (int i = 0; i < parcelable.length; i++) { workOrders.add((WorkOrder) parcelable[i]); } } workorder = b.getParcelable("WorkOrder"); stopsConfigurations = b.getParcelable("stopsConfigurations"); stopsConfiguration = stopsConfigurations.getStopsConfiguration(workorder.getType()); baseURL = stopsConfigurations.getGepUrl(); if (workorder != null) { setWorkOrder(workorder); fillView(workorder, stopsConfiguration, viewToLoad); setUpdateUrlPrefix(baseURL + stopsConfigurations.getCallback() + "/" + workorder.getStopName() + "?"); } } } public boolean isNeedToClose() { return needToClose; } public void fillView(WorkOrder workorder, StopsConfiguration stopsConfiguration, View view) { TextView textViewName = (TextView) findViewById(R.id.workorder_name); new GetPictureTask().execute(baseURL + workorder.getPictureSubUrl()); textViewName.setText(workorder.getStopName()); TextView textViewAddress = (TextView) findViewById(R.id.workorder_address); if (workorder.getType().equals(NonServiceWorkOrderType.Break.toString())) textViewAddress.setText(""); else textViewAddress.setText(workorder.getAddress()); Button allAttributesButton = (Button) findViewById(R.id.allAttributesButton); allAttributesButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { View allAttrView = LayoutInflater.from(context).inflate(R.layout.allattributes, null); TableLayout tv = (TableLayout) allAttrView.findViewById(R.id.tableLayout); tv.removeAllViewsInLayout(); tv.setShrinkAllColumns(true); TableRow trHeader = new TableRow(tv.getContext()); trHeader.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); TextView name = new TextView(trHeader.getContext()); name.setTextSize(14); name.setTextColor(Color.WHITE); name.setText("Field"); name.setBackgroundDrawable(getResources().getDrawable(R.drawable.header_cell_shape)); trHeader.addView(name); TextView value = new TextView(trHeader.getContext()); value.setTextSize(14); value.setTextColor(Color.WHITE); value.setText("Value"); value.setBackgroundDrawable(getResources().getDrawable(R.drawable.header_cell_shape)); trHeader.addView(value); tv.addView(trHeader); Map<String, String> aliases = getWorkOrder().getFieldAliases(); Map<String, Integer> fieldTypes = getWorkOrder().getFieldTypes(); for (Map.Entry<String, String> entry : aliases.entrySet()) { TableRow tr = new TableRow(tv.getContext()); tr.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); String workOrderResourceName = entry.getValue(); String alias = entry.getValue(); TextView fieldNameText = new TextView(tr.getContext()); fieldNameText.setTextSize(14); fieldNameText.setTextColor(Color.WHITE); fieldNameText.setText(alias); fieldNameText.setBackgroundDrawable(getResources().getDrawable(R.drawable.fieldname_cell_shape)); tr.addView(fieldNameText); TextView fieldValueText = new TextView(tr.getContext()); fieldValueText.setTextSize(14); fieldValueText.setTextColor(Color.BLACK); if(fieldTypes.get(workOrderResourceName) == Field.esriFieldTypeDate) { if(getWorkOrder().getAttributes(workOrderResourceName)==null) fieldValueText.setText(""); else { Date d = new Date((Long)getWorkOrder().getAttributes(workOrderResourceName)); fieldValueText.setText(d.toString()); } } else fieldValueText.setText(getWorkOrder().getAttributes(workOrderResourceName)==null?"":getWorkOrder().getAttributes(workOrderResourceName).toString()); fieldValueText.setBackgroundDrawable(getResources().getDrawable(R.drawable.cell_shape)); tr.addView(fieldValueText); tv.addView(tr); } Button cancelButton = (Button) allAttrView.findViewById(R.id.cancel_button); final PopupWindow popUp = new PopupWindow(allAttrView, viewToLoad.getWidth(), viewToLoad.getHeight(), true); // new // PopupWindow(allAttrView); cancelButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { popUp.dismiss(); } }); popUp.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.simple_popup_window_drop_shadow)); popUp.showAtLocation(viewToLoad, Gravity.CENTER, 0, 0); } }); TextView textViewWorkOrderId = (TextView) findViewById(R.id.workorder_id); textViewWorkOrderId.setText("#" + workorder.getId()); TextView textViewTask = (TextView) findViewById(R.id.workorder_task); ImageView imageViewWorkOrder = (ImageView) findViewById(R.id.iconWorkOrder); String type = workorder.getType(); if (type.equals("Turn On")) { imageViewWorkOrder.setImageResource(R.drawable.ic_turnon_w); textViewTask.setText("Turn On"); } else if (type.equals("DoorTag")) { imageViewWorkOrder.setImageResource(R.drawable.ic_doortag_w); textViewTask.setText("Door Tag"); } else if (type.equals("Inspection")) { imageViewWorkOrder.setImageResource(R.drawable.ic_inspection_w); textViewTask.setText("Inspection"); // To Do Show text input } else if (type.equals("Break")) { imageViewWorkOrder.setImageResource(R.drawable.ic_breaktime_w); textViewTask.setText("Break"); } else { imageViewWorkOrder.setImageResource(R.drawable.ic_no); textViewTask.setText("N/A"); } TextView textViewArrivalTime = (TextView) findViewById(R.id.arrivalTime); TextView textViewDepartureTime = (TextView) findViewById(R.id.departureTime); if (workorder.getType().equals(NonServiceWorkOrderType.Break.toString())) { textViewArrivalTime.setText(workorder.getProjectedArrival() + " Arrival"); textViewDepartureTime.setText(workorder.getProjectedDeparture() + " Departure"); } else { textViewArrivalTime.setText(workorder.getEtaTime() + " Arrival"); textViewDepartureTime.setText(workorder.getEtdTime() + " Departure"); } if (stopsConfiguration == null) { LinearLayout updatesLayout = (LinearLayout) findViewById(R.id.updatesLayout); updatesLayout.setVisibility(View.INVISIBLE); return; } // Special handling for status PropertyDefinition statusPD = stopsConfiguration.getPropertyDefinition(getResources().getString(R.string.ALIAS_STOPSLAYER_STATUS)); LinearLayout layout = (LinearLayout) findViewById(R.id.statusButtonsLayout); if (statusPD.getAllowedValues().size() > 0) { // Create a vertical list of buttons for (Object statusObj : statusPD.getAllowedValues()) { ToggleButton button = new ToggleButton(this); button.setTag(statusPD.getPropertyName()); button.setChecked(false); button.setTextOff((String) statusObj); button.setText((String) statusObj); button.setTextOn((String) statusObj); button.setWidth(getPixelFromDP(90)); button.setHeight(getPixelFromDP(50)); button.setPadding(0, 0, 0, 8); if (workorder.getStatus().equals(statusObj)) { button.setChecked(true); } button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Exception LinearLayout parent = (LinearLayout) v.getParent(); ToggleButton thisButton = (ToggleButton) v; if (!thisButton.isChecked()) { // toggle button changes checked state as soon as it is clicked thisButton.setChecked(true); return; } String newStatus = ((Button) v).getText().toString(); //getWorkOrder().setAttributes(((Button) v).getTag().toString(), ((Button) v).getText().toString()); updateWorkOrderTimesAndStatus(newStatus); selectRemarks(parent, thisButton); // unselect other buttons for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); if (child instanceof ToggleButton && child != v) { ((ToggleButton) child).setChecked(false); } } } }); layout.addView(button); } } else { // Create a label and a input box } // Handle additional update fields TextView updatesSeparator = (TextView) findViewById(R.id.updatesSeparator); LinearLayout updatesLayout = (LinearLayout) findViewById(R.id.updatesLayout); updatesLayout.setVisibility(View.INVISIBLE); updatesSeparator.setVisibility(View.INVISIBLE); updates = new HashMap<String, View>(); for (PropertyDefinition pd : stopsConfiguration.getPropertyDefinitions()) { if (!pd.isReadOnly() && pd != statusPD && !pd.getPropertyName().equals(getResources().getString(R.string.ALIAS_STOPSLAYER_STATUS_REMARK))) { if (pd.hasAllowedValues()) { String[] values = pd.getAllowedValues().toArray(new String[pd.getAllowedValues().size()]); Spinner spinner = new Spinner(view.getContext()); ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(view.getContext(), android.R.layout.simple_spinner_item, values); spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(spinnerArrayAdapter); Object obj = workorder.getAttributes(pd.getPropertyName()); String matchString = null; if (obj != null) { matchString = obj.toString(); } else { if (pd.getDefaultValue() != null) matchString = pd.getDefaultValue().toString(); } if (matchString != null) { ArrayAdapter myAdap = (ArrayAdapter) spinner.getAdapter(); int spinnerPosition = myAdap.getPosition(matchString); spinner.setSelection(spinnerPosition); } updates.put(pd.getPropertyName(), spinner); updatesLayout.addView(spinner, 0); } else { EditText editText = new EditText(view.getContext()); editText.setPadding(0, 0, 0, getPixelFromDP(5)); editText.setTextSize(getPixelFromDP(16)); Object obj = workorder.getAttributes(pd.getPropertyName()); if (obj != null) { editText.setText(obj.toString()); } else { if (pd.getDefaultValue() != null) editText.setHint(pd.getDefaultValue().toString()); } updates.put(pd.getPropertyName(), editText); updatesLayout.addView(editText, 0); } TextView label = new TextView(this); label.setTextSize(getPixelFromDP(16)); label.setText(pd.getLabel()); updatesLayout.addView(label, 0); } } if (updatesLayout.getChildCount() > 1) { updatesLayout.setVisibility(View.VISIBLE); updatesSeparator.setVisibility(View.VISIBLE); Button updateButton = (Button) findViewById(R.id.updateButton); updateButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Iterator it = updates.entrySet().iterator(); while (it.hasNext()) { Map.Entry pairs = (Map.Entry) it.next(); if (pairs.getValue() instanceof EditText) { try { getWorkOrder().setAttributes(pairs.getKey().toString(), ((EditText) pairs.getValue()).getText().toString()); } catch (Exception e) { e.printStackTrace(); } } else if (pairs.getValue() instanceof Spinner) { try { getWorkOrder().setAttributes(pairs.getKey().toString(), (String) ((Spinner) pairs.getValue()).getSelectedItem()); } catch (Exception e) { e.printStackTrace(); } } } updateStopsLayer(false); } }); } else if (getWorkOrder().getType().equals(NonServiceWorkOrderType.Break.toString())) { updatesLayout.setVisibility(View.VISIBLE); updatesSeparator.setVisibility(View.VISIBLE); Button updateButton = (Button) findViewById(R.id.updateButton); updateButton.setText("Change Break..."); updateButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(getParent(), StopTypeActivity.class); Bundle b = new Bundle(); b.putParcelable("WorkOrder", getWorkOrder()); b.putParcelableArray("WorkOrders", workOrders.toArray(new Parcelable[workOrders.size()])); intent.putExtras(b); TabGroupActivity parentActivity = (TabGroupActivity) getParent(); parentActivity.startChildActivity("StopTypeActivity", intent); } }); if (getWorkOrder().getStatus().equals(WorkOrderStatus.Completed.toString()) || getWorkOrder().getStatus().equals(WorkOrderStatus.AtStop.toString())) updateButton.setEnabled(false); } } private void updateWorkOrderTimesAndStatus(String newStatus) { Date now = new Date(); getWorkOrder().setLastUpdated(now.getTime()); getWorkOrder().setStatus(newStatus); if(newStatus.equals(WorkOrderStatus.AtStop.toString())) getWorkOrder().setAttributes(getResources().getString(R.string.ALIAS_STOPSLAYER_ACTUAL_ARRIVAL), Long.toString(now.getTime())); if(newStatus.equals(WorkOrderStatus.Completed.toString()) || newStatus.equals(WorkOrderStatus.Exception.toString())) { getWorkOrder().setAttributes(getResources().getString(R.string.ALIAS_STOPSLAYER_ACTUAL_DEPARTURE), Long.toString(now.getTime())); if(getWorkOrder().getActualArrivalAsLong() != null) { // TODO: Revisit duration strategy long minutes = (now.getTime()-getWorkOrder().getActualArrivalAsLong())/60000 > 32767 ? 32767 : (now.getTime()-getWorkOrder().getActualArrivalAsLong())/60000; getWorkOrder().setAttributes(getResources().getString(R.string.ALIAS_STOPSLAYER_ACTUAL_DURATION), Long.toString(minutes)); } } } private void selectRemarks(View parent, ToggleButton thisButton) { PropertyDefinition pd = getPropertyDefinitionBasedOnDependency(getResources().getString(R.string.ALIAS_STOPSLAYER_STATUS_REMARK)); if(pd==null) { updateStopsLayer(true); } else { final String[] values = pd.getAllowedValues().toArray(new String[pd.getAllowedValues().size()]); final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_dropdown_item, values); new AlertDialog.Builder(getContext()).setTitle(R.string.exceptionReasonPrompt).setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String selection = ""; try { ListView lw = ((AlertDialog) dialog).getListView(); selection = (String) lw.getAdapter().getItem(which); } catch (Exception e) { e.printStackTrace(); } getWorkOrder().setAttributes(getResources().getString(R.string.ALIAS_STOPSLAYER_STATUS_REMARK), selection); updateStopsLayer(true); dialog.dismiss(); } }).create().show(); } } private PropertyDefinition getPropertyDefinitionBasedOnDependency(String name) { List<PropertyDefinition> pds = stopsConfiguration.getPropertyDefinitions(name); if(pds != null) { for(PropertyDefinition p:pds) { String dependsOn = p.getDependsOn(); if(dependsOn != null) { if(dependsOn.contains("=")) { String fieldAlias = dependsOn.split("=")[0].trim(); String value = dependsOn.split("=")[1].trim(); if(((String)getWorkOrder().getAttributes(fieldAlias)).equals(value)) { return p; } } } } } return null; } private class GetPictureTask extends AsyncTask<String, Void, Bitmap> { @Override protected Bitmap doInBackground(String... uri) { URL url; Bitmap bmp = null; try { url = new URL(uri[0]); bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream()); } catch (MalformedURLException e) { } catch (IOException e) { } return bmp; } @Override protected void onPostExecute(Bitmap bmp) { ImageView imageViewWorkOrderLocation = (ImageView) findViewById(R.id.icon_workorderLocation); try { if (bmp != null) { imageViewWorkOrderLocation.setImageBitmap(bmp); } else { imageViewWorkOrderLocation.setImageResource(R.drawable.image_missing); } } catch (Exception e) { imageViewWorkOrderLocation.setImageResource(R.drawable.image_missing); } } } private void showProgressDialog() { progressDialog = new ProgressDialog(context); progressDialog.setTitle("Processing..."); progressDialog.setMessage("Please wait."); progressDialog.setCancelable(false); progressDialog.setIndeterminate(true); progressDialog.show(); } private void updateStopsLayer(final boolean notifyGEP) { showProgressDialog(); agsObjects = ((AGSObjects) getApplicationContext()); stopLayer = agsObjects.getStopsLayer(); Map<String, Object> attrs = getWorkOrder().getAllAttributes(); final Graphic newGraphic = new Graphic(getWorkOrder().getGraphic().getGeometry(), null, attrs); try { stopLayer.applyEdits(null, null, new Graphic[] { newGraphic }, new CallbackListener<FeatureEditResult[][]>() { public void onCallback(FeatureEditResult[][] result) { if (notifyGEP) { stopPendingLayer = agsObjects.getStopsPendingLayer(); try { stopPendingLayer.applyEdits(new Graphic[] { newGraphic }, null, null, new CallbackListener<FeatureEditResult[][]>() { public void onError(Throwable arg0) { progressDialog.dismiss(); showUpdateResult(false); } public void onCallback(FeatureEditResult[][] arg0) { progressDialog.dismiss(); showUpdateResult(true); // fillView(getWorkOrder(), stopsConfiguration, viewToLoad); if (getWorkOrder().getType().equals(NonServiceWorkOrderType.Break.toString())) { Button updateButton = (Button) findViewById(R.id.updateButton); if (getWorkOrder().getStatus().equals(WorkOrderStatus.AtStop.toString()) || getWorkOrder().getStatus().equals(WorkOrderStatus.Completed.toString())) updateButton.setEnabled(false); else updateButton.setEnabled(true); } } }); } catch (Exception e) { progressDialog.dismiss(); showUpdateResult(false); } } else { progressDialog.dismiss(); showUpdateResult(true); } } public void onError(Throwable e) { progressDialog.dismiss(); showUpdateResult(false); } }); } catch (Exception e) { progressDialog.dismiss(); showUpdateResult(false); } } private void showUpdateResult(final boolean successful) { WorkOrderDetailActivity.this.runOnUiThread(new Runnable() { public void run() { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); // set title alertDialogBuilder.setTitle(R.string.updateResult); // set dialog message alertDialogBuilder.setMessage(successful ? R.string.updateSucceeded : R.string.updateFailed).setCancelable(false).setPositiveButton(R.string.okButtonLabel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } }); } private int getPixelFromDP(int dp) { final float scale = this.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } protected String getUpdateUrlPrefix() { return updateUrlPrefix; } protected void setUpdateUrlPrefix(String updateUrlPrefix) { this.updateUrlPrefix = updateUrlPrefix; } protected Context getContext() { return context; } protected void setContext(Context context) { this.context = context; } protected WorkOrder getWorkOrder() { return workOrder; } protected void setWorkOrder(WorkOrder workOrder) { this.workOrder = workOrder; } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); } @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); } public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) { needToClose = true; } }