mirror of
https://github.com/gitnex-org/gitnex.git
synced 2026-06-14 16:00:30 -05:00
Refactor instance administration - settings and cron tasks
This commit is contained in:
@@ -144,9 +144,6 @@
|
||||
android:name=".activities.CreatePullRequestActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
|
||||
android:windowSoftInputMode="adjustResize"/>
|
||||
<activity
|
||||
android:name=".activities.AdminCronTasksActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
|
||||
<activity
|
||||
android:name=".activities.WikiActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
package org.mian.gitnex.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import org.mian.gitnex.adapters.AdminCronTasksAdapter;
|
||||
import org.mian.gitnex.databinding.ActivityAdminCronTasksBinding;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.viewmodels.AdminCronTasksViewModel;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class AdminCronTasksActivity extends BaseActivity {
|
||||
|
||||
private AdminCronTasksViewModel adminCronTasksViewModel;
|
||||
private View.OnClickListener onClickListener;
|
||||
private AdminCronTasksAdapter adapter;
|
||||
|
||||
private ActivityAdminCronTasksBinding activityAdminCronTasksBinding;
|
||||
|
||||
private final int PAGE = 1;
|
||||
private int resultLimit;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityAdminCronTasksBinding = ActivityAdminCronTasksBinding.inflate(getLayoutInflater());
|
||||
setContentView(activityAdminCronTasksBinding.getRoot());
|
||||
adminCronTasksViewModel = new ViewModelProvider(this).get(AdminCronTasksViewModel.class);
|
||||
|
||||
resultLimit = Constants.getCurrentResultLimit(ctx);
|
||||
initCloseListener();
|
||||
activityAdminCronTasksBinding.close.setOnClickListener(onClickListener);
|
||||
|
||||
Toolbar toolbar = activityAdminCronTasksBinding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
activityAdminCronTasksBinding.recyclerView.setHasFixedSize(true);
|
||||
activityAdminCronTasksBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
|
||||
|
||||
activityAdminCronTasksBinding.pullToRefresh.setOnRefreshListener(
|
||||
() ->
|
||||
new Handler(Looper.getMainLooper())
|
||||
.postDelayed(
|
||||
() -> {
|
||||
activityAdminCronTasksBinding.progressBar.setVisibility(
|
||||
View.VISIBLE);
|
||||
activityAdminCronTasksBinding.pullToRefresh
|
||||
.setRefreshing(false);
|
||||
adminCronTasksViewModel.loadCronTasksList(
|
||||
ctx, PAGE, resultLimit);
|
||||
},
|
||||
500));
|
||||
|
||||
fetchDataAsync(ctx);
|
||||
}
|
||||
|
||||
private void fetchDataAsync(Context ctx) {
|
||||
|
||||
adminCronTasksViewModel
|
||||
.getCronTasksList(ctx, PAGE, resultLimit)
|
||||
.observe(
|
||||
this,
|
||||
cronTasksListMain -> {
|
||||
adapter = new AdminCronTasksAdapter(cronTasksListMain);
|
||||
|
||||
if (adapter.getItemCount() > 0) {
|
||||
activityAdminCronTasksBinding.recyclerView.setAdapter(adapter);
|
||||
activityAdminCronTasksBinding.noData.setVisibility(View.GONE);
|
||||
activityAdminCronTasksBinding.progressBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
activityAdminCronTasksBinding.noData.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initCloseListener() {
|
||||
onClickListener = view -> finish();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,34 @@
|
||||
package org.mian.gitnex.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||
import org.mian.gitnex.api.clients.ApiRetrofitClient;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.gitnex.tea4j.v2.models.Cron;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.adapters.AdminCronTasksAdapter;
|
||||
import org.mian.gitnex.api.models.settings.RepositoryGlobal;
|
||||
import org.mian.gitnex.databinding.ActivityAdministrationBinding;
|
||||
import org.mian.gitnex.databinding.BottomSheetGlobalRepositorySettingsBinding;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
import org.mian.gitnex.databinding.BottomsheetAdminCronTasksBinding;
|
||||
import org.mian.gitnex.databinding.ItemAdministrationRepoSettingRowBinding;
|
||||
import org.mian.gitnex.helpers.AppUtil;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.EndlessRecyclerViewScrollListener;
|
||||
import org.mian.gitnex.helpers.TimeHelper;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import org.mian.gitnex.viewmodels.AdministrationViewModel;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
@@ -19,7 +36,8 @@ import retrofit2.Response;
|
||||
public class AdministrationActivity extends BaseActivity {
|
||||
|
||||
private ActivityAdministrationBinding binding;
|
||||
private BottomSheetDialog settingsBottomSheet;
|
||||
private AdministrationViewModel viewModel;
|
||||
private int resultLimit;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -27,80 +45,224 @@ public class AdministrationActivity extends BaseActivity {
|
||||
binding = ActivityAdministrationBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
resultLimit = Constants.getCurrentResultLimit(this);
|
||||
|
||||
viewModel = new ViewModelProvider(this).get(AdministrationViewModel.class);
|
||||
|
||||
initCards();
|
||||
setupListeners();
|
||||
handleIntentActions();
|
||||
observeViewModel();
|
||||
}
|
||||
|
||||
private void observeViewModel() {
|
||||
viewModel
|
||||
.getErrorMessage()
|
||||
.observe(
|
||||
this,
|
||||
error -> {
|
||||
if (error != null) Toasty.show(this, error);
|
||||
});
|
||||
|
||||
viewModel
|
||||
.getTaskSuccessMessage()
|
||||
.observe(
|
||||
this,
|
||||
taskName -> {
|
||||
if (taskName != null) {
|
||||
Toasty.show(
|
||||
this,
|
||||
getString(R.string.adminCronTaskSuccessMsg, taskName));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
binding.systemUsersFrame.setOnClickListener(
|
||||
v -> startActivity(new Intent(this, AdminGetUsersActivity.class)));
|
||||
binding.btnBack.setOnClickListener(v -> finish());
|
||||
|
||||
binding.adminCronFrame.setOnClickListener(
|
||||
v -> startActivity(new Intent(this, AdminCronTasksActivity.class)));
|
||||
binding.cardUsers
|
||||
.getRoot()
|
||||
.setOnClickListener(
|
||||
v -> startActivity(new Intent(this, AdminGetUsersActivity.class)));
|
||||
|
||||
binding.unadoptedReposFrame.setOnClickListener(
|
||||
v -> startActivity(new Intent(this, AdminUnadoptedReposActivity.class)));
|
||||
binding.cardCron.getRoot().setOnClickListener(v -> showCronTasksSheet());
|
||||
|
||||
binding.adminRepositoryFrame.setOnClickListener(v -> showRepositorySettings());
|
||||
binding.cardUnadopted
|
||||
.getRoot()
|
||||
.setOnClickListener(
|
||||
v -> startActivity(new Intent(this, AdminUnadoptedReposActivity.class)));
|
||||
|
||||
binding.cardRepoSettings.getRoot().setOnClickListener(v -> showRepositorySettings());
|
||||
}
|
||||
|
||||
private void handleIntentActions() {
|
||||
String action = getIntent().getStringExtra("giteaAdminAction");
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
case "users" -> startActivity(new Intent(this, AdminGetUsersActivity.class));
|
||||
case "monitor" -> startActivity(new Intent(this, AdminCronTasksActivity.class));
|
||||
}
|
||||
}
|
||||
private void showCronTasksSheet() {
|
||||
|
||||
BottomsheetAdminCronTasksBinding sheetBinding =
|
||||
BottomsheetAdminCronTasksBinding.inflate(getLayoutInflater());
|
||||
BottomSheetDialog dialog = new BottomSheetDialog(this);
|
||||
dialog.setContentView(sheetBinding.getRoot());
|
||||
AppUtil.applySheetStyle(dialog, true);
|
||||
|
||||
viewModel.resetCronPagination();
|
||||
|
||||
AdminCronTasksAdapter adapter =
|
||||
new AdminCronTasksAdapter(
|
||||
new ArrayList<>(),
|
||||
new AdminCronTasksAdapter.OnCronTaskListener() {
|
||||
@Override
|
||||
public void onRunTask(String taskName) {
|
||||
viewModel.runCronTask(AdministrationActivity.this, taskName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowDetails(Cron task) {
|
||||
showCronDetailDialog(task);
|
||||
}
|
||||
});
|
||||
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
sheetBinding.recyclerView.setLayoutManager(layoutManager);
|
||||
sheetBinding.recyclerView.setAdapter(adapter);
|
||||
|
||||
EndlessRecyclerViewScrollListener scrollListener =
|
||||
new EndlessRecyclerViewScrollListener(layoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
viewModel.fetchCronTasks(
|
||||
AdministrationActivity.this, page, resultLimit, false);
|
||||
}
|
||||
};
|
||||
sheetBinding.recyclerView.addOnScrollListener(scrollListener);
|
||||
|
||||
viewModel
|
||||
.getCronTasks()
|
||||
.observe(
|
||||
this,
|
||||
list -> {
|
||||
if (list != null) {
|
||||
adapter.updateList(list);
|
||||
}
|
||||
});
|
||||
|
||||
viewModel
|
||||
.getIsLoading()
|
||||
.observe(
|
||||
this,
|
||||
loading ->
|
||||
sheetBinding.expressiveLoader.setVisibility(
|
||||
loading ? View.VISIBLE : View.GONE));
|
||||
|
||||
viewModel.fetchCronTasks(this, 1, resultLimit, true);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void showCronDetailDialog(Cron task) {
|
||||
|
||||
View view = LayoutInflater.from(this).inflate(R.layout.layout_cron_task_info, null);
|
||||
|
||||
TextView taskScheduleContent = view.findViewById(R.id.taskScheduleContent);
|
||||
TextView nextRunContent = view.findViewById(R.id.nextRunContent);
|
||||
TextView lastRunContent = view.findViewById(R.id.lastRunContent);
|
||||
TextView execTimeContent = view.findViewById(R.id.execTimeContent);
|
||||
|
||||
Locale locale = Locale.getDefault();
|
||||
String nextRun =
|
||||
(task.getNext() != null) ? TimeHelper.getFullDateTime(task.getNext(), locale) : "";
|
||||
String lastRun =
|
||||
(task.getPrev() != null) ? TimeHelper.getFullDateTime(task.getPrev(), locale) : "";
|
||||
|
||||
taskScheduleContent.setText(task.getSchedule());
|
||||
nextRunContent.setText(nextRun);
|
||||
lastRunContent.setText(lastRun);
|
||||
execTimeContent.setText(String.valueOf(task.getExecTimes()));
|
||||
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(StringUtils.capitalize(task.getName().replace("_", " ")))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.close, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showRepositorySettings() {
|
||||
settingsBottomSheet = new BottomSheetDialog(this);
|
||||
|
||||
BottomSheetGlobalRepositorySettingsBinding sheetBinding =
|
||||
BottomSheetGlobalRepositorySettingsBinding.inflate(LayoutInflater.from(this));
|
||||
settingsBottomSheet.setContentView(sheetBinding.getRoot());
|
||||
BottomSheetGlobalRepositorySettingsBinding.inflate(getLayoutInflater());
|
||||
|
||||
loadRepositorySettings(sheetBinding);
|
||||
settingsBottomSheet.show();
|
||||
}
|
||||
BottomSheetDialog dialog = new BottomSheetDialog(this);
|
||||
dialog.setContentView(sheetBinding.getRoot());
|
||||
AppUtil.applySheetStyle(dialog, false);
|
||||
|
||||
private void loadRepositorySettings(BottomSheetGlobalRepositorySettingsBinding sheetBinding) {
|
||||
Call<RepositoryGlobal> call =
|
||||
ApiRetrofitClient.getInstance(this).getRepositoryGlobalSettings();
|
||||
sheetBinding.itemForks.settingLabel.setText(R.string.forks);
|
||||
sheetBinding.itemMigrations.settingLabel.setText(R.string.migrations);
|
||||
sheetBinding.itemHttpGit.settingLabel.setText(R.string.http_git);
|
||||
sheetBinding.itemLfs.settingLabel.setText(R.string.lfs);
|
||||
sheetBinding.itemMirrors.settingLabel.setText(R.string.mirrors);
|
||||
sheetBinding.itemTime.settingLabel.setText(R.string.time_tracking);
|
||||
sheetBinding.itemStars.settingLabel.setText(R.string.stars);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<RepositoryGlobal> call,
|
||||
@NonNull Response<RepositoryGlobal> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
updateSettingsUI(sheetBinding, response.body());
|
||||
}
|
||||
}
|
||||
viewModel
|
||||
.getRepositorySettings()
|
||||
.observe(
|
||||
this,
|
||||
settings -> {
|
||||
if (settings != null) {
|
||||
updateSettingsUI(sheetBinding, settings);
|
||||
sheetBinding.settingsContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<RepositoryGlobal> call, @NonNull Throwable t) {
|
||||
// Handle failure
|
||||
}
|
||||
});
|
||||
viewModel
|
||||
.getIsLoading()
|
||||
.observe(
|
||||
this,
|
||||
loading -> {
|
||||
sheetBinding.loadingIndicator.setVisibility(
|
||||
loading ? View.VISIBLE : View.GONE);
|
||||
if (loading) sheetBinding.settingsContainer.setVisibility(View.GONE);
|
||||
});
|
||||
|
||||
viewModel.fetchRepositoryGlobalSettings(this);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void updateSettingsUI(
|
||||
BottomSheetGlobalRepositorySettingsBinding sheetBinding, RepositoryGlobal settings) {
|
||||
sheetBinding.forksDisabledValue.setText(
|
||||
settings.isForksDisabled() ? "Disabled" : "Enabled");
|
||||
sheetBinding.migrationsDisabledValue.setText(
|
||||
settings.isMigrationsDisabled() ? "Disabled" : "Enabled");
|
||||
sheetBinding.httpGitDisabledValue.setText(
|
||||
settings.isHttpGitDisabled() ? "Disabled" : "Enabled");
|
||||
sheetBinding.lfsDisabledValue.setText(settings.isLfsDisabled() ? "Disabled" : "Enabled");
|
||||
sheetBinding.mirrorsDisabledValue.setText(
|
||||
settings.isMirrorsDisabled() ? "Disabled" : "Enabled");
|
||||
sheetBinding.timeTrackingDisabledValue.setText(
|
||||
settings.isTimeTrackingDisabled() ? "Disabled" : "Enabled");
|
||||
sheetBinding.starsDisabledValue.setText(
|
||||
settings.isStarsDisabled() ? "Disabled" : "Enabled");
|
||||
BottomSheetGlobalRepositorySettingsBinding binding, RepositoryGlobal settings) {
|
||||
applyStatusStyle(binding.itemForks, !settings.isForksDisabled());
|
||||
applyStatusStyle(binding.itemMigrations, !settings.isMigrationsDisabled());
|
||||
applyStatusStyle(binding.itemHttpGit, !settings.isHttpGitDisabled());
|
||||
applyStatusStyle(binding.itemLfs, !settings.isLfsDisabled());
|
||||
applyStatusStyle(binding.itemMirrors, !settings.isMirrorsDisabled());
|
||||
applyStatusStyle(binding.itemTime, !settings.isTimeTrackingDisabled());
|
||||
applyStatusStyle(binding.itemStars, !settings.isStarsDisabled());
|
||||
}
|
||||
|
||||
private void applyStatusStyle(
|
||||
ItemAdministrationRepoSettingRowBinding itemBinding, boolean isEnabled) {
|
||||
itemBinding.settingStatus.setText(isEnabled ? R.string.enabled : R.string.disabled);
|
||||
|
||||
if (isEnabled) {
|
||||
itemBinding.statusContainer.setCardBackgroundColor(Color.parseColor("#1A2E7D32"));
|
||||
itemBinding.settingStatus.setTextColor(ContextCompat.getColor(this, R.color.darkGreen));
|
||||
} else {
|
||||
itemBinding.statusContainer.setCardBackgroundColor(Color.parseColor("#1AC62828"));
|
||||
itemBinding.settingStatus.setTextColor(ContextCompat.getColor(this, R.color.darkRed));
|
||||
}
|
||||
}
|
||||
|
||||
private void initCards() {
|
||||
binding.cardUsers.cardIcon.setImageResource(R.drawable.ic_people);
|
||||
binding.cardUsers.cardTitle.setText(R.string.adminUsers);
|
||||
binding.cardUsers.cardSubtext.setText(R.string.adminUsersSubtext);
|
||||
|
||||
binding.cardCron.cardIcon.setImageResource(R.drawable.ic_tasks);
|
||||
binding.cardCron.cardTitle.setText(R.string.adminCron);
|
||||
binding.cardCron.cardSubtext.setText(R.string.adminCronSubtext);
|
||||
|
||||
binding.cardUnadopted.cardIcon.setImageResource(R.drawable.ic_directory_2);
|
||||
binding.cardUnadopted.cardTitle.setText(R.string.unadoptedRepos);
|
||||
binding.cardUnadopted.cardSubtext.setText(R.string.unadoptedReposSubtext);
|
||||
|
||||
binding.cardRepoSettings.cardIcon.setImageResource(R.drawable.ic_repo);
|
||||
binding.cardRepoSettings.cardTitle.setText(R.string.repoSettingsTitle);
|
||||
binding.cardRepoSettings.cardSubtext.setText(R.string.repoSettingsSubtext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,9 @@ public class AccountSettingsSSHKeysAdapter
|
||||
holder.binding.copyFrame.setOnClickListener(
|
||||
v -> {
|
||||
AppUtil.copyToClipboard(
|
||||
context, currentKey.getKey(), context.getString(R.string.copied_to_clipboard));
|
||||
context,
|
||||
currentKey.getKey(),
|
||||
context.getString(R.string.copied_to_clipboard));
|
||||
});
|
||||
|
||||
holder.binding.deleteFrame.setOnClickListener(
|
||||
|
||||
@@ -1,160 +1,72 @@
|
||||
package org.mian.gitnex.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.annotation.SuppressLint;
|
||||
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 com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.gitnex.tea4j.v2.models.Cron;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.helpers.AlertDialogs;
|
||||
import org.mian.gitnex.helpers.TimeHelper;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import org.mian.gitnex.databinding.ListAdminCronTasksBinding;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class AdminCronTasksAdapter
|
||||
extends RecyclerView.Adapter<AdminCronTasksAdapter.CronTasksViewHolder> {
|
||||
public class AdminCronTasksAdapter extends RecyclerView.Adapter<AdminCronTasksAdapter.ViewHolder> {
|
||||
|
||||
private final List<Cron> tasksList;
|
||||
private final List<Cron> tasks;
|
||||
private final OnCronTaskListener listener;
|
||||
|
||||
public static class CronTasksViewHolder extends RecyclerView.ViewHolder {
|
||||
public interface OnCronTaskListener {
|
||||
void onRunTask(String taskName);
|
||||
|
||||
private Cron cronTasks;
|
||||
|
||||
private final TextView taskName;
|
||||
|
||||
private CronTasksViewHolder(View itemView) {
|
||||
|
||||
super(itemView);
|
||||
Context ctx = itemView.getContext();
|
||||
|
||||
final Locale locale = ctx.getResources().getConfiguration().locale;
|
||||
|
||||
ImageView runTask = itemView.findViewById(R.id.runTask);
|
||||
taskName = itemView.findViewById(R.id.taskName);
|
||||
|
||||
taskName.setOnClickListener(
|
||||
taskInfo -> {
|
||||
String nextRun = "";
|
||||
String lastRun = "";
|
||||
|
||||
if (cronTasks.getNext() != null) {
|
||||
nextRun = TimeHelper.formatTime(cronTasks.getNext(), locale);
|
||||
}
|
||||
if (cronTasks.getPrev() != null) {
|
||||
lastRun = TimeHelper.formatTime(cronTasks.getPrev(), locale);
|
||||
}
|
||||
|
||||
View view =
|
||||
LayoutInflater.from(ctx)
|
||||
.inflate(R.layout.layout_cron_task_info, null);
|
||||
|
||||
TextView taskScheduleContent = view.findViewById(R.id.taskScheduleContent);
|
||||
TextView nextRunContent = view.findViewById(R.id.nextRunContent);
|
||||
TextView lastRunContent = view.findViewById(R.id.lastRunContent);
|
||||
TextView execTimeContent = view.findViewById(R.id.execTimeContent);
|
||||
|
||||
taskScheduleContent.setText(cronTasks.getSchedule());
|
||||
nextRunContent.setText(nextRun);
|
||||
lastRunContent.setText(lastRun);
|
||||
execTimeContent.setText(String.valueOf(cronTasks.getExecTimes()));
|
||||
|
||||
MaterialAlertDialogBuilder materialAlertDialogBuilder =
|
||||
new MaterialAlertDialogBuilder(ctx)
|
||||
.setTitle(
|
||||
StringUtils.capitalize(
|
||||
cronTasks.getName().replace("_", " ")))
|
||||
.setView(view)
|
||||
.setNeutralButton(ctx.getString(R.string.close), null);
|
||||
|
||||
materialAlertDialogBuilder.create().show();
|
||||
});
|
||||
|
||||
runTask.setOnClickListener(taskInfo -> runCronTask(ctx, cronTasks.getName()));
|
||||
}
|
||||
void onShowDetails(Cron task);
|
||||
}
|
||||
|
||||
public AdminCronTasksAdapter(List<Cron> tasksListMain) {
|
||||
this.tasksList = tasksListMain;
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
public void updateList(List<Cron> newList) {
|
||||
this.tasks.clear();
|
||||
this.tasks.addAll(newList);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public AdminCronTasksAdapter(List<Cron> tasks, OnCronTaskListener listener) {
|
||||
this.tasks = tasks;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public AdminCronTasksAdapter.CronTasksViewHolder onCreateViewHolder(
|
||||
@NonNull ViewGroup parent, int viewType) {
|
||||
|
||||
View v =
|
||||
LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.list_admin_cron_tasks, parent, false);
|
||||
return new AdminCronTasksAdapter.CronTasksViewHolder(v);
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
ListAdminCronTasksBinding binding =
|
||||
ListAdminCronTasksBinding.inflate(
|
||||
LayoutInflater.from(parent.getContext()), parent, false);
|
||||
return new ViewHolder(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(
|
||||
@NonNull AdminCronTasksAdapter.CronTasksViewHolder holder, int position) {
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Cron task = tasks.get(position);
|
||||
String cleanName = StringUtils.capitalize(task.getName().replace("_", " "));
|
||||
|
||||
Cron currentItem = tasksList.get(position);
|
||||
holder.binding.taskName.setText(cleanName);
|
||||
holder.binding.runTask.setOnClickListener(v -> listener.onRunTask(task.getName()));
|
||||
holder.binding.getRoot().setOnClickListener(v -> listener.onShowDetails(task));
|
||||
|
||||
holder.cronTasks = currentItem;
|
||||
holder.taskName.setText(StringUtils.capitalize(currentItem.getName().replace("_", " ")));
|
||||
}
|
||||
|
||||
private static void runCronTask(final Context ctx, final String taskName) {
|
||||
|
||||
Call<Void> call = RetrofitClient.getApiInterface(ctx).adminCronRun(taskName);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
|
||||
|
||||
switch (response.code()) {
|
||||
case 204:
|
||||
Toasty.show(
|
||||
ctx,
|
||||
ctx.getString(R.string.adminCronTaskSuccessMsg, taskName));
|
||||
break;
|
||||
|
||||
case 401:
|
||||
AlertDialogs.authorizationTokenRevokedDialog(ctx);
|
||||
break;
|
||||
|
||||
case 403:
|
||||
Toasty.show(ctx, ctx.getString(R.string.authorizeError));
|
||||
break;
|
||||
|
||||
case 404:
|
||||
Toasty.show(ctx, ctx.getString(R.string.apiNotFound));
|
||||
break;
|
||||
|
||||
default:
|
||||
Toasty.show(ctx, ctx.getString(R.string.genericError));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
|
||||
|
||||
Toasty.show(ctx, ctx.getString(R.string.genericServerResponseError));
|
||||
}
|
||||
});
|
||||
holder.binding.getRoot().updateAppearance(position, getItemCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return tasksList.size();
|
||||
return tasks.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ListAdminCronTasksBinding binding;
|
||||
|
||||
ViewHolder(ListAdminCronTasksBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
package org.mian.gitnex.viewmodels;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import java.util.List;
|
||||
import org.gitnex.tea4j.v2.models.Cron;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.helpers.AlertDialogs;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class AdminCronTasksViewModel extends ViewModel {
|
||||
|
||||
private MutableLiveData<List<Cron>> tasksList;
|
||||
|
||||
public LiveData<List<Cron>> getCronTasksList(Context ctx, int page, int limit) {
|
||||
|
||||
tasksList = new MutableLiveData<>();
|
||||
loadCronTasksList(ctx, page, limit);
|
||||
|
||||
return tasksList;
|
||||
}
|
||||
|
||||
public void loadCronTasksList(final Context ctx, int page, int limit) {
|
||||
|
||||
Call<List<Cron>> call = RetrofitClient.getApiInterface(ctx).adminCronList(page, limit);
|
||||
|
||||
call.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Cron>> call,
|
||||
@NonNull Response<List<Cron>> response) {
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
tasksList.postValue(response.body());
|
||||
} else if (response.code() == 401) {
|
||||
AlertDialogs.authorizationTokenRevokedDialog(ctx);
|
||||
} else if (response.code() == 403) {
|
||||
Toasty.show(ctx, ctx.getString(R.string.authorizeError));
|
||||
} else if (response.code() == 404) {
|
||||
Toasty.show(ctx, ctx.getString(R.string.apiNotFound));
|
||||
} else {
|
||||
Toasty.show(ctx, ctx.getString(R.string.genericError));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<Cron>> call, @NonNull Throwable t) {
|
||||
|
||||
Toasty.show(ctx, ctx.getString(R.string.genericServerResponseError));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package org.mian.gitnex.viewmodels;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.gitnex.tea4j.v2.models.Cron;
|
||||
import org.mian.gitnex.api.clients.ApiRetrofitClient;
|
||||
import org.mian.gitnex.api.models.settings.RepositoryGlobal;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class AdministrationViewModel extends ViewModel {
|
||||
|
||||
private final MutableLiveData<RepositoryGlobal> repositorySettings = new MutableLiveData<>();
|
||||
private final MutableLiveData<List<Cron>> cronTasks = new MutableLiveData<>(new ArrayList<>());
|
||||
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
||||
private final MutableLiveData<String> errorMessage = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> taskSuccessMessage = new MutableLiveData<>();
|
||||
|
||||
private int cronTotalCount = -1;
|
||||
private boolean isCronLastPage = false;
|
||||
|
||||
public LiveData<RepositoryGlobal> getRepositorySettings() {
|
||||
return repositorySettings;
|
||||
}
|
||||
|
||||
public LiveData<List<Cron>> getCronTasks() {
|
||||
return cronTasks;
|
||||
}
|
||||
|
||||
public LiveData<Boolean> getIsLoading() {
|
||||
return isLoading;
|
||||
}
|
||||
|
||||
public LiveData<String> getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public LiveData<String> getTaskSuccessMessage() {
|
||||
return taskSuccessMessage;
|
||||
}
|
||||
|
||||
public void fetchRepositoryGlobalSettings(Context context) {
|
||||
isLoading.setValue(true);
|
||||
ApiRetrofitClient.getInstance(context)
|
||||
.getRepositoryGlobalSettings()
|
||||
.enqueue(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<RepositoryGlobal> call,
|
||||
@NonNull Response<RepositoryGlobal> response) {
|
||||
isLoading.setValue(false);
|
||||
if (response.isSuccessful()) {
|
||||
repositorySettings.setValue(response.body());
|
||||
} else {
|
||||
errorMessage.setValue("Error: " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<RepositoryGlobal> call, @NonNull Throwable t) {
|
||||
isLoading.setValue(false);
|
||||
errorMessage.setValue(t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void fetchCronTasks(Context context, int page, int limit, boolean isRefresh) {
|
||||
if (Boolean.TRUE.equals(isLoading.getValue())) return;
|
||||
if (!isRefresh && isCronLastPage) return;
|
||||
|
||||
isLoading.setValue(true);
|
||||
|
||||
RetrofitClient.getApiInterface(context)
|
||||
.adminCronList(page, limit)
|
||||
.enqueue(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<List<Cron>> call,
|
||||
@NonNull Response<List<Cron>> response) {
|
||||
isLoading.setValue(false);
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
String totalHeader = response.headers().get("x-total-count");
|
||||
if (totalHeader != null) {
|
||||
cronTotalCount = Integer.parseInt(totalHeader);
|
||||
}
|
||||
|
||||
List<Cron> currentList =
|
||||
isRefresh
|
||||
? new ArrayList<>()
|
||||
: new ArrayList<>(
|
||||
Objects.requireNonNull(
|
||||
cronTasks.getValue()));
|
||||
currentList.addAll(response.body());
|
||||
cronTasks.setValue(currentList);
|
||||
|
||||
if (response.body().size() < limit
|
||||
|| currentList.size() >= cronTotalCount) {
|
||||
isCronLastPage = true;
|
||||
}
|
||||
} else {
|
||||
errorMessage.setValue("Error: " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<List<Cron>> call, @NonNull Throwable t) {
|
||||
isLoading.setValue(false);
|
||||
errorMessage.setValue(t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void resetCronPagination() {
|
||||
this.isCronLastPage = false;
|
||||
this.cronTotalCount = -1;
|
||||
this.cronTasks.setValue(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void runCronTask(Context context, String taskName) {
|
||||
isLoading.setValue(true);
|
||||
RetrofitClient.getApiInterface(context)
|
||||
.adminCronRun(taskName)
|
||||
.enqueue(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(
|
||||
@NonNull Call<Void> call, @NonNull Response<Void> response) {
|
||||
isLoading.setValue(false);
|
||||
if (response.code() == 204) {
|
||||
taskSuccessMessage.setValue(taskName);
|
||||
taskSuccessMessage.setValue(null);
|
||||
} else {
|
||||
errorMessage.setValue("Error: " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
|
||||
isLoading.setValue(false);
|
||||
errorMessage.setValue(t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,149 +4,121 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="@dimen/dimen56dp"
|
||||
android:background="?attr/primaryBackgroundColor">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="@dimen/dimen56dp"
|
||||
android:paddingBottom="@dimen/dimen84dp">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/dimen8dp">
|
||||
android:paddingHorizontal="@dimen/dimen16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/systemUsersFrame"
|
||||
android:layout_width="match_parent"
|
||||
<include
|
||||
android:id="@+id/cardUsers"
|
||||
layout="@layout/item_card_full_generic"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/dimen16dp">
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_people"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/dimen16dp"
|
||||
android:text="@string/adminUsers"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_chevron_right"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/adminCronFrame"
|
||||
android:layout_width="match_parent"
|
||||
<include
|
||||
android:id="@+id/cardCron"
|
||||
layout="@layout/item_card_full_generic"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/dimen16dp">
|
||||
android:layout_marginTop="@dimen/dimen12dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cardUsers" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_tasks"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/dimen16dp"
|
||||
android:text="@string/adminCron"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_chevron_right"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/unadoptedReposFrame"
|
||||
android:layout_width="match_parent"
|
||||
<include
|
||||
android:id="@+id/cardUnadopted"
|
||||
layout="@layout/item_card_full_generic"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/dimen16dp">
|
||||
android:layout_marginTop="@dimen/dimen12dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cardCron" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_directory_2"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/dimen16dp"
|
||||
android:text="@string/unadoptedRepos"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:srcCompat="@drawable/ic_chevron_right"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/admin_repository_frame"
|
||||
android:layout_width="match_parent"
|
||||
<include
|
||||
android:id="@+id/cardRepoSettings"
|
||||
layout="@layout/item_card_full_generic"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/dimen16dp">
|
||||
android:layout_marginTop="@dimen/dimen12dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cardUnadopted" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_repo"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/dimen16dp"
|
||||
android:text="@string/repoSettingsTitle"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<com.google.android.material.dockedtoolbar.DockedToolbarLayout
|
||||
android:id="@+id/docked_toolbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:paddingBottomSystemWindowInsets="false"
|
||||
app:paddingLeftSystemWindowInsets="false"
|
||||
app:paddingRightSystemWindowInsets="false"
|
||||
app:paddingTopSystemWindowInsets="false"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="@dimen/dimen32dp"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.RoundedDock"
|
||||
android:backgroundTint="?attr/colorSurfaceContainerHigh"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideViewOnScrollBehavior">
|
||||
|
||||
<com.google.android.material.overflow.OverflowLinearLayout
|
||||
android:id="@+id/docked_toolbar_child"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_back"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_arrow_back"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="@dimen/dimen0dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:insetLeft="@dimen/dimen0dp"
|
||||
android:insetRight="@dimen/dimen0dp"
|
||||
android:contentDescription="@string/close" />
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/dimen1dp"
|
||||
android:layout_height="@dimen/dimen24dp"
|
||||
android:layout_marginHorizontal="@dimen/dimen8dp"
|
||||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
android:background="?attr/colorOutlineVariant" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/pageTitleAdministration"
|
||||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:layout_marginStart="@dimen/dimen8dp"
|
||||
android:layout_marginEnd="@dimen/dimen8dp" />
|
||||
|
||||
</com.google.android.material.overflow.OverflowLinearLayout>
|
||||
|
||||
</com.google.android.material.dockedtoolbar.DockedToolbarLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -1,243 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/dimen16dp">
|
||||
android:paddingHorizontal="@dimen/dimen24dp"
|
||||
android:paddingBottom="@dimen/dimen32dp">
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/dimen32dp"
|
||||
android:layout_height="@dimen/dimen6dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="@dimen/dimen8dp"
|
||||
android:background="@drawable/bottom_sheet_handle"
|
||||
android:backgroundTint="?attr/primaryTextColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/milestonesFilterHeadFrame"
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerTitle"
|
||||
style="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/repoSettingsTitle"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/drag_handle" />
|
||||
|
||||
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||
android:id="@+id/loadingIndicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:indicatorSize="@dimen/dimen48dp"
|
||||
app:trackThickness="@dimen/dimen4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/headerTitle"
|
||||
android:layout_marginTop="@dimen/dimen48dp"
|
||||
android:layout_marginBottom="@dimen/dimen48dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/settingsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen16dp"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/dimen8dp">
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/headerTitle">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottomSheetHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/repoSettingsTitle"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen18sp"/>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="?attr/materialCardViewFilledStyle"
|
||||
android:layout_width="@dimen/dimen28dp"
|
||||
android:layout_height="@dimen/dimen4dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/dimen8dp"
|
||||
android:layout_marginBottom="@dimen/dimen16dp"
|
||||
app:cardCornerRadius="@dimen/dimen24dp"
|
||||
app:cardElevation="@dimen/dimen0dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/fabColor" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<include android:id="@+id/itemForks" layout="@layout/item_administration_repo_setting_row" />
|
||||
<include android:id="@+id/itemMigrations" layout="@layout/item_administration_repo_setting_row" />
|
||||
<include android:id="@+id/itemHttpGit" layout="@layout/item_administration_repo_setting_row" />
|
||||
<include android:id="@+id/itemLfs" layout="@layout/item_administration_repo_setting_row" />
|
||||
<include android:id="@+id/itemMirrors" layout="@layout/item_administration_repo_setting_row" />
|
||||
<include android:id="@+id/itemTime" layout="@layout/item_administration_repo_setting_row" />
|
||||
<include android:id="@+id/itemStars" layout="@layout/item_administration_repo_setting_row" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Forks -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/forks"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/forksDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Migrations -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/migrations"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/migrationsDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- HTTP Git -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/http_git"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/httpGitDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- LFS -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/lfs"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lfsDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Mirrors -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/mirrors"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mirrorsDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Time Tracking -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/time_tracking"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timeTrackingDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Stars -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="@dimen/dimen12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/stars"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/starsDisabledValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loading"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
49
app/src/main/res/layout/bottomsheet_admin_cron_tasks.xml
Normal file
49
app/src/main/res/layout/bottomsheet_admin_cron_tasks.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="@dimen/dimen24dp">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/adminCron"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/drag_handle" />
|
||||
|
||||
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||
android:id="@+id/expressive_loader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen24dp"
|
||||
android:layout_marginBottom="@dimen/dimen24dp"
|
||||
android:layout_gravity="center"
|
||||
app:indicatorSize="@dimen/dimen48dp"
|
||||
app:trackThickness="@dimen/dimen4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen16dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingBottom="@dimen/dimen32dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="@dimen/dimen12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settingLabel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/statusContainer"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/statusContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="@dimen/dimen24dp"
|
||||
app:cardElevation="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settingStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="@dimen/dimen16dp"
|
||||
android:paddingVertical="@dimen/dimen6dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textStyle="bold"
|
||||
android:textAllCaps="true" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
54
app/src/main/res/layout/item_card_full_generic.xml
Normal file
54
app/src/main/res/layout/item_card_full_generic.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="?attr/materialCardBackgroundColor"
|
||||
app:cardCornerRadius="@dimen/dimen32dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/dimen24dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cardIcon"
|
||||
android:layout_width="@dimen/dimen24dp"
|
||||
android:layout_height="@dimen/dimen24dp"
|
||||
android:contentDescription="@string/generalImgContentText"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/iconsColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/dimen12dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleSmall.Emphasized"
|
||||
app:layout_constraintBottom_toTopOf="@+id/cardSubtext"
|
||||
app:layout_constraintEnd_toStartOf="@+id/cardIcon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardSubtext"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen4dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:alpha=".7"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@id/cardTitle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cardTitle" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -1,97 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="25dp">
|
||||
android:padding="@dimen/dimen24dp">
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/taskScheduleHeader"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.7"
|
||||
android:text="@string/adminCronScheduleHeader"
|
||||
app:layout_constraintEnd_toStartOf="@+id/execTimeHeader"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/taskScheduleContent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen4dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="@+id/taskScheduleHeader"
|
||||
app:layout_constraintStart_toStartOf="@+id/taskScheduleHeader"
|
||||
app:layout_constraintTop_toBottomOf="@id/taskScheduleHeader" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/execTimeHeader"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.7"
|
||||
android:text="@string/adminCronExecutionHeader"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/taskScheduleHeader"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/execTimeContent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen4dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="@+id/execTimeHeader"
|
||||
app:layout_constraintStart_toStartOf="@+id/execTimeHeader"
|
||||
app:layout_constraintTop_toBottomOf="@id/execTimeHeader" />
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/taskScheduleContent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/taskScheduleHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/adminCronScheduleHeader"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/taskScheduleContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/primaryTextColor"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/nextRunHeader"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen16dp"
|
||||
android:alpha="0.7"
|
||||
android:text="@string/adminCronNextRunHeader"
|
||||
app:layout_constraintTop_toBottomOf="@id/divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextRunHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/adminCronNextRunHeader"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextRunContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/primaryTextColor"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/nextRunContent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen4dp"
|
||||
android:textColor="?attr/colorPrimary"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintTop_toBottomOf="@id/nextRunHeader" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lastRunHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/adminCronLastRunHeader"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lastRunContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/primaryTextColor"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/lastRunHeader"
|
||||
style="@style/TextAppearance.Material3.LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen16dp"
|
||||
android:alpha="0.7"
|
||||
android:text="@string/adminCronLastRunHeader"
|
||||
app:layout_constraintTop_toBottomOf="@id/nextRunContent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/execTimeHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/adminCronExecutionHeader"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="16sp"/>
|
||||
<TextView
|
||||
android:id="@+id/lastRunContent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dimen4dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/lastRunHeader" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/execTimeContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textColorLink="@color/lightBlue"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -1,46 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
<com.google.android.material.listitem.ListItemLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:paddingTop="@dimen/dimen4dp"
|
||||
android:paddingBottom="@dimen/dimen4dp">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
<com.google.android.material.listitem.ListItemCardView
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/materialCardViewElevatedStyle"
|
||||
app:cardElevation="@dimen/dimen0dp">
|
||||
android:checkable="false"
|
||||
android:layout_marginVertical="@dimen/dimen1dp"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardBackgroundColor="?attr/materialCardBackgroundColor">
|
||||
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:background="?attr/materialCardBackgroundColor"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/dimen12dp">
|
||||
android:padding="@dimen/dimen8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/taskName"
|
||||
android:layout_width="match_parent"
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/dimen6dp"
|
||||
android:layout_marginEnd="@dimen/dimen16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/adminCron"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="@dimen/dimen16sp" />
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/runTask"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/runTask"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_alignParentEnd="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:scaleType="fitCenter"
|
||||
android:contentDescription="@string/adminCron"
|
||||
android:src="@drawable/ic_play" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</com.google.android.material.listitem.ListItemCardView>
|
||||
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.listitem.ListItemLayout>
|
||||
|
||||
@@ -616,6 +616,8 @@
|
||||
<string name="template">Template</string>
|
||||
<string name="accounts">Accounts</string>
|
||||
<string name="copied">Copied</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<!-- generic copy -->
|
||||
|
||||
<string name="exploreUsers">Explore users</string>
|
||||
@@ -1098,4 +1100,8 @@
|
||||
<string name="forked_repository">forked repository</string>
|
||||
<string name="mirrored_repository">mirrored repository</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
<string name="adminUsersSubtext">Manage all system accounts and users</string>
|
||||
<string name="adminCronSubtext">View and execute system scheduled maintenance tasks</string>
|
||||
<string name="unadoptedReposSubtext">Search and claim repositories found on disk</string>
|
||||
<string name="repoSettingsSubtext">View global repository and LFS settings</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user