feat: Roles and Permission
diff --git a/app/src/main/java/com/mifos/apache/fineract/data/datamanager/DataManagerRoles.java b/app/src/main/java/com/mifos/apache/fineract/data/datamanager/DataManagerRoles.java
new file mode 100644
index 0000000..e1ea804
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/data/datamanager/DataManagerRoles.java
@@ -0,0 +1,36 @@
+package com.mifos.apache.fineract.data.datamanager;
+
+import com.mifos.apache.fineract.data.local.PreferencesHelper;
+import com.mifos.apache.fineract.data.models.rolesandpermission.Role;
+import com.mifos.apache.fineract.data.remote.BaseApiManager;
+
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import io.reactivex.Observable;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+@Singleton
+public class DataManagerRoles extends MifosBaseDataManager {
+
+ private final BaseApiManager baseApiManager;
+ private final PreferencesHelper preferencesHelper;
+
+ @Inject
+ public DataManagerRoles(BaseApiManager baseApiManager,
+ DataManagerAuth dataManagerAuth, PreferencesHelper preferencesHelper) {
+ super(dataManagerAuth, preferencesHelper);
+ this.baseApiManager = baseApiManager;
+ this.preferencesHelper = preferencesHelper;
+ }
+
+ public Observable<List<Role>> getRoles() {
+ return authenticatedObservableApi(
+ baseApiManager.getRolesAndPermissionsService().getRoles());
+ }
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/AllowedOperation.java b/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/AllowedOperation.java
new file mode 100644
index 0000000..e1d36cc
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/AllowedOperation.java
@@ -0,0 +1,19 @@
+package com.mifos.apache.fineract.data.models.rolesandpermission;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public enum AllowedOperation {
+
+ @SerializedName("READ")
+ READ, //GET, HEAD
+
+ @SerializedName("CHANGE")
+ CHANGE, //POST, PUT
+
+ @SerializedName("DELETE")
+ DELETE //DELETE
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/Permission.java b/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/Permission.java
new file mode 100644
index 0000000..fbf4c20
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/Permission.java
@@ -0,0 +1,73 @@
+package com.mifos.apache.fineract.data.models.rolesandpermission;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public class Permission implements Parcelable {
+
+ @SerializedName("permittableEndpointGroupIdentifier")
+ private String permittableEndpointGroupIdentifier;
+
+ @SerializedName("allowedOperations")
+ private List<AllowedOperation> allowedOperations;
+
+ public String getPermittableEndpointGroupIdentifier() {
+ return permittableEndpointGroupIdentifier;
+ }
+
+ public void setPermittableEndpointGroupIdentifier(String permittableEndpointGroupIdentifier) {
+ this.permittableEndpointGroupIdentifier = permittableEndpointGroupIdentifier;
+ }
+
+ public List<AllowedOperation> getAllowedOperations() {
+ return allowedOperations;
+ }
+
+ public void setAllowedOperations(
+ List<AllowedOperation> allowedOperations) {
+ this.allowedOperations = allowedOperations;
+ }
+
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.permittableEndpointGroupIdentifier);
+ dest.writeList(this.allowedOperations);
+ }
+
+ public Permission() {
+ }
+
+ protected Permission(Parcel in) {
+ this.permittableEndpointGroupIdentifier = in.readString();
+ this.allowedOperations = new ArrayList<AllowedOperation>();
+ in.readList(this.allowedOperations, AllowedOperation.class.getClassLoader());
+ }
+
+ public static final Parcelable.Creator<Permission> CREATOR =
+ new Parcelable.Creator<Permission>() {
+ @Override
+ public Permission createFromParcel(Parcel source) {
+ return new Permission(source);
+ }
+
+ @Override
+ public Permission[] newArray(int size) {
+ return new Permission[size];
+ }
+ };
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/Role.java b/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/Role.java
new file mode 100644
index 0000000..acfedaf
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/data/models/rolesandpermission/Role.java
@@ -0,0 +1,69 @@
+package com.mifos.apache.fineract.data.models.rolesandpermission;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public class Role implements Parcelable {
+
+ @SerializedName("identifier")
+ private String identifier;
+
+ @SerializedName("permissions")
+ private List<Permission> permissions;
+
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ public void setIdentifier(String identifier) {
+ this.identifier = identifier;
+ }
+
+ public List<Permission> getPermissions() {
+ return permissions;
+ }
+
+ public void setPermissions(
+ List<Permission> permissions) {
+ this.permissions = permissions;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.identifier);
+ dest.writeTypedList(this.permissions);
+ }
+
+ public Role() {
+ }
+
+ protected Role(Parcel in) {
+ this.identifier = in.readString();
+ this.permissions = in.createTypedArrayList(Permission.CREATOR);
+ }
+
+ public static final Parcelable.Creator<Role> CREATOR = new Parcelable.Creator<Role>() {
+ @Override
+ public Role createFromParcel(Parcel source) {
+ return new Role(source);
+ }
+
+ @Override
+ public Role[] newArray(int size) {
+ return new Role[size];
+ }
+ };
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/data/remote/BaseApiManager.java b/app/src/main/java/com/mifos/apache/fineract/data/remote/BaseApiManager.java
index 678e965..085aef8 100644
--- a/app/src/main/java/com/mifos/apache/fineract/data/remote/BaseApiManager.java
+++ b/app/src/main/java/com/mifos/apache/fineract/data/remote/BaseApiManager.java
@@ -8,6 +8,7 @@
import com.mifos.apache.fineract.data.services.DepositService;
import com.mifos.apache.fineract.data.services.IndividualLendingService;
import com.mifos.apache.fineract.data.services.LoanService;
+import com.mifos.apache.fineract.data.services.RolesService;
import java.util.concurrent.TimeUnit;
@@ -33,6 +34,7 @@
private static LoanService loanApi;
private static IndividualLendingService individualLendingService;
private static AnonymousService anonymousService;
+ private static RolesService rolesService;
public BaseApiManager(Context context) {
@@ -46,6 +48,7 @@
depositApi = createApi(DepositService.class);
loanApi = createApi(LoanService.class);
individualLendingService = createApi(IndividualLendingService.class);
+ rolesService = createApi(RolesService.class);
}
private static void initAnonymous() {
@@ -121,4 +124,8 @@
public AnonymousService getAnonymousService() {
return anonymousService;
}
+
+ public RolesService getRolesAndPermissionsService() {
+ return rolesService;
+ }
}
diff --git a/app/src/main/java/com/mifos/apache/fineract/data/services/RolesService.java b/app/src/main/java/com/mifos/apache/fineract/data/services/RolesService.java
new file mode 100644
index 0000000..377c8e9
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/data/services/RolesService.java
@@ -0,0 +1,19 @@
+package com.mifos.apache.fineract.data.services;
+
+import com.mifos.apache.fineract.data.models.rolesandpermission.Role;
+import com.mifos.apache.fineract.data.remote.EndPoints;
+
+import java.util.List;
+
+import io.reactivex.Observable;
+import retrofit2.http.GET;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public interface RolesService {
+
+ @GET(EndPoints.API_IDENTITY_PATH + "/roles")
+ Observable<List<Role>> getRoles();
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/injection/component/ActivityComponent.java b/app/src/main/java/com/mifos/apache/fineract/injection/component/ActivityComponent.java
index 8d8c3b2..277ca5e 100644
--- a/app/src/main/java/com/mifos/apache/fineract/injection/component/ActivityComponent.java
+++ b/app/src/main/java/com/mifos/apache/fineract/injection/component/ActivityComponent.java
@@ -34,6 +34,7 @@
import com.mifos.apache.fineract.ui.online.loanaccounts.loandetails.CustomerLoanDetailsFragment;
import com.mifos.apache.fineract.ui.online.login.LoginActivity;
import com.mifos.apache.fineract.ui.online.loanaccounts.plannedpayment.PlannedPaymentFragment;
+import com.mifos.apache.fineract.ui.online.roles.roleslist.RolesFragment;
import dagger.Subcomponent;
@@ -97,4 +98,6 @@
void inject(CustomerActivitiesFragment customerActivitiesFragment);
void inject(DashboardActivity dashboardActivity);
+
+ void inject(RolesFragment rolesFragment);
}
diff --git a/app/src/main/java/com/mifos/apache/fineract/injection/component/ApplicationComponent.java b/app/src/main/java/com/mifos/apache/fineract/injection/component/ApplicationComponent.java
index 0f143f7..a546b6f 100644
--- a/app/src/main/java/com/mifos/apache/fineract/injection/component/ApplicationComponent.java
+++ b/app/src/main/java/com/mifos/apache/fineract/injection/component/ApplicationComponent.java
@@ -10,6 +10,7 @@
import com.mifos.apache.fineract.data.datamanager.DataManagerDeposit;
import com.mifos.apache.fineract.data.datamanager.DataManagerIndividualLending;
import com.mifos.apache.fineract.data.datamanager.DataManagerLoans;
+import com.mifos.apache.fineract.data.datamanager.DataManagerRoles;
import com.mifos.apache.fineract.data.local.PreferencesHelper;
import com.mifos.apache.fineract.data.remote.BaseApiManager;
import com.mifos.apache.fineract.data.remote.MifosInterceptor;
@@ -34,6 +35,7 @@
DataManagerLoans dataManagerLoans();
DataManagerIndividualLending dataManagerIndividualLending();
DataManagerAnonymous dataManagerAnonymous();
+ DataManagerRoles dataManagerRolesAndPermissions();
BaseApiManager baseApiManager();
PreferencesHelper preferencesHelper();
diff --git a/app/src/main/java/com/mifos/apache/fineract/ui/adapters/RolesAdapter.java b/app/src/main/java/com/mifos/apache/fineract/ui/adapters/RolesAdapter.java
new file mode 100644
index 0000000..76a9d92
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/ui/adapters/RolesAdapter.java
@@ -0,0 +1,108 @@
+package com.mifos.apache.fineract.ui.adapters;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.mifos.apache.fineract.R;
+import com.mifos.apache.fineract.data.models.rolesandpermission.Role;
+import com.mifos.apache.fineract.injection.ApplicationContext;
+import com.mifos.apache.fineract.ui.base.OnItemClickListener;
+import com.mifos.apache.fineract.ui.views.TextDrawable;
+import com.mifos.apache.fineract.utils.ColorGenerator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public class RolesAdapter extends RecyclerView.Adapter<RolesAdapter.ViewHolder> {
+
+ private Context context;
+ private List<Role> roles;
+ private ColorGenerator colorGenerator;
+ private OnItemClickListener onItemClickListener;
+
+ @Inject
+ public RolesAdapter(@ApplicationContext Context context) {
+ this.context = context;
+ colorGenerator = ColorGenerator.MATERIAL;
+ roles = new ArrayList<>();
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.item_roles, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ Role role = roles.get(position);
+
+ TextDrawable drawable = TextDrawable.builder()
+ .beginConfig().toUpperCase().endConfig()
+ .buildRound(role.getIdentifier().substring(0, 1),
+ colorGenerator.getColor(role.getIdentifier()));
+ holder.ivRole.setImageDrawable(drawable);
+
+ holder.tvRoleName.setText(role.getIdentifier());
+ }
+
+ @Override
+ public int getItemCount() {
+ return roles.size();
+ }
+
+ public void setRoles(List<Role> roles) {
+ this.roles = roles;
+ notifyDataSetChanged();
+ }
+
+ public void setOnItemClickListener(OnItemClickListener itemClickListener) {
+ onItemClickListener = itemClickListener;
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
+ View.OnLongClickListener {
+
+ @BindView(R.id.iv_role)
+ ImageView ivRole;
+
+ @BindView(R.id.tv_role_name)
+ TextView tvRoleName;
+
+ @BindView(R.id.ll_role)
+ LinearLayout llRole;
+
+ public ViewHolder(View v) {
+ super(v);
+ ButterKnife.bind(this, v);
+ llRole.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ onItemClickListener.onItemClick(v, getAdapterPosition());
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ onItemClickListener.onItemLongPress(v, getAdapterPosition());
+ return true;
+ }
+ }
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/ui/online/DashboardActivity.java b/app/src/main/java/com/mifos/apache/fineract/ui/online/DashboardActivity.java
index dec9b29..cbc4e28 100644
--- a/app/src/main/java/com/mifos/apache/fineract/ui/online/DashboardActivity.java
+++ b/app/src/main/java/com/mifos/apache/fineract/ui/online/DashboardActivity.java
@@ -18,6 +18,7 @@
import com.mifos.apache.fineract.ui.online.customers.customerlist.CustomersFragment;
import com.mifos.apache.fineract.ui.online.dashboard.DashboardFragment;
import com.mifos.apache.fineract.ui.online.launcher.LauncherActivity;
+import com.mifos.apache.fineract.ui.online.roles.roleslist.RolesFragment;
import com.mifos.apache.fineract.utils.MaterialDialog;
import javax.inject.Inject;
@@ -92,6 +93,9 @@
case R.id.item_dashboard:
replaceFragment(DashboardFragment.newInstance(), true, R.id.container);
break;
+ case R.id.item_roles:
+ replaceFragment(RolesFragment.newInstance(), true, R.id.container);
+ break;
case R.id.item_customer:
replaceFragment(CustomersFragment.newInstance(), true, R.id.container);
break;
diff --git a/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesContract.java b/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesContract.java
new file mode 100644
index 0000000..b93cc7d
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesContract.java
@@ -0,0 +1,35 @@
+package com.mifos.apache.fineract.ui.online.roles.roleslist;
+
+import com.mifos.apache.fineract.data.models.rolesandpermission.Role;
+import com.mifos.apache.fineract.ui.base.MvpView;
+
+import java.util.List;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public interface RolesContract {
+
+ interface View extends MvpView {
+
+ void showUserInterface();
+
+ void showRoles(List<Role> roles);
+
+ void showEmptyRoles();
+
+ void showRecyclerView(Boolean status);
+
+ void showProgressbar();
+
+ void hideProgressbar();
+
+ void showError(String message);
+ }
+
+ interface Presenter {
+
+ void fetchRoles();
+ }
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesFragment.java b/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesFragment.java
new file mode 100644
index 0000000..36e24ea
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesFragment.java
@@ -0,0 +1,170 @@
+package com.mifos.apache.fineract.ui.online.roles.roleslist;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.mifos.apache.fineract.R;
+import com.mifos.apache.fineract.data.models.rolesandpermission.Role;
+import com.mifos.apache.fineract.ui.adapters.RolesAdapter;
+import com.mifos.apache.fineract.ui.base.MifosBaseActivity;
+import com.mifos.apache.fineract.ui.base.MifosBaseFragment;
+import com.mifos.apache.fineract.ui.base.OnItemClickListener;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+public class RolesFragment extends MifosBaseFragment implements RolesContract.View,
+ OnItemClickListener, SwipeRefreshLayout.OnRefreshListener {
+
+ @BindView(R.id.rv_roles)
+ RecyclerView rvRoles;
+
+ @BindView(R.id.swipe_container)
+ SwipeRefreshLayout swipeRefreshLayout;
+
+ @BindView(R.id.rl_error)
+ RelativeLayout rlError;
+
+ @BindView(R.id.iv_retry)
+ ImageView ivRetry;
+
+ @BindView(R.id.tv_error)
+ TextView tvError;
+
+ View rootView;
+
+ @Inject
+ RolesPresenter rolesPresenter;
+
+ @Inject
+ RolesAdapter rolesAdapter;
+
+ public static RolesFragment newInstance() {
+ RolesFragment fragment = new RolesFragment();
+ Bundle args = new Bundle();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ rootView = inflater.inflate(R.layout.fragment_roles_list, container, false);
+ ((MifosBaseActivity) getActivity()).getActivityComponent().inject(this);
+ ButterKnife.bind(this, rootView);
+ rolesPresenter.attachView(this);
+ setToolbarTitle(getString(R.string.manage_roles));
+
+ showUserInterface();
+
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ rolesPresenter.fetchRoles();
+ }
+
+ @Override
+ public void onRefresh() {
+ rolesPresenter.fetchRoles();
+ }
+
+ @OnClick(R.id.iv_retry)
+ void reloadRoles() {
+ rlError.setVisibility(View.GONE);
+ rvRoles.setVisibility(View.GONE);
+ rolesPresenter.fetchRoles();
+ }
+
+ @Override
+ public void showUserInterface() {
+ LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
+ layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
+ rvRoles.setLayoutManager(layoutManager);
+ rvRoles.setHasFixedSize(true);
+ rolesAdapter.setOnItemClickListener(this);
+ rvRoles.setAdapter(rolesAdapter);
+ swipeRefreshLayout.setColorSchemeColors(getActivity()
+ .getResources().getIntArray(R.array.swipeRefreshColors));
+ swipeRefreshLayout.setOnRefreshListener(this);
+ }
+
+ @Override
+ public void showRoles(List<Role> roles) {
+ showRecyclerView(true);
+ rolesAdapter.setRoles(roles);
+ }
+
+ @Override
+ public void showEmptyRoles() {
+ showRecyclerView(false);
+ tvError.setText(R.string.empty_roles);
+ ivRetry.setImageDrawable(ContextCompat.getDrawable(getActivity(),
+ R.drawable.ic_assignment_turned_in_black_24dp));
+ }
+
+ @Override
+ public void showRecyclerView(Boolean status) {
+ if (status) {
+ rvRoles.setVisibility(View.VISIBLE);
+ rlError.setVisibility(View.GONE);
+ } else {
+ rvRoles.setVisibility(View.GONE);
+ rlError.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void showProgressbar() {
+ swipeRefreshLayout.setRefreshing(true);
+ }
+
+ @Override
+ public void hideProgressbar() {
+ swipeRefreshLayout.setRefreshing(false);
+ }
+
+ @Override
+ public void showError(String message) {
+ showRecyclerView(false);
+ tvError.setText(message);
+ }
+
+ @Override
+ public void onItemClick(View childView, int position) {
+
+ }
+
+ @Override
+ public void onItemLongPress(View childView, int position) {
+
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ rolesPresenter.detachView();
+ }
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesPresenter.java b/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesPresenter.java
new file mode 100644
index 0000000..278c259
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/ui/online/roles/roleslist/RolesPresenter.java
@@ -0,0 +1,71 @@
+package com.mifos.apache.fineract.ui.online.roles.roleslist;
+
+import android.content.Context;
+
+import com.mifos.apache.fineract.R;
+import com.mifos.apache.fineract.data.datamanager.DataManagerRoles;
+import com.mifos.apache.fineract.data.models.rolesandpermission.Role;
+import com.mifos.apache.fineract.injection.ApplicationContext;
+import com.mifos.apache.fineract.injection.ConfigPersistent;
+import com.mifos.apache.fineract.ui.base.BasePresenter;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * @author Rajan Maurya
+ * On 24/08/17.
+ */
+@ConfigPersistent
+public class RolesPresenter extends BasePresenter<RolesContract.View>
+ implements RolesContract.Presenter {
+
+ private final DataManagerRoles dataManagerRoles;
+ private CompositeDisposable compositeDisposable;
+
+ @Inject
+ protected RolesPresenter(@ApplicationContext Context context,
+ DataManagerRoles dataManagerRoles) {
+ super(context);
+ this.dataManagerRoles = dataManagerRoles;
+ compositeDisposable = new CompositeDisposable();
+ }
+
+ @Override
+ public void fetchRoles() {
+ checkViewAttached();
+ getMvpView().showProgressbar();
+ compositeDisposable.add(dataManagerRoles.getRoles()
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribeWith(new DisposableObserver<List<Role>>() {
+ @Override
+ public void onNext(List<Role> roles) {
+ getMvpView().hideProgressbar();
+ if (!roles.isEmpty()) {
+ getMvpView().showRoles(roles);
+ } else {
+ getMvpView().showEmptyRoles();
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ getMvpView().hideProgressbar();
+ getMvpView().showError(context.getString(R.string.error_fetching_roles));
+ }
+
+ @Override
+ public void onComplete() {
+
+ }
+ })
+ );
+ }
+}
diff --git a/app/src/main/java/com/mifos/apache/fineract/ui/views/TextDrawable.java b/app/src/main/java/com/mifos/apache/fineract/ui/views/TextDrawable.java
index 521ef91..d4e65cb 100644
--- a/app/src/main/java/com/mifos/apache/fineract/ui/views/TextDrawable.java
+++ b/app/src/main/java/com/mifos/apache/fineract/ui/views/TextDrawable.java
@@ -275,44 +275,44 @@
}
public interface IConfigBuilder {
- public IConfigBuilder width(int width);
+ IConfigBuilder width(int width);
- public IConfigBuilder height(int height);
+ IConfigBuilder height(int height);
- public IConfigBuilder textColor(int color);
+ IConfigBuilder textColor(int color);
- public IConfigBuilder withBorder(int thickness);
+ IConfigBuilder withBorder(int thickness);
- public IConfigBuilder useFont(Typeface font);
+ IConfigBuilder useFont(Typeface font);
- public IConfigBuilder fontSize(int size);
+ IConfigBuilder fontSize(int size);
- public IConfigBuilder bold();
+ IConfigBuilder bold();
- public IConfigBuilder toUpperCase();
+ IConfigBuilder toUpperCase();
- public IShapeBuilder endConfig();
+ IShapeBuilder endConfig();
}
public static interface IBuilder {
- public TextDrawable build(String text, int color);
+ TextDrawable build(String text, int color);
}
public static interface IShapeBuilder {
- public IConfigBuilder beginConfig();
+ IConfigBuilder beginConfig();
- public IBuilder rect();
+ IBuilder rect();
- public IBuilder round();
+ IBuilder round();
- public IBuilder roundRect(int radius);
+ IBuilder roundRect(int radius);
- public TextDrawable buildRect(String text, int color);
+ TextDrawable buildRect(String text, int color);
- public TextDrawable buildRoundRect(String text, int color, int radius);
+ TextDrawable buildRoundRect(String text, int color, int radius);
- public TextDrawable buildRound(String text, int color);
+ TextDrawable buildRound(String text, int color);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mifos/apache/fineract/utils/ColorGenerator.java b/app/src/main/java/com/mifos/apache/fineract/utils/ColorGenerator.java
new file mode 100644
index 0000000..eb59645
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/utils/ColorGenerator.java
@@ -0,0 +1,65 @@
+package com.mifos.apache.fineract.utils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+public class ColorGenerator {
+
+ public static final ColorGenerator DEFAULT;
+
+ public static final ColorGenerator MATERIAL;
+
+ static {
+ DEFAULT = create(Arrays.asList(
+ 0xfff16364,
+ 0xfff58559,
+ 0xfff9a43e,
+ 0xffe4c62e,
+ 0xff67bf74,
+ 0xff59a2be,
+ 0xff2093cd,
+ 0xffad62a7,
+ 0xff805781
+ ));
+ MATERIAL = create(Arrays.asList(
+ 0xffe57373,
+ 0xfff06292,
+ 0xffba68c8,
+ 0xff9575cd,
+ 0xff7986cb,
+ 0xff64b5f6,
+ 0xff4fc3f7,
+ 0xff4dd0e1,
+ 0xff4db6ac,
+ 0xff81c784,
+ 0xffaed581,
+ 0xffff8a65,
+ 0xffd4e157,
+ 0xffffd54f,
+ 0xffffb74d,
+ 0xffa1887f,
+ 0xff90a4ae
+ ));
+ }
+
+ private final List<Integer> colors;
+ private final Random random;
+
+ public static ColorGenerator create(List<Integer> colorList) {
+ return new ColorGenerator(colorList);
+ }
+
+ private ColorGenerator(List<Integer> colorList) {
+ colors = colorList;
+ random = new Random(System.currentTimeMillis());
+ }
+
+ public int getRandomColor() {
+ return colors.get(random.nextInt(colors.size()));
+ }
+
+ public int getColor(Object key) {
+ return colors.get(Math.abs(key.hashCode()) % colors.size());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/mifos/apache/fineract/utils/ScrollFabBehavior.java b/app/src/main/java/com/mifos/apache/fineract/utils/ScrollFabBehavior.java
new file mode 100644
index 0000000..82ad339
--- /dev/null
+++ b/app/src/main/java/com/mifos/apache/fineract/utils/ScrollFabBehavior.java
@@ -0,0 +1,45 @@
+package com.mifos.apache.fineract.utils;
+
+import android.content.Context;
+import android.support.design.widget.CoordinatorLayout;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class ScrollFabBehavior extends FloatingActionButton.Behavior {
+
+ public ScrollFabBehavior(Context context, AttributeSet attrs) {
+ super();
+ }
+
+ @Override
+ public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
+ FloatingActionButton child, View directTargetChild,
+ View target, int nestedScrollAxes) {
+ return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
+ super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target,
+ nestedScrollAxes);
+ }
+
+ @Override
+ public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
+ View target, int dxConsumed, int dyConsumed, int dxUnconsumed,
+ int dyUnconsumed) {
+ super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
+ dyUnconsumed);
+ if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
+ // Reason to set fab visiblity as INVISIBLE :
+ // https://stackoverflow.com/a/41386278/4672688
+ child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
+ @Override
+ public void onHidden(FloatingActionButton fab) {
+ super.onHidden(fab);
+ fab.setVisibility(View.INVISIBLE);
+ }
+ });
+ } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
+ child.show();
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_roles_list.xml b/app/src/main/res/layout/fragment_roles_list.xml
new file mode 100644
index 0000000..c422a41
--- /dev/null
+++ b/app/src/main/res/layout/fragment_roles_list.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.design.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+
+ <android.support.v4.widget.SwipeRefreshLayout
+ android:id="@+id/swipe_container"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/rv_roles"
+ android:layout_centerHorizontal="true"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layout_width="wrap_content"/>
+ </android.support.v4.widget.SwipeRefreshLayout>
+
+ <include
+ layout="@layout/layout_error"
+ android:id="@+id/rl_error"
+ android:visibility="gone"/>
+
+ <android.support.design.widget.FloatingActionButton
+ android:clickable="true"
+ android:id="@+id/fab_add_role"
+ android:layout_gravity="bottom|end"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/layout_padding_16dp"
+ android:layout_width="wrap_content"
+ app:layout_behavior="com.mifos.apache.fineract.utils.ScrollFabBehavior"
+ app:srcCompat="@drawable/ic_add_black_24dp"/>
+
+</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_roles.xml b/app/src/main/res/layout/item_roles.xml
new file mode 100644
index 0000000..96c5210
--- /dev/null
+++ b/app/src/main/res/layout/item_roles.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:clickable="true"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:id="@+id/ll_role"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/layout_padding_8dp">
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/linearLayout"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/layout_padding_8dp"
+ android:layout_width="match_parent"
+ android:minHeight="?attr/listPreferredItemHeight"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:contentDescription="@string/roles"
+ android:id="@+id/iv_role"
+ android:layout_gravity="center_vertical"
+ android:layout_height="45dp"
+ android:layout_width="45dp"
+ android:layout_marginLeft="@dimen/layout_padding_16dp"
+ android:layout_marginStart="@dimen/layout_padding_16dp"
+ app:srcCompat="@drawable/ic_account_circle_black_24dp"
+ />
+
+ <LinearLayout
+ android:gravity="center_vertical"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingStart="16dp">
+
+ <TextView
+ style="@style/Base.TextAppearance.AppCompat.Medium"
+ android:ellipsize="end"
+ android:id="@+id/tv_role_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:lines="1"
+ android:textColor="@color/black"
+ tools:text="Role Name"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <View
+ android:background="#c7c6c6"
+ android:layout_height="0.2dp"
+ android:layout_width="wrap_content"/>
+
+</LinearLayout>
diff --git a/app/src/main/res/menu/menu_navigation_drawer.xml b/app/src/main/res/menu/menu_navigation_drawer.xml
index 3f4dcf4..ac89428 100644
--- a/app/src/main/res/menu/menu_navigation_drawer.xml
+++ b/app/src/main/res/menu/menu_navigation_drawer.xml
@@ -10,6 +10,13 @@
android:icon="@drawable/ic_dashboard_black_24dp"
android:id="@+id/item_dashboard"
android:title="@string/dashboard"/>
+
+ <item
+ android:checked="true"
+ android:icon="@drawable/ic_lock_black_24dp"
+ android:id="@+id/item_roles"
+ android:title="@string/roles_and_permissions"/>
+
<item
android:checked="true"
android:icon="@drawable/ic_customer_black_24dp"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bc9af44..7cb87ff 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,6 +20,7 @@
<string name="manage_loan_accounts">Manage loan accounts</string>
<string name="loan_accounts">Loan accounts</string>
<string name="deposit_accounts">Deposit accounts</string>
+ <string name="roles_and_permissions">Roles/Permissions</string>
<string name="manage_deposit_accounts">Manage deposit accounts</string>
<string name="contact_information">Contact information</string>
<string name="address">Address</string>
@@ -169,6 +170,7 @@
<string name="no_beneficiary">No beneficiaries</string>
<string name="activities_created_by_on">%1$s, %2$s</string>
<string name="logout">Logout</string>
+ <string name="manage_roles">Manage roles</string>
<!--Edit Text hint required-->
<string name="required_account">Account*</string>
@@ -199,6 +201,7 @@
<string name="empty_income_to_show">There is no income to show</string>
<string name="empty_scans_to_show">There is no scans to show</string>
<string name="empty_customer_activities">There is no activities to show</string>
+ <string name="empty_roles">There is no roles to show</string>
<!--Edit Text validations-->
<string name="value_must_greater_or_equal_to">Value must be greater than or equal to  %1$s</string>
@@ -239,6 +242,7 @@
<string name="error_creating_deposit_account">Error creating deposit account</string>
<string name="error_updating_deposit_account">Error updating deposit account</string>
<string name="error_fetching_customer_activities">Error fetching customer activities</string>
+ <string name="error_fetching_roles">Error fetching roles</string>
<!--Material Dialog-->
@@ -314,6 +318,7 @@
<string name="mifos_logo_image">Mifos logo image</string>
<string name="status_image">Status Image</string>
<string name="customer_image">Customer image</string>
+ <string name="roles">Roles</string>
<string name="calender_image">Calender image</string>
<string name="colon">: </string>
<string name="debt_income_edit_image">Debt edit delete image</string>
diff --git a/config/quality/findbugs/android-exclude-filter.xml b/config/quality/findbugs/android-exclude-filter.xml
index f549140..4dc4166 100644
--- a/config/quality/findbugs/android-exclude-filter.xml
+++ b/config/quality/findbugs/android-exclude-filter.xml
@@ -26,6 +26,12 @@
<Bug pattern="MS_MUTABLE_COLLECTION" />
</Match>
+ <!--Ignore RV_ABSOLUTE_VALUE_OF_HASHCODE in ColorGenerator-->
+ <Match>
+ <Class name="com.mifos.apache.fineract.utils.ColorGenerator"/>
+ <Bug pattern="RV_ABSOLUTE_VALUE_OF_HASHCODE" />
+ </Match>
+
<!-- Ignore DM_DEFAULT_ENCODING in TestDataFactory-->
<Match>
<Class name="com.mifos.apache.fineract.TestDataFactory" />