From 7bfdfa3223fe024b3498835ffc1d8417ae468482 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Wed, 20 May 2020 18:21:09 +0000 Subject: [PATCH] Add/Remove new member to team (#483) Search as user type, fix datalist. Code Format Fix users search theme add and remove user from team Add interface and user search and check for being team member or not bottom sheet menu and few refactors Co-authored-by: 6543 <6543@noreply.gitea.io> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitnex/GitNex/pulls/483 Reviewed-by: 6543 <6543@noreply.gitea.io> --- app/src/main/AndroidManifest.xml | 1 + .../org/mian/gitnex/actions/TeamActions.java | 154 +++++++++++++++ .../AddCollaboratorToRepositoryActivity.java | 23 +-- .../activities/AddNewTeamMemberActivity.java | 164 ++++++++++++++++ .../OrganizationTeamMembersActivity.java | 113 ++++++++--- .../UserSearchForTeamMemberAdapter.java | 184 ++++++++++++++++++ .../BottomSheetAdminUsersFragment.java | 2 +- .../BottomSheetOrganizationFragment.java | 2 +- .../BottomSheetOrganizationTeamsFragment.java | 58 ++++++ .../fragments/BottomSheetProfileFragment.java | 2 +- .../fragments/BottomSheetRepoFragment.java | 2 +- .../BottomSheetSingleIssueFragment.java | 2 +- .../org/mian/gitnex/helpers/AlertDialogs.java | 64 +++--- .../mian/gitnex/interfaces/ApiInterface.java | 9 + .../layout/activity_add_new_team_member.xml | 95 +++++++++ .../res/layout/activity_admin_get_users.xml | 1 - ...ayout.xml => bottom_sheet_admin_users.xml} | 0 ...yout.xml => bottom_sheet_organization.xml} | 0 .../bottom_sheet_organization_teams.xml | 36 ++++ ...le_layout.xml => bottom_sheet_profile.xml} | 0 ..._repo_layout.xml => bottom_sheet_repo.xml} | 0 ...yout.xml => bottom_sheet_single_issue.xml} | 0 .../res/layout/list_collaborators_search.xml | 6 + app/src/main/res/values/strings.xml | 7 + 24 files changed, 846 insertions(+), 79 deletions(-) create mode 100644 app/src/main/java/org/mian/gitnex/actions/TeamActions.java create mode 100644 app/src/main/java/org/mian/gitnex/activities/AddNewTeamMemberActivity.java create mode 100644 app/src/main/java/org/mian/gitnex/adapters/UserSearchForTeamMemberAdapter.java create mode 100644 app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationTeamsFragment.java create mode 100644 app/src/main/res/layout/activity_add_new_team_member.xml rename app/src/main/res/layout/{bottom_sheet_admin_users_layout.xml => bottom_sheet_admin_users.xml} (100%) rename app/src/main/res/layout/{bottom_sheet_organization_layout.xml => bottom_sheet_organization.xml} (100%) create mode 100644 app/src/main/res/layout/bottom_sheet_organization_teams.xml rename app/src/main/res/layout/{bottom_sheet_profile_layout.xml => bottom_sheet_profile.xml} (100%) rename app/src/main/res/layout/{bottom_sheet_repo_layout.xml => bottom_sheet_repo.xml} (100%) rename app/src/main/res/layout/{bottom_sheet_single_issue_layout.xml => bottom_sheet_single_issue.xml} (100%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 32beaf54..959ff820 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -80,6 +80,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/org/mian/gitnex/actions/TeamActions.java b/app/src/main/java/org/mian/gitnex/actions/TeamActions.java new file mode 100644 index 00000000..181851e5 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/actions/TeamActions.java @@ -0,0 +1,154 @@ +package org.mian.gitnex.actions; + +import android.content.Context; +import androidx.annotation.NonNull; +import com.google.gson.JsonElement; +import org.mian.gitnex.R; +import org.mian.gitnex.activities.AddNewTeamMemberActivity; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.Authorization; +import org.mian.gitnex.helpers.Toasty; +import org.mian.gitnex.util.TinyDB; +import retrofit2.Call; +import retrofit2.Callback; + +/** + * Author M M Arif + */ + +public class TeamActions { + + public static void removeTeamMember(final Context context, String userName, int teamId) { + + final TinyDB tinyDb = new TinyDB(context); + final String instanceUrl = tinyDb.getString("instanceUrl"); + final String loginUid = tinyDb.getString("loginUid"); + final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); + + Call call; + + call = RetrofitClient + .getInstance(instanceUrl, context) + .getApiInterface() + .removeTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName); + + call.enqueue(new Callback() { + + @Override + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + + if(response.isSuccessful()) { + + if(response.code() == 204) { + + tinyDb.putBoolean("teamActionFlag", true); + Toasty.info(context, context.getString(R.string.memberRemovedMessage)); + ((AddNewTeamMemberActivity)context).finish(); + + } + + } + else if(response.code() == 401) { + + AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle), + context.getResources().getString(R.string.alertDialogTokenRevokedMessage), + context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), + context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); + + } + else if(response.code() == 403) { + + Toasty.info(context, context.getString(R.string.authorizeError)); + + } + else if(response.code() == 404) { + + Toasty.info(context, context.getString(R.string.apiNotFound)); + + } + else { + + Toasty.info(context, context.getString(R.string.genericError)); + + } + + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + + Toasty.error(context, context.getResources().getString(R.string.genericServerResponseError)); + + } + }); + + } + + public static void addTeamMember(final Context context, String userName, int teamId) { + + final TinyDB tinyDb = new TinyDB(context); + final String instanceUrl = tinyDb.getString("instanceUrl"); + final String loginUid = tinyDb.getString("loginUid"); + final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); + + Call call; + + call = RetrofitClient + .getInstance(instanceUrl, context) + .getApiInterface() + .addTeamMember(Authorization.returnAuthentication(context, loginUid, instanceToken), teamId, userName); + + call.enqueue(new Callback() { + + @Override + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + + if(response.isSuccessful()) { + + if(response.code() == 204) { + + tinyDb.putBoolean("teamActionFlag", true); + Toasty.info(context, context.getString(R.string.memberAddedMessage)); + ((AddNewTeamMemberActivity)context).finish(); + + } + + } + else if(response.code() == 401) { + + AlertDialogs.authorizationTokenRevokedDialog(context, context.getResources().getString(R.string.alertDialogTokenRevokedTitle), + context.getResources().getString(R.string.alertDialogTokenRevokedMessage), + context.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), + context.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); + + } + else if(response.code() == 403) { + + Toasty.info(context, context.getString(R.string.authorizeError)); + + } + else if(response.code() == 404) { + + Toasty.info(context, context.getString(R.string.apiNotFound)); + + } + else { + + Toasty.info(context, context.getString(R.string.genericError)); + + } + + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + + Toasty.error(context, context.getResources().getString(R.string.genericServerResponseError)); + + } + }); + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/activities/AddCollaboratorToRepositoryActivity.java b/app/src/main/java/org/mian/gitnex/activities/AddCollaboratorToRepositoryActivity.java index 4810697e..3ef91b8b 100644 --- a/app/src/main/java/org/mian/gitnex/activities/AddCollaboratorToRepositoryActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/AddCollaboratorToRepositoryActivity.java @@ -74,16 +74,16 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity { initCloseListener(); closeActivity.setOnClickListener(onClickListener); - addCollaboratorSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_SEND) { - if(!addCollaboratorSearch.getText().toString().equals("")) { - loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), loginUid); - } + addCollaboratorSearch.setOnEditorActionListener((v, actionId, event) -> { + + if (actionId == EditorInfo.IME_ACTION_SEND) { + if(!addCollaboratorSearch.getText().toString().equals("")) { + loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), loginUid); } - return false; } + + return false; + }); } @@ -142,12 +142,7 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity { } private void initCloseListener() { - onClickListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - finish(); - } - }; + onClickListener = view -> finish(); } diff --git a/app/src/main/java/org/mian/gitnex/activities/AddNewTeamMemberActivity.java b/app/src/main/java/org/mian/gitnex/activities/AddNewTeamMemberActivity.java new file mode 100644 index 00000000..ebe8a917 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/activities/AddNewTeamMemberActivity.java @@ -0,0 +1,164 @@ +package org.mian.gitnex.activities; + +import android.content.Context; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import org.mian.gitnex.R; +import org.mian.gitnex.adapters.UserSearchForTeamMemberAdapter; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.helpers.Authorization; +import org.mian.gitnex.models.UserInfo; +import org.mian.gitnex.models.UserSearch; +import org.mian.gitnex.util.TinyDB; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class AddNewTeamMemberActivity extends BaseActivity { + + private View.OnClickListener onClickListener; + final Context ctx = this; + private Context appCtx; + private TextView addNewTeamMember; + private TextView noData; + private ProgressBar mProgressBar; + + private RecyclerView mRecyclerView; + private List dataList; + private UserSearchForTeamMemberAdapter adapter; + + private String teamId; + + @Override + protected int getLayoutResourceId() { + return R.layout.activity_add_new_team_member; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + appCtx = getApplicationContext(); + + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + + TinyDB tinyDb = new TinyDB(appCtx); + final String instanceUrl = tinyDb.getString("instanceUrl"); + final String loginUid = tinyDb.getString("loginUid"); + String repoFullName = tinyDb.getString("repoFullName"); + String[] parts = repoFullName.split("/"); + final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); + + ImageView closeActivity = findViewById(R.id.close); + addNewTeamMember = findViewById(R.id.addNewTeamMeber); + mRecyclerView = findViewById(R.id.recyclerViewUserSearch); + mProgressBar = findViewById(R.id.progress_bar); + noData = findViewById(R.id.noData); + + addNewTeamMember.requestFocus(); + assert imm != null; + imm.showSoftInput(addNewTeamMember, InputMethodManager.SHOW_IMPLICIT); + + initCloseListener(); + closeActivity.setOnClickListener(onClickListener); + + if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")) { + teamId = getIntent().getStringExtra("teamId"); + } + else { + teamId = "0"; + } + + mRecyclerView.setHasFixedSize(true); + mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx)); + + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL); + mRecyclerView.addItemDecoration(dividerItemDecoration); + + dataList = new ArrayList<>(); + + addNewTeamMember.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + if(!addNewTeamMember.getText().toString().equals("")) { + + adapter = new UserSearchForTeamMemberAdapter(dataList, ctx, Integer.parseInt(teamId)); + loadUserSearchList(instanceUrl, instanceToken, addNewTeamMember.getText().toString(), loginUid, teamId); + + } + + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void afterTextChanged(Editable s) { + } + + }); + + } + + public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, String loginUid, String teamId) { + + Call call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().getUserBySearch(Authorization.returnAuthentication(ctx, loginUid, token), searchKeyword, 10); + + call.enqueue(new Callback() { + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + + if(response.isSuccessful()) { + + assert response.body() != null; + if(response.body().getData().size() > 0) { + + dataList.clear(); + dataList.addAll(response.body().getData()); + mRecyclerView.setAdapter(adapter); + noData.setVisibility(View.GONE); + mProgressBar.setVisibility(View.GONE); + + } + else { + + noData.setVisibility(View.VISIBLE); + mProgressBar.setVisibility(View.GONE); + + } + + } + + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + Log.e("onFailure", t.toString()); + } + + }); + } + + private void initCloseListener() { + onClickListener = view -> finish(); + } + +} diff --git a/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamMembersActivity.java b/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamMembersActivity.java index 293c626c..a270ecdf 100644 --- a/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamMembersActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamMembersActivity.java @@ -1,28 +1,30 @@ package org.mian.gitnex.activities; -import androidx.annotation.Nullable; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; import android.content.Context; +import android.content.Intent; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.widget.GridView; import android.widget.ImageView; import android.widget.TextView; +import androidx.appcompat.widget.Toolbar; +import androidx.lifecycle.ViewModelProvider; import org.mian.gitnex.R; import org.mian.gitnex.adapters.TeamMembersByOrgAdapter; +import org.mian.gitnex.fragments.BottomSheetOrganizationTeamsFragment; import org.mian.gitnex.helpers.Authorization; -import org.mian.gitnex.models.UserInfo; import org.mian.gitnex.util.TinyDB; import org.mian.gitnex.viewmodels.TeamMembersByOrgViewModel; -import java.util.List; import java.util.Objects; /** * Author M M Arif */ -public class OrganizationTeamMembersActivity extends BaseActivity { +public class OrganizationTeamMembersActivity extends BaseActivity implements BottomSheetOrganizationTeamsFragment.BottomSheetListener { private TextView noDataMembers; private View.OnClickListener onClickListener; @@ -32,6 +34,8 @@ public class OrganizationTeamMembersActivity extends BaseActivity { final Context ctx = this; private Context appCtx; + private String teamId; + @Override protected int getLayoutResourceId(){ return R.layout.activity_org_team_members; @@ -42,6 +46,8 @@ public class OrganizationTeamMembersActivity extends BaseActivity { super.onCreate(savedInstanceState); appCtx = getApplicationContext(); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); TinyDB tinyDb = new TinyDB(appCtx); final String instanceUrl = tinyDb.getString("instanceUrl"); @@ -63,7 +69,6 @@ public class OrganizationTeamMembersActivity extends BaseActivity { toolbarTitle.setText(R.string.orgTeamMembers); } - String teamId; if(getIntent().getStringExtra("teamId") != null && !Objects.requireNonNull(getIntent().getStringExtra("teamId")).equals("")){ teamId = getIntent().getStringExtra("teamId"); } @@ -71,11 +76,24 @@ public class OrganizationTeamMembersActivity extends BaseActivity { teamId = "0"; } - getIntent().getStringExtra("teamId"); - //Log.i("teamId", getIntent().getStringExtra("teamId")); - assert teamId != null; - fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.valueOf(teamId)); + fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.parseInt(teamId)); + + } + + @Override + public void onResume() { + + super.onResume(); + TinyDB tinyDb = new TinyDB(appCtx); + final String instanceUrl = tinyDb.getString("instanceUrl"); + final String loginUid = tinyDb.getString("loginUid"); + final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); + + if(tinyDb.getBoolean("teamActionFlag")) { + fetchDataAsync(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), Integer.parseInt(teamId)); + tinyDb.putBoolean("teamActionFlag", false); + } } @@ -83,30 +101,65 @@ public class OrganizationTeamMembersActivity extends BaseActivity { TeamMembersByOrgViewModel teamMembersModel = new ViewModelProvider(this).get(TeamMembersByOrgViewModel.class); - teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId, ctx).observe(this, new Observer>() { - @Override - public void onChanged(@Nullable List teamMembersListMain) { - adapter = new TeamMembersByOrgAdapter(ctx, teamMembersListMain); - if(adapter.getCount() > 0) { - mGridView.setAdapter(adapter); - noDataMembers.setVisibility(View.GONE); - } - else { - adapter.notifyDataSetChanged(); - mGridView.setAdapter(adapter); - noDataMembers.setVisibility(View.VISIBLE); - } + teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId, ctx).observe(this, teamMembersListMain -> { + + adapter = new TeamMembersByOrgAdapter(ctx, teamMembersListMain); + if(adapter.getCount() > 0) { + mGridView.setAdapter(adapter); + noDataMembers.setVisibility(View.GONE); } + else { + adapter.notifyDataSetChanged(); + mGridView.setAdapter(adapter); + noDataMembers.setVisibility(View.VISIBLE); + } + }); } - private void initCloseListener() { - onClickListener = new View.OnClickListener() { - @Override - public void onClick(View view) { + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.generic_nav_dotted_menu, menu); + return true; + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + int id = item.getItemId(); + + switch(id) { + case android.R.id.home: finish(); - } - }; + return true; + case R.id.genericMenu: + BottomSheetOrganizationTeamsFragment bottomSheet = new BottomSheetOrganizationTeamsFragment(); + bottomSheet.show(getSupportFragmentManager(), "orgTeamsBottomSheet"); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + @Override + public void onButtonClicked(String text) { + + TinyDB tinyDb = new TinyDB(appCtx); + + if("newMember".equals(text)) { + Intent intent = new Intent(OrganizationTeamMembersActivity.this, AddNewTeamMemberActivity.class); + intent.putExtra("teamId", teamId); + startActivity(intent); + } + + } + + private void initCloseListener() { + onClickListener = view -> finish(); } } diff --git a/app/src/main/java/org/mian/gitnex/adapters/UserSearchForTeamMemberAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/UserSearchForTeamMemberAdapter.java new file mode 100644 index 00000000..5c65b465 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/adapters/UserSearchForTeamMemberAdapter.java @@ -0,0 +1,184 @@ +package org.mian.gitnex.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import org.mian.gitnex.R; +import org.mian.gitnex.clients.PicassoService; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.Authorization; +import org.mian.gitnex.helpers.RoundedTransformation; +import org.mian.gitnex.helpers.Toasty; +import org.mian.gitnex.models.UserInfo; +import org.mian.gitnex.util.TinyDB; +import java.util.List; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * Author M M Arif + */ + +public class UserSearchForTeamMemberAdapter extends RecyclerView.Adapter { + + private List usersSearchList; + private Context mCtx; + private int teamId; + + public UserSearchForTeamMemberAdapter(List dataList, Context mCtx, int teamId) { + this.mCtx = mCtx; + this.usersSearchList = dataList; + this.teamId = teamId; + } + + static class UserSearchViewHolder extends RecyclerView.ViewHolder { + + private ImageView userAvatar; + private TextView userFullName; + private TextView userName; + private TextView userNameMain; + private ImageView addMemberButtonAdd; + private ImageView addMemberButtonRemove; + private TextView teamId_; + + private UserSearchViewHolder(View itemView) { + + super(itemView); + userAvatar = itemView.findViewById(R.id.userAvatar); + userFullName = itemView.findViewById(R.id.userFullName); + userName = itemView.findViewById(R.id.userName); + userNameMain = itemView.findViewById(R.id.userNameMain); + addMemberButtonAdd = itemView.findViewById(R.id.addCollaboratorButtonAdd); + addMemberButtonRemove = itemView.findViewById(R.id.addCollaboratorButtonRemove); + teamId_ = itemView.findViewById(R.id.teamId); + + addMemberButtonAdd.setOnClickListener(v -> { + + Context context = v.getContext(); + + AlertDialogs.addMemberDialog(context, userNameMain.getText().toString(), + context.getResources().getString(R.string.addTeamMemberTitle), + context.getResources().getString(R.string.addTeamMemberMessage), + context.getResources().getString(R.string.addButton), + context.getResources().getString(R.string.cancelButton), Integer.parseInt(teamId_.getText().toString())); + + }); + + addMemberButtonRemove.setOnClickListener(v -> { + + Context context = v.getContext(); + + AlertDialogs.removeMemberDialog(context, userNameMain.getText().toString(), + context.getResources().getString(R.string.removeTeamMemberTitle), + context.getResources().getString(R.string.removeTeamMemberMessage), + context.getResources().getString(R.string.removeButton), + context.getResources().getString(R.string.cancelButton), Integer.parseInt(teamId_.getText().toString())); + + }); + + } + + } + + @NonNull + @Override + public UserSearchForTeamMemberAdapter.UserSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_collaborators_search, parent, false); + return new UserSearchForTeamMemberAdapter.UserSearchViewHolder(v); + } + + @Override + public void onBindViewHolder(@NonNull final UserSearchForTeamMemberAdapter.UserSearchViewHolder holder, int position) { + + final UserInfo currentItem = usersSearchList.get(position); + + holder.userNameMain.setText(currentItem.getLogin()); + holder.teamId_.setText(String.valueOf(teamId)); + + if (!currentItem.getFullname().equals("")) { + holder.userFullName.setText(currentItem.getFullname()); + holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin())); + } + else { + holder.userFullName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin())); + holder.userName.setText(mCtx.getResources().getString(R.string.usernameWithAt, currentItem.getLogin())); + } + + if (!currentItem.getAvatar().equals("")) { + PicassoService.getInstance(mCtx).get().load(currentItem.getAvatar()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.userAvatar); + } + + if(getItemCount() > 0) { + + TinyDB tinyDb = new TinyDB(mCtx); + final String instanceUrl = tinyDb.getString("instanceUrl"); + final String loginUid = tinyDb.getString("loginUid"); + String repoFullName = tinyDb.getString("repoFullName"); + String[] parts = repoFullName.split("/"); + final String repoOwner = parts[0]; + final String repoName = parts[1]; + final String instanceToken = "token " + tinyDb.getString(loginUid + "-token"); + + Call call = RetrofitClient + .getInstance(instanceUrl, mCtx) + .getApiInterface() + .checkTeamMember(Authorization.returnAuthentication(mCtx, loginUid, instanceToken), teamId, currentItem.getLogin()); + + call.enqueue(new Callback() { + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + + if(response.code() == 200) { + + if(!currentItem.getLogin().equals(loginUid) && !currentItem.getLogin().equals(repoOwner)) { + holder.addMemberButtonRemove.setVisibility(View.VISIBLE); + } + else { + holder.addMemberButtonRemove.setVisibility(View.GONE); + } + + } + else if(response.code() == 404) { + + if(!currentItem.getLogin().equals(loginUid) && !currentItem.getLogin().equals(repoOwner)) { + holder.addMemberButtonAdd.setVisibility(View.VISIBLE); + } + else { + holder.addMemberButtonAdd.setVisibility(View.GONE); + } + + } + else { + holder.addMemberButtonRemove.setVisibility(View.GONE); + holder.addMemberButtonAdd.setVisibility(View.GONE); + } + + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + + Toasty.error(mCtx, mCtx.getResources().getString(R.string.genericServerResponseError)); + + } + + }); + + } + + } + + @Override + public int getItemCount() { + return usersSearchList.size(); + } + +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetAdminUsersFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetAdminUsersFragment.java index 1438a72d..96942406 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetAdminUsersFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetAdminUsersFragment.java @@ -22,7 +22,7 @@ public class BottomSheetAdminUsersFragment extends BottomSheetDialogFragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.bottom_sheet_admin_users_layout, container, false); + View v = inflater.inflate(R.layout.bottom_sheet_admin_users, container, false); TextView createNewUser = v.findViewById(R.id.createNewUser); diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationFragment.java index 38e57a74..7abd7715 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationFragment.java @@ -22,7 +22,7 @@ public class BottomSheetOrganizationFragment extends BottomSheetDialogFragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.bottom_sheet_organization_layout, container, false); + View v = inflater.inflate(R.layout.bottom_sheet_organization, container, false); TextView createTeam = v.findViewById(R.id.createTeam); TextView createRepository = v.findViewById(R.id.createRepository); diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationTeamsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationTeamsFragment.java new file mode 100644 index 00000000..717a70c3 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetOrganizationTeamsFragment.java @@ -0,0 +1,58 @@ +package org.mian.gitnex.fragments; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; +import org.mian.gitnex.R; + +/** + * Author M M Arif + */ + +public class BottomSheetOrganizationTeamsFragment extends BottomSheetDialogFragment { + + private BottomSheetOrganizationTeamsFragment.BottomSheetListener bmListener; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + View v = inflater.inflate(R.layout.bottom_sheet_organization_teams, container, false); + + TextView addNewMember = v.findViewById(R.id.addNewMember); + + addNewMember.setOnClickListener(v1 -> { + + bmListener.onButtonClicked("newMember"); + dismiss(); + + }); + + return v; + + } + + public interface BottomSheetListener { + void onButtonClicked(String text); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + + try { + bmListener = (BottomSheetOrganizationTeamsFragment.BottomSheetListener) context; + } + catch (ClassCastException e) { + Log.e("BsOrganizationTeams", e.toString()); + } + } + +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetProfileFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetProfileFragment.java index 8c8c9368..4c635008 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetProfileFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetProfileFragment.java @@ -21,7 +21,7 @@ public class BottomSheetProfileFragment extends BottomSheetDialogFragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.bottom_sheet_profile_layout, container, false); + View v = inflater.inflate(R.layout.bottom_sheet_profile, container, false); TextView addNewEmailAddress = v.findViewById(R.id.addNewEmailAddress); diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java index d40c6cd0..ac11a1ae 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java @@ -24,7 +24,7 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.bottom_sheet_repo_layout, container, false); + View v = inflater.inflate(R.layout.bottom_sheet_repo, container, false); final TinyDB tinyDb = new TinyDB(getContext()); diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetSingleIssueFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetSingleIssueFragment.java index 7daa9360..8d1daf85 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetSingleIssueFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetSingleIssueFragment.java @@ -33,7 +33,7 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.bottom_sheet_single_issue_layout, container, false); + View v = inflater.inflate(R.layout.bottom_sheet_single_issue, container, false); final Context ctx = getContext(); final TinyDB tinyDB = new TinyDB(ctx); diff --git a/app/src/main/java/org/mian/gitnex/helpers/AlertDialogs.java b/app/src/main/java/org/mian/gitnex/helpers/AlertDialogs.java index 595a9297..ad82d98c 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/AlertDialogs.java +++ b/app/src/main/java/org/mian/gitnex/helpers/AlertDialogs.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import org.mian.gitnex.R; +import org.mian.gitnex.actions.TeamActions; import org.mian.gitnex.activities.CreateLabelActivity; import org.mian.gitnex.activities.LoginActivity; import org.mian.gitnex.actions.CollaboratorActions; @@ -25,25 +26,17 @@ public class AlertDialogs { .setMessage(message) .setCancelable(true) .setIcon(R.drawable.ic_warning) - .setNegativeButton(copyNegativeButton, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }) - .setPositiveButton(copyPositiveButton, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { + .setNegativeButton(copyNegativeButton, (dialog, which) -> dialog.dismiss()) + .setPositiveButton(copyPositiveButton, (dialog, which) -> { - final TinyDB tinyDb = new TinyDB(context); - tinyDb.putBoolean("loggedInMode", false); - tinyDb.remove("basicAuthPassword"); - tinyDb.putBoolean("basicAuthFlag", false); - Intent intent = new Intent(context, LoginActivity.class); - context.startActivity(intent); - dialog.dismiss(); + final TinyDB tinyDb = new TinyDB(context); + tinyDb.putBoolean("loggedInMode", false); + tinyDb.remove("basicAuthPassword"); + tinyDb.putBoolean("basicAuthFlag", false); + Intent intent = new Intent(context, LoginActivity.class); + context.startActivity(intent); + dialog.dismiss(); - } }); AlertDialog alertDialog = alertDialogBuilder.create(); @@ -56,15 +49,14 @@ public class AlertDialogs { .setTitle(title + labelTitle) .setMessage(message) .setIcon(R.drawable.ic_delete) - .setPositiveButton(positiveButton, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { + .setPositiveButton(positiveButton, (dialog, whichButton) -> { - Intent intent = new Intent(context, CreateLabelActivity.class); - intent.putExtra("labelId", labelId); - intent.putExtra("labelAction", "delete"); - context.startActivity(intent); + Intent intent = new Intent(context, CreateLabelActivity.class); + intent.putExtra("labelId", labelId); + intent.putExtra("labelAction", "delete"); + context.startActivity(intent); - }}) + }) .setNegativeButton(negativeButton, null).show(); } @@ -74,13 +66,27 @@ public class AlertDialogs { new AlertDialog.Builder(context) .setTitle(title + userNameMain) .setMessage(message) - .setIcon(R.drawable.ic_warning) - .setPositiveButton(positiveButton, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { + .setPositiveButton(positiveButton, (dialog, whichButton) -> CollaboratorActions.deleteCollaborator(context, searchKeyword, userNameMain)) + .setNegativeButton(negativeButton, null).show(); - CollaboratorActions.deleteCollaborator(context, searchKeyword, userNameMain); + } - }}) + public static void addMemberDialog(final Context context, final String userNameMain, String title, String message, String positiveButton, String negativeButton, int teamId) { + + new AlertDialog.Builder(context) + .setTitle(title + userNameMain) + .setMessage(message) + .setPositiveButton(positiveButton, (dialog, whichButton) -> TeamActions.addTeamMember(context, userNameMain, teamId)) + .setNegativeButton(negativeButton, null).show(); + + } + + public static void removeMemberDialog(final Context context, final String userNameMain, String title, String message, String positiveButton, String negativeButton, int teamId) { + + new AlertDialog.Builder(context) + .setTitle(title + userNameMain) + .setMessage(message) + .setPositiveButton(positiveButton, (dialog, whichButton) -> TeamActions.removeTeamMember(context, userNameMain, teamId)) .setNegativeButton(negativeButton, null).show(); } diff --git a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java index 910e2f74..54f29522 100644 --- a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java +++ b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java @@ -275,4 +275,13 @@ public interface ApiInterface { @DELETE("repos/{owner}/{repo}/issues/comments/{id}") // delete own comment from issue Call deleteComment(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("id") int commentIndex); + + @GET("teams/{teamId}/members/{username}") // check team member + Call checkTeamMember(@Header("Authorization") String token, @Path("teamId") int teamId, @Path("username") String username); + + @PUT("teams/{teamId}/members/{username}") // add new team member + Call addTeamMember(@Header("Authorization") String token, @Path("teamId") int teamId, @Path("username") String username); + + @DELETE("teams/{teamId}/members/{username}") // remove team member + Call removeTeamMember(@Header("Authorization") String token, @Path("teamId") int teamId, @Path("username") String username); } diff --git a/app/src/main/res/layout/activity_add_new_team_member.xml b/app/src/main/res/layout/activity_add_new_team_member.xml new file mode 100644 index 00000000..8c830a7c --- /dev/null +++ b/app/src/main/res/layout/activity_add_new_team_member.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_admin_get_users.xml b/app/src/main/res/layout/activity_admin_get_users.xml index 3730be65..06805643 100644 --- a/app/src/main/res/layout/activity_admin_get_users.xml +++ b/app/src/main/res/layout/activity_admin_get_users.xml @@ -18,7 +18,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/primaryBackgroundColor" - android:theme="@style/AppTheme.AppBarOverlay" tools:ignore="UnusedAttribute"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/bottom_sheet_profile_layout.xml b/app/src/main/res/layout/bottom_sheet_profile.xml similarity index 100% rename from app/src/main/res/layout/bottom_sheet_profile_layout.xml rename to app/src/main/res/layout/bottom_sheet_profile.xml diff --git a/app/src/main/res/layout/bottom_sheet_repo_layout.xml b/app/src/main/res/layout/bottom_sheet_repo.xml similarity index 100% rename from app/src/main/res/layout/bottom_sheet_repo_layout.xml rename to app/src/main/res/layout/bottom_sheet_repo.xml diff --git a/app/src/main/res/layout/bottom_sheet_single_issue_layout.xml b/app/src/main/res/layout/bottom_sheet_single_issue.xml similarity index 100% rename from app/src/main/res/layout/bottom_sheet_single_issue_layout.xml rename to app/src/main/res/layout/bottom_sheet_single_issue.xml diff --git a/app/src/main/res/layout/list_collaborators_search.xml b/app/src/main/res/layout/list_collaborators_search.xml index 520e70a9..93d01902 100644 --- a/app/src/main/res/layout/list_collaborators_search.xml +++ b/app/src/main/res/layout/list_collaborators_search.xml @@ -8,6 +8,12 @@ android:paddingEnd="20dp" android:background="?attr/primaryBackgroundColor" > + + No members found Org members Organization team members + Add / Remove New Member + Remove\u0020 + Add\u0020 + Do you want to add this user to the team? + Do you want to remove this user from the team? + Member added to the team successfully + Member removed from the team successfully