Currently on my application when i run it the code is working correctly, except when i add a 'symptom' that already belongs in the 'symptom history' , currently when i add a symptom which is already added in the symptom history the app gives out the message "Duplicate Symptom", "You already have recorded this symptom" and "Historical Symptom", "This symptom is in your history - Please restore from here". How can i get to it to only display "Historical Symptom", "This symptom is in your history - Please restore from here" message.
Currently if the symptom isnt deleted and moved to the symptom history the app will only output the "Duplicate Symptom", "You already have recorded this symptom" message corrrectly.
The functionality is working correctly just need to only display that one message on the function instead of both of them.
This is the current code on my button:
async void btnAdd_Clicked(object sender, EventArgs e)
{
CheckSymptomInHistory(AutoCompleteSymptomToAdd.Id);
//If the autocomplete is not empty - add that symptom to the user symptom table
if (AutoCompleteSymptomToAdd != null)
{
//If the user already has symptoms, loop through them to make sure that they are not adding a duplicate
if (UserSymptoms.Count > 0)
{
foreach (usersymptom item in UserSymptoms)
{
if (item.Symptomid == AutoCompleteSymptomToAdd.Id)
{
await DisplayAlert("Duplicate Symptom", "You already have recorded this symptom", "OK");
return;
}
//Check if it is not active (i.e in SYmptom History)
else
{
UserSymptomToAdd.Symptomid = AutoCompleteSymptomToAdd.Id;
UserSymptomToAdd.UserID = Helpers.Settings.UserKey;
UserSymptomToAdd.Datetimeadded = DateTime.Now.ToString();
UserSymptomToAdd.IsActive = true;
try
{
await usersymptommanager.AddUserSymptom(UserSymptomToAdd);
await AddInitialFeedback(UserSymptomToAdd.Id);
//await DisplayAlert("Symptom Added", "Your Symptom has been added", "OK");
}
catch (Exception ex)
{
Analytics.TrackEvent("App Screen: " + Title + ": " + ex);
//await DisplayAlert("Error", ex.ToString(), "OK");
}
}
}
}
The code for my history message:
async void CheckSymptomInHistory(string id)
{
foreach (string item in SymptomHistoryIDs)
{
if (id == item)
{
await DisplayAlert("Historical Symptom", "This symptom is in your history - Please restore from here", "OK");
}
}
}
So the first thing I see is that you're doing a null-check on AutoCompleteSymptomToAdd after you used it for CheckSymptomInHistory. I would put the null-check before CheckSymptomInHistory, otherwise you may be subjected to a NullReferenceException:
if (AutoCompleteSymptomToAdd == null)
{
// Display an error message?
return;
}
// AutoCompleteSymptomToAdd is not null, proceed to use it
CheckSymptomInHistory(AutoCompleteSymptomToAdd.Id);
I would then change the return type of CheckSymptomInHistory to return bool like so:
bool CheckSymptomInHistory(string id)
{
foreach (string item in SymptomHistoryIDs)
{
if (id == item)
{
return true;
}
}
return false;
}
Then in your handler, check the return type of the CheckSymptomInHistory method like so:
bool isSymptomInHistory = CheckSymptomInHistory(AutoCompleteSymptomToAdd.Id);
if (isSymptomInHistory)
{
await DisplayAlert("Historical Symptom", "This symptom is in your history - Please restore from here", "OK");
return;
}
// Symptom is not in history, carry on as normal
Do the following to achieve what you are trying;
Comment the First line of code in your method i.e. CheckSymptomInHistory(AutoCompleteSymptomToAdd.Id);
In the ForEach Loop:
foreach (usersymptom item in UserSymptoms)
{
if (item.Symptomid == AutoCompleteSymptomToAdd.Id)
{
await DisplayAlert("Duplicate Symptom", "You already have recorded this symptom", "OK");
return;
}
else if(CheckSymptomInHistory(AutoCompleteSymptomToAdd.Id);)
{
await DisplayAlert("Historical Symptom", "This symptom is in your history - Please restore from here", "OK");
}
Where CheckSystemInHistory is as below:
private bool CheckSymptomInHistory(string id)
{
foreach (string item in SymptomHistoryIDs)
{
if (id == item)
{
return true;
}
}
return false;
}
Related
I am running into an issue with signing up a user into Parse-Server while using Facebook.
When the user clicks on the Sign up with facebook icon this code will run..
ParseFacebookUtils.logInWithReadPermissionsInBackground(LoginRegister.this, permissions, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
MethodContants.showLog(TAG, "Uh oh. The user cancelled the Facebook login.", true);
} else if (user.isNew()) {
MethodContants.showLog(TAG, "User logged in through Facebook", false);
getUserDetailsFromFacebook();
} else {
MethodContants.showLog(TAG, "User logged in through Facebook", false);
Intent intent = new Intent(LoginRegister.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
}
}
});
My getUserDetailsFromFacebook() method looks like this
private void getUserDetailsFromFacebook() {
GraphRequest graphRequest = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject jsonObject, GraphResponse response) {
try {
facebookUser = jsonObject.getString("name");
MethodContants.showLog(TAG, "json name object: " + jsonObject.getString("name"), false);
} catch (JSONException e) {
MethodContants.showLog(TAG, "Error when getting facebook name: " + e.getMessage(), true);
showToast("Error saving Facebook user.");
}
try {
facebookEmail = jsonObject.getString("email");
MethodContants.showLog(TAG, "json email object: " + jsonObject.getString("email"), false);
} catch (JSONException e) {
MethodContants.showLog(TAG, "Error when getting facebook email: " + e.getMessage(), true);
showToast("Error saving Facebook email.");
}
saveNewFacebookUser();
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "name,email");
graphRequest.setParameters(parameters);
graphRequest.executeAsync();
}
my saveNewFacebookUser() looks like this...
private void saveNewFacebookUser() {
final ParseUser newFacebookUser = new ParseUser();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.profile_picture);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] image = stream.toByteArray();
ParseFile file = new ParseFile(AppConstants.PARSEUSER_IMAGE_FILE_NAME, image);
newFacebookUser.setUsername(facebookUser);
newFacebookUser.setEmail(facebookEmail);
newFacebookUser.put(AppConstants.PARSEUSER_FULLNAME, facebookUser);
newFacebookUser.put(AppConstants.PARSEUSER_FIRST_TIME_LOGGED_IN, "true");
newFacebookUser.put(AppConstants.PARSEUSER_PROFILE_IMAGE, file);
file.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
newFacebookUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
// USER CREATED!
// TODO SEND AN EMAIL TO THE USER WITH USERNAME AND PASSWORD
Intent intent = new Intent(LoginRegister.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
} else {
MethodContants.showLog(TAG, "Facebook Error:" + e.getMessage(), true);
showToast("Facebook Error: " + e.getMessage());
}
}
});
} else {
MethodContants.showLog(TAG, "Facebook Error:" + e.getMessage(), true);
showToast("Facebook Error: " + e.getMessage());
}
}
});
}
The error is telling me that I have to use signUpInBackground and not saveInBackground. However, when I do that, I get another error that says I need to save a password for the user -> which defeats the whole purpose of the facebook login.
Any help would be much appreciated!
I found the issue.
in the saveNewFacebookUser() method, I was setting it as a brand new user.
ParseUser new = new ParseUser();
This should have been
ParseUser new = ParseUser.getCurrentUser();
I will leave this up in case anyone has issues.
I want to check whether the email id entered by user is unique or not so for that initially I have my variable Boolean valid = false;. On clicking a button i am taking the email id entered and checking it for valid email id expression using regular expression and then i am using an asyntask to check its uniqueness. Code in my onclicklistner is
if (emailid.matches(regexp) && emailid.length() > 0) {
new Validate().execute();
Toast.makeText(getApplicationContext(), valid.toString(), Toast.LENGTH_LONG).show();
if (valid) {
data.putString("eid", eid);
data.putString("firstname", firstname);
data.putString("lastname", lastname);
data.putString("emailid", emailid);
Intent i = new Intent(getApplicationContext(), GamesFragment.class);
startActivity(i);
} else {
Toast.makeText(getApplicationContext(), "Email Address Already Exist", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(getApplicationContext(), "Check Your Email Address", Toast.LENGTH_LONG).show();
}
Here what problem i am facing is, for first time when i am entering an email which is unique and clicks the button, the Validate() asynctask checks and sets the valid variable to true, but it doesn't goes to next activity GamesFragment because i have declared valid = false initially. Now when i again click the button, then it goes to next activity as the valid variable is set to true because of previous click.
Now My Validate() asynctask is
private class Validate extends AsyncTask<Void, Void, Void> {
#Override
protected Boolean doInBackground(Void... params) {
ArrayList<NameValuePair> emailId = new ArrayList<NameValuePair>();
emailId.add(new BasicNameValuePair("email", emailid));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("url/validate.php");
httppost.setEntity(new UrlEncodedFormEntity(emailId));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
iss = entity.getContent();
} catch(Exception e) {
Log.e("pass 1", "Connection Error");
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader
(new InputStreamReader(iss,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null)
sb.append(line + "\n");
iss.close();
result = sb.toString();
} catch(Exception e) {
e.printStackTrace();
}
try {
JSONObject json_data = new JSONObject(result);
code=(json_data.getInt("code"));
if(code == 1)
valid = true;
else
valid = false;
Log.e("pass 3", "valid "+valid);
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
}
Please help i am not getting why this is happening.
Create function to check validation.
private boolean function validate(String emailid){
if (emailid.matches(regexp) && emailid.length() > 0) {
return true;
}
return false;
}
use that function to decide event
if(validate(emailid)){ // if function return true then email is valid and good to go.
new Validate().execute();
}
For second condition you have to check it in your async task onPostExecute() that is Validate();
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
if(code == 1){
// check if response is valid than
Intent i = new Intent(getApplicationContext(), GamesFragment.class);
startActivity(i);
}
}
I'm having an issue changing the workflow state for an item programmatically. The state isn't being changed no matter what I do to the field. I've tried using (new SecurityDisabler()){} and putting the item in editing mode then changing the field manually. I've noticed that the item itself has the Lock set to <r />, could this be causing an issue?
Here is some sample code of what I've tried to do:
[HttpPost]
[MultipleButton(Name = "action", Argument = "Submit")]
public ActionResult Submit(LoI model)
{
if (model.Submitted || !model.Signed)
{
return Redirect("/Profile/LoI");
}
ModifyCandidateInfo(model, true);
Session["message"] = Translate.Text("loi-submitted-message");
Session["messageClass"] = "success";
return Redirect("/Profile/LoI");
}
private static void ModifyCandidateInfo(LoI model, bool isSubmission)
{
using (new SecurityDisabler())
{
var candidateFolder = CBUtility.GetCandidateFolder();
var loi= candidateFolder.GetChildren().SingleOrDefault(loi => loi.TemplateID == LoITemplateId);
if (loi == null) return;
loi.Editing.BeginEdit();
EditFields(loi, model);
EditChildren(loi, model);
//Send emails upon submission
if (isSubmission)
{
loi.ExecuteCommand("Submit",
loi.Name + " submitted for " + model.CandidateName);
using (new SecurityDisabler())
{
loi.Editing.BeginEdit();
loi.Fields["__Workflow state"].Value = "{F352B651-341B-4CCF-89FE-BD77F5E4D540}";
loi.Editing.EndEdit();
}
}
loi.Editing.EndEdit();
}
}
I initalized the item's workflow with the following function:
public static void InitializeWorkflow(Item item, ID workflowId)
{
item.Editing.BeginEdit();
var workflow =
item.Database.WorkflowProvider.GetWorkflow(workflowId.ToString());
workflow.Start(item);
item.Editing.EndEdit();
}
The item starts at the default drafting state and executed a "Submit" command that fires off emails. Through the Sitecore UI if I hit submit it'll go to the next workflow state but not programmatically when I fire off the ExecuteCommand function. Below you'll find the ExecuteCommand function.
public static WorkflowResult ExecuteCommand(this Item item, string commandName, string comment)
{
using (new SecurityDisabler())
{
var workflow = item.Database.WorkflowProvider.GetWorkflow(item);
if (workflow == null)
{
return new WorkflowResult(false, "No workflow assigned to item");
}
var command = workflow.GetCommands(item[FieldIDs.WorkflowState])
.FirstOrDefault(c => c.DisplayName == commandName);
return command == null
? new WorkflowResult(false, "Workflow command not found")
: workflow.Execute(command.CommandID, item, comment, false);
}
}
The command fires off fine and the emails are sent but I can't figure out why the state won't change. Could someone provide me with other suggestions or a solution?
Am I reading the workflow state id correctly? I'm using the item ID for the workflow state.
I think your code is really similar to my implementation. This is my code's background.
All items have the same workflow named "WF" and it has three workflow states (Working, Awaiting Approval, and Approved). One page-item having "WF" has some rendering items and those datasource items. Suppose a content editor is ready to submit and approve the item with its related items. By hitting the "Submit" and "Approval" button in the page, all page-item's related items have the same workflow state as the page-item's one.
Most code are from Marek Musielak and this code is perfectly working in my side.
public class UpdateWorkflowState
{
// List all controls in page item
public RenderingReference[] GetListOfSublayouts(string itemId, Item targetItem)
{
RenderingReference[] renderings = null;
if (Sitecore.Data.ID.IsID(itemId))
{
renderings = targetItem.Visualization.GetRenderings(Sitecore.Context.Device, true);
}
return renderings;
}
// Return all datasource defined on one item
public IEnumerable<string> GetDatasourceValue(WorkflowPipelineArgs args, Item targetItem)
{
List<string> uniqueDatasourceValues = new List<string>();
Sitecore.Layouts.RenderingReference[] renderings = GetListOfSublayouts(targetItem.ID.ToString(), targetItem);
LayoutField layoutField = new LayoutField(targetItem.Fields[Sitecore.FieldIDs.FinalLayoutField]);
LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);
DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(Sitecore.Context.Device.ID.ToString());
foreach (var rendering in renderings)
{
if (!uniqueDatasourceValues.Contains(rendering.Settings.DataSource))
uniqueDatasourceValues.Add(rendering.Settings.DataSource);
}
return uniqueDatasourceValues;
}
// Check workflow state and update state
public WorkflowResult ChangeWorkflowState(Item item, ID workflowStateId)
{
using (new EditContext(item))
{
item[FieldIDs.WorkflowState] = workflowStateId.ToString();
}
Sitecore.Layouts.RenderingReference[] renderings = GetListOfSublayouts(item.ID.ToString(), item);
return new WorkflowResult(true, "OK", workflowStateId);
}
// Verify workflow state and update workflow state
public WorkflowResult ChangeWorkflowState(Item item, string workflowStateName)
{
IWorkflow workflow = item.Database.WorkflowProvider.GetWorkflow(item);
if (workflow == null)
{
return new WorkflowResult(false, "No workflow assigned to item");
}
WorkflowState newState = workflow.GetStates().FirstOrDefault(state => state.DisplayName == workflowStateName);
if (newState == null)
{
return new WorkflowResult(false, "Cannot find workflow state " + workflowStateName);
}
unlockItem(newState, item);
return ChangeWorkflowState(item, ID.Parse(newState.StateID));
}
// Unlock the item when it is on FinalState
public void unlockItem(WorkflowState newState, Item item)
{
if (newState.FinalState && item.Locking.IsLocked())
{
using (new EditContext(item, false, false))
{
item["__lock"] = "<r />";
}
}
}
}
I implemented a "before save" operation hook in my code to compare the new instance about to be saved with the old one already in the database.
For that, I compare the value given in the ctx.data with the one given by a query in the database.
The problem is the returned values are always similar, as if the new instance has already been saved in the database.
Have I totally missed the point of the "before save" hook, or is there a way to compare the two values ?
module.exports = function(app) {
var Like = app.models.Like;
Like.observe('before save', function(ctx, next) {
var count = 0;
if (ctx.instance) { // create operation
console.log('create operation);
}
else { // update operation
// Query for the existing model in db
Like.findById(ctx.where.id,
function(err, item) {
if (err)
console.log(err);
else {//compare query value and instance value
if (item.value != ctx.data.value) {
// Always false
}
else {
//Always true
}
}
}
);
}
next();
I can't understand why item.value always similar to ctx.data.value as the first one is supposed to be the actual value in the db and the second one the value about to be saved.
They way you have next() at the bottom doesn't seem right and might be giving enough time for the save to actually happen before the findById call returns. Once you call next the save can actually happen so findById can race with your save.
Try it like this where your next() is within the callback from the findById which will block saving until you've done your comparison.
module.exports = function(app) {
var Like = app.models.Like;
Like.observe('before save', function(ctx, next) {
var count = 0;
if (ctx.instance) { // create operation
console.log('create operation);
next();
}
else { // update operation
// Query for the existing model in db
Like.findById(ctx.where.id,
function(err, item) {
if (err)
console.log(err);
else {//compare query value and instance value
if (item.value != ctx.data.value) {
// Always false
}
else {
//Always true
}
}
next();
}
);
}
I am quite new at Android.
So I am a bit confused of working with fragments.
I have found a very great tutorial.
So I have working code. But it is the layout oft a normal activity.
Then I tried to include it into a navigation drawer.
So the list view with data will only be shown when the menu item has been selected.
On the fragment View there is a never ending loading Dialog.
While debugging I have figured out that the code loads still the data and inserts it into feedItems.
So feedItems is filled correctly.
Now after listAdapter.notifyDataSetChanged() there happens nothing.
So here that is my code:
public class FragmentNews extends ListFragment {
private static final String TAG = FragmentNews.class.getSimpleName();
private ListView listView;
private FeedListAdapter listAdapter;
private List<FeedItem> feedItems;
private String URL_FEED = "http://address.com";
public FragmentNews(){}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
loadDataForNews();
}
private void loadDataForNews(){
listView = this.getListView();
feedItems = new ArrayList<FeedItem>();
listAdapter = new FeedListAdapter(getActivity(), feedItems);
listView.setAdapter(listAdapter);
// We first check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
if (entry != null) {
// fetch the data from cache
try {
String data = new String(entry.data, "UTF-8");
try {
parseJsonFeed(new JSONObject(data));
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// making fresh volley request and getting json
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
URL_FEED, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, "Response: " + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
}
// List View Feed
private void parseJsonFeed(JSONObject response) {
try {
JSONArray feedArray = response.getJSONArray("feed");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
FeedItem item = new FeedItem();
item.setId(feedObj.getInt("id"));
item.setName(feedObj.getString("name"));
// Image might be null sometimes
String image = feedObj.isNull("image") ? null : feedObj
.getString("image");
item.setImge(image);
item.setStatus(feedObj.getString("status"));
item.setProfilePic(feedObj.getString("profilePic"));
item.setTimeStamp(feedObj.getString("timeStamp"));
// url might be null sometimes
String feedUrl = feedObj.isNull("url") ? null : feedObj
.getString("url");
item.setUrl(feedUrl);
feedItems.add(item);
}
// notify data changes to list adapater
listAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Can the problem be that the inflater of listAdapter is null?
Thanks for help!
Sometimes listAdapter.notifyDataSetChanged() does not work properly.
Try removing
listAdapter = new FeedListAdapter(getActivity(), feedItems);
listView.setAdapter(listAdapter);
from loadDataForNews() and adding in
place of listAdapter.notifyDataSetChanged();