diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml
index 2fc4178814a2..bbc07ca3563f 100644
--- a/WordPress/src/main/AndroidManifest.xml
+++ b/WordPress/src/main/AndroidManifest.xml
@@ -337,7 +337,7 @@
+ android:theme="@style/Calypso.NoActionBar"/>
0);
}
@@ -769,6 +770,7 @@ public boolean deleteWordPressComBlogs(Context ctx) {
int localBlogId = MapUtils.getMapInt(blog, "id");
deleteQuickPressShortcutsForLocalTableBlogId(ctx, localBlogId);
deleteAllPostsForLocalTableBlogId(localBlogId);
+ PeopleTable.deletePeopleForBlog(localBlogId);
}
// H4ck alert: We need to delete the Jetpack sites that were added in the initial
diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java b/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java
index 16a71dfc1d10..6139a39f4f6d 100644
--- a/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java
+++ b/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java
@@ -65,9 +65,12 @@ public static void save(Person person, SQLiteDatabase database) {
database.insertWithOnConflict(PEOPLE_TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
- public static void savePeople(List peopleList) {
+ public static void savePeople(List peopleList, int localTableBlogId) {
getWritableDb().beginTransaction();
try {
+ //We have a fresh list, remove the previous list of people in case it was deleted on remote
+ PeopleTable.deletePeopleForBlog(localTableBlogId);
+
for (Person person : peopleList) {
PeopleTable.save(person);
}
@@ -77,10 +80,21 @@ public static void savePeople(List peopleList) {
}
}
+ public static void deletePeopleForBlog(int localTableBlogId) {
+ String[] args = new String[]{Integer.toString(localTableBlogId)};
+ getWritableDb().delete(PEOPLE_TABLE, "local_blog_id=?", args);
+ }
+
+ public static void deletePerson(long personID, int localTableBlogId) {
+ String[] args = new String[]{Long.toString(personID), Integer.toString(localTableBlogId)};
+ getWritableDb().delete(PEOPLE_TABLE, "person_id=? AND local_blog_id=?", args);
+ }
+
public static List getPeople(int localTableBlogId) {
List people = new ArrayList<>();
String[] args = { Integer.toString(localTableBlogId) };
- Cursor c = getReadableDb().rawQuery("SELECT * FROM " + PEOPLE_TABLE + " WHERE local_blog_id=?", args);
+ Cursor c = getReadableDb().rawQuery("SELECT * FROM " + PEOPLE_TABLE +
+ " WHERE local_blog_id=? ORDER BY display_name, user_name", args);
try {
while (c.moveToNext()) {
@@ -102,7 +116,8 @@ public static List getPeople(int localTableBlogId) {
*/
public static Person getPerson(long personId, int localTableBlogId) {
String[] args = { Long.toString(personId), Integer.toString(localTableBlogId) };
- Cursor c = getReadableDb().rawQuery("SELECT * FROM " + PEOPLE_TABLE + " WHERE person_id=? AND local_blog_id=?", args);
+ Cursor c = getReadableDb().rawQuery("SELECT * FROM " + PEOPLE_TABLE +
+ " WHERE person_id=? AND local_blog_id=?", args);
try {
if (!c.moveToFirst()) {
return null;
@@ -123,6 +138,7 @@ private static Person getPersonFromCursor(Cursor c, int localTableBlogId) {
String avatarUrl = c.getString(c.getColumnIndex("avatar_url"));
String role = c.getString(c.getColumnIndex("role"));
- return new Person(personId, blogId, localTableBlogId, username, firstName, lastName, displayName, avatarUrl, role);
+ return new Person(personId, blogId, localTableBlogId, username,
+ firstName, lastName, displayName, avatarUrl, role);
}
}
diff --git a/WordPress/src/main/java/org/wordpress/android/models/Capability.java b/WordPress/src/main/java/org/wordpress/android/models/Capability.java
index 28436c73269a..2ae03aeac063 100644
--- a/WordPress/src/main/java/org/wordpress/android/models/Capability.java
+++ b/WordPress/src/main/java/org/wordpress/android/models/Capability.java
@@ -5,9 +5,9 @@
* A list of capabilities can be found in: https://codex.wordpress.org/Roles_and_Capabilities#Capabilities
*/
public enum Capability {
- EDIT_USERS("edit_users"), // Check if user can change another user's role
LIST_USERS("list_users"), // Check if user can visit People page
- PROMOTE_USERS("promote_users"); // Check if user can invite another user
+ PROMOTE_USERS("promote_users"), // Check if user can change another user's role
+ REMOVE_USERS("remove_users"); // Check if user can remove another user
private final String label;
diff --git a/WordPress/src/main/java/org/wordpress/android/models/Person.java b/WordPress/src/main/java/org/wordpress/android/models/Person.java
index f121b810ad90..8eca72227541 100644
--- a/WordPress/src/main/java/org/wordpress/android/models/Person.java
+++ b/WordPress/src/main/java/org/wordpress/android/models/Person.java
@@ -50,7 +50,7 @@ public static Person fromJSON(JSONObject json, String blogId, int localTableBlog
String username = json.optString("login");
String firstName = json.optString("first_name");
String lastName = json.optString("last_name");
- String displayName = json.optString("nice_name");
+ String displayName = json.optString("name");
String avatarUrl = json.optString("avatar_URL");
// We don't support multiple roles, so the first role is picked just as it's in Calypso
String role = json.getJSONArray("roles").optString(0);
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleAdapter.java
index a726d5f106cb..1806d8716cc7 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleAdapter.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleAdapter.java
@@ -88,10 +88,10 @@ private class PeopleViewHolder {
private final TextView txtRole;
PeopleViewHolder(View row) {
- imgAvatar = (WPNetworkImageView) row.findViewById(R.id.people_list_row_avatar);
- txtDisplayName = (TextView) row.findViewById(R.id.people_list_row_display_name);
- txtUsername = (TextView) row.findViewById(R.id.people_list_row_username);
- txtRole = (TextView) row.findViewById(R.id.people_list_row_role);
+ imgAvatar = (WPNetworkImageView) row.findViewById(R.id.person_avatar);
+ txtDisplayName = (TextView) row.findViewById(R.id.person_display_name);
+ txtUsername = (TextView) row.findViewById(R.id.person_username);
+ txtRole = (TextView) row.findViewById(R.id.person_role);
}
}
}
\ No newline at end of file
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleManagementActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleManagementActivity.java
index 2005f2b9ff6e..4131e7457693 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleManagementActivity.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/people/PeopleManagementActivity.java
@@ -1,10 +1,13 @@
package org.wordpress.android.ui.people;
+import android.app.AlertDialog;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import org.wordpress.android.R;
@@ -15,10 +18,12 @@
import org.wordpress.android.ui.ActivityLauncher;
import org.wordpress.android.ui.accounts.BlogUtils;
import org.wordpress.android.ui.people.utils.PeopleUtils;
+import org.wordpress.android.util.ToastUtils;
import java.util.List;
-public class PeopleManagementActivity extends AppCompatActivity implements PeopleListFragment.OnPersonSelectedListener {
+public class PeopleManagementActivity extends AppCompatActivity
+ implements PeopleListFragment.OnPersonSelectedListener, RoleChangeDialogFragment.OnChangeListener {
private static final String KEY_PEOPLE_LIST_FRAGMENT = "people-list-fragment";
private static final String KEY_PERSON_DETAIL_FRAGMENT = "person-detail-fragment";
@@ -26,12 +31,16 @@ public class PeopleManagementActivity extends AppCompatActivity implements Peopl
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setContentView(R.layout.people_management_activity);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
+ actionBar.setTitle(R.string.people);
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
}
- setContentView(R.layout.people_management_activity);
int localBlogId = BlogUtils.getBlogLocalId(WordPress.getCurrentBlog());
Blog blog = WordPress.getBlog(localBlogId);
@@ -57,9 +66,7 @@ public void finish() {
@Override
public void onBackPressed() {
- if (getFragmentManager().getBackStackEntryCount() > 0 ){
- getFragmentManager().popBackStack();
- } else {
+ if (!navigateBackToPeopleListFragment()) {
super.onBackPressed();
}
}
@@ -69,6 +76,9 @@ public boolean onOptionsItemSelected(final MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
+ } else if (item.getItemId() == R.id.remove_person) {
+ confirmRemovePerson();
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -77,25 +87,15 @@ private void refreshUsersList(String dotComBlogId, final int localTableBlogId) {
PeopleUtils.fetchUsers(dotComBlogId, localTableBlogId, new PeopleUtils.FetchUsersCallback() {
@Override
public void onSuccess(List peopleList) {
- PeopleTable.savePeople(peopleList);
-
- FragmentManager fragmentManager = getFragmentManager();
- PeopleListFragment peopleListFragment = (PeopleListFragment) fragmentManager
- .findFragmentByTag(KEY_PEOPLE_LIST_FRAGMENT);
- PersonDetailFragment personDetailFragment = (PersonDetailFragment) fragmentManager
- .findFragmentByTag(KEY_PERSON_DETAIL_FRAGMENT);
-
- if (peopleListFragment != null) {
- peopleListFragment.refreshPeopleList();
- }
- if (personDetailFragment != null) {
- personDetailFragment.refreshPersonDetails();
- }
+ PeopleTable.savePeople(peopleList, localTableBlogId);
+ refreshOnScreenFragmentDetails();
}
@Override
public void onError() {
- //TODO: show some kind of error to the user
+ ToastUtils.showToast(PeopleManagementActivity.this,
+ R.string.error_fetch_people_list,
+ ToastUtils.Duration.LONG);
}
});
}
@@ -120,4 +120,124 @@ public void onPersonSelected(Person person) {
fragmentTransaction.commit();
}
}
+
+ @Override
+ public void onRoleChanged(long personID, int localTableBlogId, String newRole) {
+ Person person = PeopleTable.getPerson(personID, localTableBlogId);
+ if (person == null || newRole == null || newRole.equalsIgnoreCase(person.getRole())) {
+ return;
+ }
+ PeopleUtils.updateRole(person.getBlogId(), person.getPersonID(), newRole, localTableBlogId,
+ new PeopleUtils.UpdateUserCallback() {
+ @Override
+ public void onSuccess(Person person) {
+ PeopleTable.save(person);
+ refreshOnScreenFragmentDetails();
+ }
+
+ @Override
+ public void onError() {
+ ToastUtils.showToast(PeopleManagementActivity.this,
+ R.string.error_update_role,
+ ToastUtils.Duration.LONG);
+ }
+ });
+ }
+
+ private void confirmRemovePerson() {
+ Person person = getCurrentPerson();
+ if (person == null) {
+ return;
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Calypso_AlertDialog);
+ builder.setTitle(getString(R.string.person_remove_confirmation_title, person.getDisplayName()));
+ builder.setMessage(getString(R.string.person_remove_confirmation_message, person.getDisplayName()));
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.setPositiveButton(R.string.remove, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ removeSelectedPerson();
+ }
+ });
+ builder.show();
+ }
+
+ private void removeSelectedPerson() {
+ Person person = getCurrentPerson();
+ if (person == null) {
+ return;
+ }
+ PeopleUtils.removePerson(person.getBlogId(),
+ person.getPersonID(),
+ person.getLocalTableBlogId(),
+ new PeopleUtils.RemoveUserCallback() {
+ @Override
+ public void onSuccess(long personID, int localTableBlogId) {
+ // remove the person from db, navigate back to list fragment and refresh it
+ Person person = PeopleTable.getPerson(personID, localTableBlogId);
+ String text;
+ if (person != null) {
+ PeopleTable.deletePerson(personID, localTableBlogId);
+ text = getString(R.string.person_removed, person.getUsername());
+ } else {
+ text = getString(R.string.person_removed_general);
+ }
+
+ ToastUtils.showToast(PeopleManagementActivity.this, text, ToastUtils.Duration.LONG);
+
+ navigateBackToPeopleListFragment();
+ refreshPeopleListFragment();
+ }
+
+ @Override
+ public void onError() {
+ ToastUtils.showToast(PeopleManagementActivity.this,
+ R.string.error_remove_user,
+ ToastUtils.Duration.LONG);
+ }
+ });
+ }
+
+ // This helper method is used after a successful network request
+ private void refreshOnScreenFragmentDetails() {
+ FragmentManager fragmentManager = getFragmentManager();
+ PersonDetailFragment personDetailFragment = (PersonDetailFragment) fragmentManager
+ .findFragmentByTag(KEY_PERSON_DETAIL_FRAGMENT);
+
+ if (personDetailFragment != null) {
+ personDetailFragment.refreshPersonDetails();
+ }
+
+ refreshPeopleListFragment();
+ }
+
+ private void refreshPeopleListFragment() {
+ FragmentManager fragmentManager = getFragmentManager();
+ PeopleListFragment peopleListFragment = (PeopleListFragment) fragmentManager
+ .findFragmentByTag(KEY_PEOPLE_LIST_FRAGMENT);
+ if (peopleListFragment != null) {
+ peopleListFragment.refreshPeopleList();
+ }
+ }
+
+ private boolean navigateBackToPeopleListFragment() {
+ if (getFragmentManager().getBackStackEntryCount() > 0) {
+ getFragmentManager().popBackStack();
+ return true;
+ }
+ return false;
+ }
+
+ private Person getCurrentPerson() {
+ FragmentManager fragmentManager = getFragmentManager();
+ PersonDetailFragment personDetailFragment = (PersonDetailFragment) fragmentManager
+ .findFragmentByTag(KEY_PERSON_DETAIL_FRAGMENT);
+
+ if (personDetailFragment == null) {
+ return null;
+ }
+
+ return personDetailFragment.loadPerson();
+ }
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/people/PersonDetailFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/people/PersonDetailFragment.java
index fdc53bef2c2c..76c19b86dc83 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/people/PersonDetailFragment.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/people/PersonDetailFragment.java
@@ -2,15 +2,28 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
+import android.app.AlertDialog;
import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
import android.widget.TextView;
import org.wordpress.android.R;
+import org.wordpress.android.WordPress;
import org.wordpress.android.datasets.PeopleTable;
+import org.wordpress.android.models.Account;
+import org.wordpress.android.models.AccountHelper;
+import org.wordpress.android.models.Blog;
+import org.wordpress.android.models.Capability;
import org.wordpress.android.models.Person;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.GravatarUtils;
@@ -27,8 +40,8 @@ public class PersonDetailFragment extends Fragment {
private WPNetworkImageView mAvatarImageView;
private TextView mDisplayNameTextView;
private TextView mUsernameTextView;
+ private LinearLayout mRoleContainer;
private TextView mRoleTextView;
- private TextView mRemoveTextView;
public static PersonDetailFragment newInstance(long personID, int localTableBlogID) {
PersonDetailFragment personDetailFragment = new PersonDetailFragment();
@@ -39,9 +52,15 @@ public static PersonDetailFragment newInstance(long personID, int localTableBlog
return personDetailFragment;
}
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.person_detail, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
/**
- * Sets the enter & pop animation for the fragment. In order to keep the animation even after the configuration
- * changes, this method is used instead of FragmentTransaction for the animation.
+ * Sets the enter & pop animation for the fragment. In order to keep the animation even after the configuration
+ * changes, this method is used instead of FragmentTransaction for the animation.
*/
@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
@@ -62,8 +81,15 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
mAvatarImageView = (WPNetworkImageView) rootView.findViewById(R.id.person_avatar);
mDisplayNameTextView = (TextView) rootView.findViewById(R.id.person_display_name);
mUsernameTextView = (TextView) rootView.findViewById(R.id.person_username);
+ mRoleContainer = (LinearLayout) rootView.findViewById(R.id.person_role_container);
mRoleTextView = (TextView) rootView.findViewById(R.id.person_role);
- mRemoveTextView = (TextView) rootView.findViewById(R.id.person_remove);
+
+ Account account = AccountHelper.getDefaultAccount();
+ boolean isCurrentUser = account.getUserId() == mPersonID;
+ Blog blog = WordPress.getBlog(mLocalTableBlogID);
+ if (!isCurrentUser && blog != null && blog.hasCapability(Capability.REMOVE_USERS)) {
+ setHasOptionsMenu(true);
+ }
return rootView;
}
@@ -78,7 +104,7 @@ public void onResume() {
public void refreshPersonDetails() {
if (!isAdded()) return;
- Person person = PeopleTable.getPerson(mPersonID, mLocalTableBlogID);
+ Person person = loadPerson();
if (person != null) {
int avatarSz = getResources().getDimensionPixelSize(R.dimen.avatar_sz_large);
String avatarUrl = GravatarUtils.fixGravatarUrl(person.getAvatarUrl(), avatarSz);
@@ -87,14 +113,8 @@ public void refreshPersonDetails() {
mDisplayNameTextView.setText(person.getDisplayName());
mUsernameTextView.setText(person.getUsername());
mRoleTextView.setText(StringUtils.capitalize(person.getRole()));
- mRemoveTextView.setText(String.format(getString(R.string.remove_user), person.getFirstName().toUpperCase()));
- mRemoveTextView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //TODO: remove user
- }
- });
+ setupRoleContainerForCapability();
} else {
AppLog.w(AppLog.T.PEOPLE, "Person returned null from DB for personID: " + mPersonID
+ " & localTableBlogID: " + mLocalTableBlogID);
@@ -106,4 +126,47 @@ public void setPersonDetails(long personID, int localTableBlogID) {
mLocalTableBlogID = localTableBlogID;
refreshPersonDetails();
}
+
+ // Checks current user's capabilities to decide whether she can change the role or not
+ private void setupRoleContainerForCapability() {
+ Blog blog = WordPress.getBlog(mLocalTableBlogID);
+ Account account = AccountHelper.getDefaultAccount();
+ boolean isCurrentUser = account.getUserId() == mPersonID;
+ boolean canChangeRole = (blog != null) && !isCurrentUser && blog.hasCapability(Capability.PROMOTE_USERS);
+ if (canChangeRole) {
+ mRoleContainer.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showRoleChangeDialog();
+ }
+ });
+ } else {
+ // Remove the selectableItemBackground if the user can't be edited
+ clearRoleContainerBackground();
+ // Change transparency to give a visual cue to the user that it's disabled
+ mRoleContainer.setAlpha(0.5f);
+ }
+ }
+
+ private void showRoleChangeDialog() {
+ Person person = loadPerson();
+ if (person == null) {
+ return;
+ }
+ RoleChangeDialogFragment.newInstance(person.getPersonID(), person.getLocalTableBlogId(), person.getRole())
+ .show(getFragmentManager(), null);
+ }
+
+ @SuppressWarnings("deprecation")
+ private void clearRoleContainerBackground() {
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ mRoleContainer.setBackgroundDrawable(null);
+ } else {
+ mRoleContainer.setBackground(null);
+ }
+ }
+
+ public Person loadPerson() {
+ return PeopleTable.getPerson(mPersonID, mLocalTableBlogID);
+ }
}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/people/RoleChangeDialogFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/people/RoleChangeDialogFragment.java
new file mode 100644
index 000000000000..6cd733931feb
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/people/RoleChangeDialogFragment.java
@@ -0,0 +1,170 @@
+package org.wordpress.android.ui.people;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
+import org.wordpress.android.R;
+
+public class RoleChangeDialogFragment extends DialogFragment {
+ private static final String PERSON_ID_TAG = "person_id";
+ private static final String PERSON_LOCAL_TABLE_BLOG_ID_TAG = "local_table_blog_id";
+ private static final String ROLE_TAG = "role";
+
+ private RoleListAdapter mRoleListAdapter;
+ private OnChangeListener mListener;
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ String role = mRoleListAdapter.getSelectedRole();
+ outState.putString(ROLE_TAG, role);
+ }
+
+ public static RoleChangeDialogFragment newInstance(long personID, int localTableBlogId, String role) {
+ RoleChangeDialogFragment roleChangeDialogFragment = new RoleChangeDialogFragment();
+ Bundle args = new Bundle();
+
+ args.putLong(PERSON_ID_TAG, personID);
+ args.putInt(PERSON_LOCAL_TABLE_BLOG_ID_TAG, localTableBlogId);
+ if (role != null) {
+ args.putString(ROLE_TAG, role);
+ }
+
+ roleChangeDialogFragment.setArguments(args);
+ return roleChangeDialogFragment;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ try {
+ mListener = (OnChangeListener) context;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(context.toString() + " must implement OnChangeListener");
+ }
+ }
+
+ // We need to override this for devices pre API 23
+ @SuppressWarnings("deprecation")
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mListener = (OnChangeListener) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString() + " must implement OnChangeListener");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mListener = null;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.Calypso_AlertDialog);
+ builder.setTitle(R.string.role);
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (mListener != null) {
+ String role = mRoleListAdapter.getSelectedRole();
+ Bundle args = getArguments();
+ if (args != null) {
+ long personID = args.getLong(PERSON_ID_TAG);
+ int localTableBlogId = args.getInt(PERSON_LOCAL_TABLE_BLOG_ID_TAG);
+ mListener.onRoleChanged(personID, localTableBlogId, role);
+ }
+ }
+ }
+ });
+
+ if (mRoleListAdapter == null) {
+ final String[] roles = getResources().getStringArray(R.array.roles);
+ mRoleListAdapter = new RoleListAdapter(getActivity(), R.layout.role_list_row, roles);
+ }
+ if (savedInstanceState != null) {
+ String savedRole = savedInstanceState.getString(ROLE_TAG);
+ mRoleListAdapter.setSelectedRole(savedRole);
+ } else {
+ Bundle args = getArguments();
+ if (args != null) {
+ String role = args.getString(ROLE_TAG);
+ mRoleListAdapter.setSelectedRole(role);
+ }
+ }
+ builder.setAdapter(mRoleListAdapter, null);
+
+ return builder.create();
+ }
+
+ private class RoleListAdapter extends ArrayAdapter {
+ private String mSelectedRole;
+
+ public RoleListAdapter(Context context, int resource, String[] objects) {
+ super(context, resource, objects);
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = View.inflate(getContext(), R.layout.role_list_row, null);
+ }
+
+ final RadioButton radioButton = (RadioButton) convertView.findViewById(R.id.radio);
+ TextView mainText = (TextView) convertView.findViewById(R.id.role_label);
+ String role = getItem(position);
+ mainText.setText(role);
+
+ if (radioButton != null) {
+ radioButton.setChecked(role.equalsIgnoreCase(mSelectedRole));
+ radioButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ changeSelection(position);
+ }
+ });
+ }
+
+ convertView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ changeSelection(position);
+ }
+ });
+
+ return convertView;
+ }
+
+ private void changeSelection(int position) {
+ mSelectedRole = getItem(position);
+ notifyDataSetChanged();
+ }
+
+ public String getSelectedRole() {
+ return mSelectedRole;
+ }
+
+ public void setSelectedRole(String role) {
+ mSelectedRole = role;
+ }
+ }
+
+ // Container Activity must implement this interface
+ public interface OnChangeListener {
+ void onRoleChanged(long personID, int localTableBlogId, String newRole);
+ }
+}
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/people/utils/PeopleUtils.java b/WordPress/src/main/java/org/wordpress/android/ui/people/utils/PeopleUtils.java
index 3ab39d7255bf..d8c688dad602 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/people/utils/PeopleUtils.java
+++ b/WordPress/src/main/java/org/wordpress/android/ui/people/utils/PeopleUtils.java
@@ -12,7 +12,9 @@
import org.wordpress.android.util.AppLog.T;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class PeopleUtils {
@@ -48,7 +50,7 @@ public void onErrorResponse(VolleyError volleyError) {
WordPress.getRestClientUtilsV1_1().get(path, listener, errorListener);
}
- public static void updateRole(final String blogId, String userID, String newRole, final int localTableBlogId,
+ public static void updateRole(final String blogId, long personID, String newRole, final int localTableBlogId,
final UpdateUserCallback callback) {
com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
@Override
@@ -79,19 +81,41 @@ public void onErrorResponse(VolleyError volleyError) {
}
};
- try {
- JSONObject jsonObject = new JSONObject();
- JSONArray roles = new JSONArray();
- roles.put(newRole);
- jsonObject.put("roles", roles);
-
- String path = String.format("sites/%s/users/%s", blogId, userID);
- WordPress.getRestClientUtilsV1_1().post(path, jsonObject, null, listener, errorListener);
- } catch (JSONException e) {
- if (callback != null) {
- callback.onError();
+ Map params = new HashMap<>();
+ params.put("roles", newRole.toLowerCase());
+ String path = String.format("sites/%s/users/%d", blogId, personID);
+ WordPress.getRestClientUtilsV1_1().post(path, params, null, listener, errorListener);
+ }
+
+ public static void removePerson(String blogId, final long personID, final int localTableBlogId,
+ final RemoveUserCallback callback) {
+ com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() {
+ @Override
+ public void onResponse(JSONObject jsonObject) {
+ if (jsonObject != null && callback != null) {
+ // check if the call was successful
+ boolean success = jsonObject.optBoolean("success");
+ if (success) {
+ callback.onSuccess(personID, localTableBlogId);
+ } else {
+ callback.onError();
+ }
+ }
}
- }
+ };
+
+ RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError volleyError) {
+ AppLog.e(T.API, volleyError);
+ if (callback != null) {
+ callback.onError();
+ }
+ }
+ };
+
+ String path = String.format("sites/%s/users/%d/delete", blogId, personID);
+ WordPress.getRestClientUtilsV1_1().post(path, listener, errorListener);
}
private static List peopleListFromJSON(JSONArray jsonArray, String blogId, int localTableBlogId)
@@ -116,6 +140,10 @@ public interface FetchUsersCallback extends Callback {
void onSuccess(List peopleList);
}
+ public interface RemoveUserCallback extends Callback {
+ void onSuccess(long personID, int localTableBlogId);
+ }
+
public interface UpdateUserCallback extends Callback {
void onSuccess(Person person);
}
diff --git a/WordPress/src/main/res/drawable/gridicons_trash.xml b/WordPress/src/main/res/drawable/gridicons_trash.xml
new file mode 100644
index 000000000000..a1ff3f401b4c
--- /dev/null
+++ b/WordPress/src/main/res/drawable/gridicons_trash.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/WordPress/src/main/res/drawable/people_list_divider.xml b/WordPress/src/main/res/drawable/people_list_divider.xml
new file mode 100644
index 000000000000..09d74f3d5075
--- /dev/null
+++ b/WordPress/src/main/res/drawable/people_list_divider.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WordPress/src/main/res/layout/people_list_fragment.xml b/WordPress/src/main/res/layout/people_list_fragment.xml
index 98e98a5e7578..d74a617eadae 100644
--- a/WordPress/src/main/res/layout/people_list_fragment.xml
+++ b/WordPress/src/main/res/layout/people_list_fragment.xml
@@ -2,15 +2,14 @@
+ android:layout_height="match_parent"
+ android:background="@color/white">
+ android:layout_marginTop="@dimen/margin_medium"
+ android:divider="@drawable/people_list_divider" />
diff --git a/WordPress/src/main/res/layout/people_list_row.xml b/WordPress/src/main/res/layout/people_list_row.xml
index 45417b26d3c6..8a7c678a524b 100644
--- a/WordPress/src/main/res/layout/people_list_row.xml
+++ b/WordPress/src/main/res/layout/people_list_row.xml
@@ -1,56 +1,32 @@
-
-
-
+ android:textColor="@color/grey"
+ android:textSize="@dimen/text_sz_small"
+ tools:text="role"/>
-
-
-
+ android:layout_toLeftOf="@id/person_role"
+ android:layout_toStartOf="@id/person_role"/>
diff --git a/WordPress/src/main/res/layout/people_management_activity.xml b/WordPress/src/main/res/layout/people_management_activity.xml
index f78b1f2c997e..c03271ff8614 100644
--- a/WordPress/src/main/res/layout/people_management_activity.xml
+++ b/WordPress/src/main/res/layout/people_management_activity.xml
@@ -1,6 +1,16 @@
-
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/layout/person_detail.xml b/WordPress/src/main/res/layout/person_detail.xml
new file mode 100644
index 000000000000..352ab2a6eaeb
--- /dev/null
+++ b/WordPress/src/main/res/layout/person_detail.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WordPress/src/main/res/layout/person_detail_fragment.xml b/WordPress/src/main/res/layout/person_detail_fragment.xml
index 17ddd3ee5f5d..f872141cd396 100644
--- a/WordPress/src/main/res/layout/person_detail_fragment.xml
+++ b/WordPress/src/main/res/layout/person_detail_fragment.xml
@@ -1,97 +1,63 @@
+ android:background="@color/white"
+ android:clickable="true">
-
+ layout="@layout/person_detail"/>
-
+
+ android:textSize="@dimen/text_sz_large"
+ tools:text="@string/role"/>
-
-
+ tools:text="@string/role"/>
-
+
-
-
-
+ android:layout_height="@dimen/people_list_divider_height"
+ android:layout_below="@id/person_role_container"
+ android:background="@color/grey_lighten_20"/>
-
+
diff --git a/WordPress/src/main/res/layout/role_list_row.xml b/WordPress/src/main/res/layout/role_list_row.xml
new file mode 100644
index 000000000000..07891321dafd
--- /dev/null
+++ b/WordPress/src/main/res/layout/role_list_row.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
diff --git a/WordPress/src/main/res/menu/person_detail.xml b/WordPress/src/main/res/menu/person_detail.xml
new file mode 100644
index 000000000000..0d5fa9557ef0
--- /dev/null
+++ b/WordPress/src/main/res/menu/person_detail.xml
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/WordPress/src/main/res/values/dimens.xml b/WordPress/src/main/res/values/dimens.xml
index c024e456126d..251ea322adab 100644
--- a/WordPress/src/main/res/values/dimens.xml
+++ b/WordPress/src/main/res/values/dimens.xml
@@ -275,6 +275,9 @@
5dp
- 84dp
+ 40dp
+ 72dp
+ 20dp
1dp
+ 72dp
diff --git a/WordPress/src/main/res/values/roles.xml b/WordPress/src/main/res/values/roles.xml
index 6d454c26ee33..db9574b9de74 100644
--- a/WordPress/src/main/res/values/roles.xml
+++ b/WordPress/src/main/res/values/roles.xml
@@ -1,6 +1,6 @@
-
+
-
Administrator
diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml
index 50e7d0d371c6..65972e770d7d 100644
--- a/WordPress/src/main/res/values/strings.xml
+++ b/WordPress/src/main/res/values/strings.xml
@@ -1023,6 +1023,9 @@
Couldn\'t retrieve site info
Couldn\'t save site info
This post or page was published on another site
+ Couldn\'t retrieve users for the site
+ Couldn\'t update role of the user
+ Couldn\'t remove user
Add media
@@ -1363,7 +1366,10 @@
People
Edit User
Role
- REMOVE %s
+ Remove %1$s
+ If you remove %1$s, that user will no longer be able to access this site, but any content that was created by %1$s will remain on the site.\n\nWould you still like to remove this user?
+ Successfully removed @%1$s
+ User removed successfully
My Profile