mirror of
https://codeberg.org/gitnex/GitNex.git
synced 2024-12-16 15:48:13 +08:00
Cron tasks (#817)
* Run task * Add info popup dialog for details * List cron tasks * Add cron to admin screen Co-authored-by: M M Arif <mmarif@swatian.com> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/817 Reviewed-by: 6543 <6543@noreply.codeberg.org> Co-Authored-By: M M Arif <mmarif@noreply.codeberg.org> Co-Committed-By: M M Arif <mmarif@noreply.codeberg.org>
This commit is contained in:
parent
cb241d80f3
commit
d72cd57cd7
@ -158,6 +158,10 @@
|
||||
android:name=".activities.SettingsNotificationsActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.AdminCronTasksActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
|
||||
|
||||
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
|
||||
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
|
||||
<!-- Version >= 3.0. DeX Dual Mode support -->
|
||||
|
@ -0,0 +1,89 @@
|
||||
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.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import org.mian.gitnex.adapters.AdminCronTasksAdapter;
|
||||
import org.mian.gitnex.databinding.ActivityAdminCronTasksBinding;
|
||||
import org.mian.gitnex.helpers.Authorization;
|
||||
import org.mian.gitnex.viewmodels.AdminCronTasksViewModel;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class AdminCronTasksActivity extends BaseActivity {
|
||||
|
||||
private View.OnClickListener onClickListener;
|
||||
private AdminCronTasksAdapter adapter;
|
||||
|
||||
private ActivityAdminCronTasksBinding activityAdminCronTasksBinding;
|
||||
|
||||
public static final int PAGE = 1;
|
||||
public static final int LIMIT = 50;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityAdminCronTasksBinding = ActivityAdminCronTasksBinding.inflate(getLayoutInflater());
|
||||
setContentView(activityAdminCronTasksBinding.getRoot());
|
||||
|
||||
initCloseListener();
|
||||
activityAdminCronTasksBinding.close.setOnClickListener(onClickListener);
|
||||
|
||||
Toolbar toolbar = activityAdminCronTasksBinding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
activityAdminCronTasksBinding.recyclerView.setHasFixedSize(true);
|
||||
activityAdminCronTasksBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
|
||||
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(activityAdminCronTasksBinding.recyclerView.getContext(),
|
||||
DividerItemDecoration.VERTICAL);
|
||||
activityAdminCronTasksBinding.recyclerView.addItemDecoration(dividerItemDecoration);
|
||||
|
||||
activityAdminCronTasksBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
|
||||
activityAdminCronTasksBinding.pullToRefresh.setRefreshing(false);
|
||||
AdminCronTasksViewModel.loadCronTasksList(ctx, Authorization.get(ctx), PAGE, LIMIT);
|
||||
|
||||
}, 500));
|
||||
|
||||
fetchDataAsync(ctx, Authorization.get(ctx));
|
||||
}
|
||||
|
||||
private void fetchDataAsync(Context ctx, String instanceToken) {
|
||||
|
||||
AdminCronTasksViewModel cronTasksViewModel = new ViewModelProvider(this).get(AdminCronTasksViewModel.class);
|
||||
|
||||
cronTasksViewModel.getCronTasksList(ctx, instanceToken, PAGE, LIMIT).observe(this, cronTasksListMain -> {
|
||||
|
||||
adapter = new AdminCronTasksAdapter(ctx, cronTasksListMain);
|
||||
|
||||
if(adapter.getItemCount() > 0) {
|
||||
|
||||
activityAdminCronTasksBinding.recyclerView.setVisibility(View.VISIBLE);
|
||||
activityAdminCronTasksBinding.recyclerView.setAdapter(adapter);
|
||||
activityAdminCronTasksBinding.noData.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
|
||||
activityAdminCronTasksBinding.recyclerView.setVisibility(View.GONE);
|
||||
activityAdminCronTasksBinding.noData.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initCloseListener() {
|
||||
onClickListener = view -> finish();
|
||||
}
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
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.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.gson.JsonElement;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.TinyDB;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import org.mian.gitnex.models.CronTasks;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class AdminCronTasksAdapter extends RecyclerView.Adapter<AdminCronTasksAdapter.CronTasksViewHolder> {
|
||||
|
||||
private final List<CronTasks> tasksList;
|
||||
private final Context mCtx;
|
||||
private static TinyDB tinyDb;
|
||||
|
||||
static class CronTasksViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private CronTasks cronTasks;
|
||||
|
||||
private final ImageView runTask;
|
||||
private final TextView taskName;
|
||||
private final LinearLayout cronTasksInfo;
|
||||
private final LinearLayout cronTasksRun;
|
||||
|
||||
private CronTasksViewHolder(View itemView) {
|
||||
|
||||
super(itemView);
|
||||
Context ctx = itemView.getContext();
|
||||
|
||||
final String locale = tinyDb.getString("locale");
|
||||
final String timeFormat = tinyDb.getString("dateFormat");
|
||||
|
||||
runTask = itemView.findViewById(R.id.runTask);
|
||||
taskName = itemView.findViewById(R.id.taskName);
|
||||
cronTasksInfo = itemView.findViewById(R.id.cronTasksInfo);
|
||||
cronTasksRun = itemView.findViewById(R.id.cronTasksRun);
|
||||
|
||||
cronTasksInfo.setOnClickListener(taskInfo -> {
|
||||
|
||||
String nextRun = "";
|
||||
String lastRun = "";
|
||||
|
||||
if(cronTasks.getNext() != null) {
|
||||
nextRun = TimeHelper.formatTime(cronTasks.getNext(), new Locale(locale), timeFormat, ctx);
|
||||
}
|
||||
if(cronTasks.getPrev() != null) {
|
||||
lastRun = TimeHelper.formatTime(cronTasks.getPrev(), new Locale(locale), timeFormat, ctx);
|
||||
}
|
||||
|
||||
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.getExec_times()));
|
||||
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx);
|
||||
|
||||
alertDialog.setTitle(StringUtils.capitalize(cronTasks.getName().replace("_", " ")));
|
||||
alertDialog.setView(view);
|
||||
alertDialog.setPositiveButton(ctx.getString(R.string.close), null);
|
||||
alertDialog.create().show();
|
||||
|
||||
});
|
||||
|
||||
cronTasksRun.setOnClickListener(taskInfo -> {
|
||||
|
||||
runCronTask(ctx, cronTasks.getName());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public AdminCronTasksAdapter(Context mCtx, List<CronTasks> tasksListMain) {
|
||||
|
||||
tinyDb = TinyDB.getInstance(mCtx);
|
||||
this.mCtx = mCtx;
|
||||
this.tasksList = tasksListMain;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull AdminCronTasksAdapter.CronTasksViewHolder holder, int position) {
|
||||
|
||||
CronTasks currentItem = tasksList.get(position);
|
||||
|
||||
holder.cronTasks = currentItem;
|
||||
holder.taskName.setText(StringUtils.capitalize(currentItem.getName().replace("_", " ")));
|
||||
}
|
||||
|
||||
private static void runCronTask(final Context ctx, final String taskName) {
|
||||
|
||||
final String loginUid = tinyDb.getString("loginUid");
|
||||
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
|
||||
|
||||
Call<JsonElement> call = RetrofitClient
|
||||
.getApiInterface(ctx)
|
||||
.adminRunCronTask(instanceToken, taskName);
|
||||
|
||||
call.enqueue(new Callback<JsonElement>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
|
||||
|
||||
switch(response.code()) {
|
||||
|
||||
case 204:
|
||||
Toasty.success(ctx, ctx.getString(R.string.adminCronTaskSuccessMsg, taskName));
|
||||
break;
|
||||
|
||||
case 401:
|
||||
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getString(R.string.alertDialogTokenRevokedTitle),
|
||||
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
|
||||
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
|
||||
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
|
||||
break;
|
||||
|
||||
case 403:
|
||||
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
|
||||
break;
|
||||
|
||||
case 404:
|
||||
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
|
||||
break;
|
||||
|
||||
default:
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericError));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
|
||||
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return tasksList.size();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
@ -8,8 +9,11 @@ import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import org.mian.gitnex.activities.AdminCronTasksActivity;
|
||||
import org.mian.gitnex.activities.AdminGetUsersActivity;
|
||||
import org.mian.gitnex.databinding.FragmentAdministrationBinding;
|
||||
import org.mian.gitnex.helpers.TinyDB;
|
||||
import org.mian.gitnex.helpers.Version;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
@ -17,12 +21,25 @@ import org.mian.gitnex.databinding.FragmentAdministrationBinding;
|
||||
|
||||
public class AdministrationFragment extends Fragment {
|
||||
|
||||
private Context ctx;
|
||||
private TinyDB tinyDB;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
|
||||
ctx = getContext();
|
||||
tinyDB = TinyDB.getInstance(ctx);
|
||||
FragmentAdministrationBinding fragmentAdministrationBinding = FragmentAdministrationBinding.inflate(inflater, container, false);
|
||||
|
||||
fragmentAdministrationBinding.adminUsers.setOnClickListener(v1 -> startActivity(new Intent(getContext(), AdminGetUsersActivity.class)));
|
||||
|
||||
// if gitea version is greater/equal(1.13.0) than user installed version (installed.higherOrEqual(compareVer))
|
||||
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.13.0")) {
|
||||
|
||||
fragmentAdministrationBinding.adminCron.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
fragmentAdministrationBinding.adminCron.setOnClickListener(v1 -> startActivity(new Intent(getContext(), AdminCronTasksActivity.class)));
|
||||
|
||||
return fragmentAdministrationBinding.getRoot();
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.mian.gitnex.models.CreateIssue;
|
||||
import org.mian.gitnex.models.CreateLabel;
|
||||
import org.mian.gitnex.models.CreatePullRequest;
|
||||
import org.mian.gitnex.models.CreateStatusOption;
|
||||
import org.mian.gitnex.models.CronTasks;
|
||||
import org.mian.gitnex.models.DeleteFile;
|
||||
import org.mian.gitnex.models.EditFile;
|
||||
import org.mian.gitnex.models.Emails;
|
||||
@ -430,5 +431,10 @@ public interface ApiInterface {
|
||||
@GET("repos/{owner}/{repo}/statuses/{sha}") // Get a commit's statuses
|
||||
Call<List<Status>> getCommitStatuses(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("sort") String sort, @Query("state") String state, @Query("page") int page, @Query("limit") int limit);
|
||||
|
||||
@GET("admin/cron") // get cron tasks
|
||||
Call<List<CronTasks>> adminGetCronTasks(@Header("Authorization") String token, @Query("page") int page, @Query("limit") int limit);
|
||||
|
||||
@POST("admin/cron/{taskName}") // run cron task
|
||||
Call<JsonElement> adminRunCronTask(@Header("Authorization") String token, @Path("taskName") String taskName);
|
||||
|
||||
}
|
||||
|
42
app/src/main/java/org/mian/gitnex/models/CronTasks.java
Normal file
42
app/src/main/java/org/mian/gitnex/models/CronTasks.java
Normal file
@ -0,0 +1,42 @@
|
||||
package org.mian.gitnex.models;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class CronTasks {
|
||||
|
||||
private String name;
|
||||
private String schedule;
|
||||
private Date next;
|
||||
private Date prev;
|
||||
private int exec_times;
|
||||
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSchedule() {
|
||||
|
||||
return schedule;
|
||||
}
|
||||
|
||||
public Date getNext() {
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
public Date getPrev() {
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
public int getExec_times() {
|
||||
|
||||
return exec_times;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package org.mian.gitnex.viewmodels;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.helpers.AlertDialogs;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import org.mian.gitnex.models.CronTasks;
|
||||
import java.util.List;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class AdminCronTasksViewModel extends ViewModel {
|
||||
|
||||
private static MutableLiveData<List<CronTasks>> tasksList;
|
||||
|
||||
public LiveData<List<CronTasks>> getCronTasksList(Context ctx, String token, int page, int limit) {
|
||||
|
||||
tasksList = new MutableLiveData<>();
|
||||
loadCronTasksList(ctx, token, page, limit);
|
||||
|
||||
return tasksList;
|
||||
}
|
||||
|
||||
public static void loadCronTasksList(final Context ctx, String token, int page, int limit) {
|
||||
|
||||
Call<List<CronTasks>> call = RetrofitClient
|
||||
.getApiInterface(ctx)
|
||||
.adminGetCronTasks(token, page, limit);
|
||||
|
||||
call.enqueue(new Callback<List<CronTasks>>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<List<CronTasks>> call, @NonNull Response<List<CronTasks>> response) {
|
||||
|
||||
if (response.code() == 200) {
|
||||
tasksList.postValue(response.body());
|
||||
}
|
||||
|
||||
else if(response.code() == 401) {
|
||||
|
||||
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
|
||||
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
|
||||
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
|
||||
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
|
||||
}
|
||||
else if(response.code() == 403) {
|
||||
|
||||
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
|
||||
}
|
||||
else if(response.code() == 404) {
|
||||
|
||||
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
|
||||
}
|
||||
else {
|
||||
|
||||
Toasty.error(ctx, ctx.getString(R.string.genericError));
|
||||
Log.i("onResponse", String.valueOf(response.code()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<CronTasks>> call, @NonNull Throwable t) {
|
||||
Log.e("onFailure", t.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
13
app/src/main/res/drawable/ic_play.xml
Normal file
13
app/src/main/res/drawable/ic_play.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M5,3l14,9l-14,9l0,-18z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?attr/iconsColor"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
20
app/src/main/res/drawable/ic_tasks.xml
Normal file
20
app/src/main/res/drawable/ic_tasks.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16,4h2a2,2 0,0 1,2 2v14a2,2 0,0 1,-2 2H6a2,2 0,0 1,-2 -2V6a2,2 0,0 1,2 -2h2"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?attr/iconsColor"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M9,2L15,2A1,1 0,0 1,16 3L16,5A1,1 0,0 1,15 6L9,6A1,1 0,0 1,8 5L8,3A1,1 0,0 1,9 2z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?attr/iconsColor"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
71
app/src/main/res/layout/activity_admin_cron_tasks.xml
Normal file
71
app/src/main/res/layout/activity_admin_cron_tasks.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/Widget.AppCompat.SearchView">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/primaryBackgroundColor">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/close"
|
||||
android:layout_width="@dimen/close_button_size"
|
||||
android:layout_height="@dimen/close_button_size"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:gravity="center_vertical"
|
||||
android:contentDescription="@string/close"
|
||||
android:src="@drawable/ic_close" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/adminCron"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:maxLines="1"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/pullToRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/noDataFound"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="20sp"
|
||||
android:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
@ -26,6 +26,25 @@
|
||||
android:padding="16dp"
|
||||
app:drawableStartCompat="@drawable/ic_people" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:id="@+id/divider"
|
||||
android:background="?attr/dividerColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/adminCron"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/adminCron"
|
||||
android:drawablePadding="32dp"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="16sp"
|
||||
android:padding="16dp"
|
||||
android:visibility="gone"
|
||||
app:drawableStartCompat="@drawable/ic_tasks" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
97
app/src/main/res/layout/layout_cron_task_info.xml
Normal file
97
app/src/main/res/layout/layout_cron_task_info.xml
Normal file
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="25dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<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/execTimeContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:textColorLink="@color/lightBlue"
|
||||
android:textColor="?attr/primaryTextColor" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
45
app/src/main/res/layout/list_admin_cron_tasks.xml
Normal file
45
app/src/main/res/layout/list_admin_cron_tasks.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?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"
|
||||
android:padding="15dp"
|
||||
android:background="?attr/primaryBackgroundColor" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cronTasksRun"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginEnd="15dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/runTask"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:scaleType="fitCenter"
|
||||
android:contentDescription="@string/adminCron"
|
||||
android:src="@drawable/ic_play" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cronTasksInfo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/cronTasksRun"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/taskName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="@string/userName"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
@ -33,7 +33,7 @@
|
||||
android:id="@+id/editCommentStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:contentDescription="@string/menuDeleteText"
|
||||
android:src="@drawable/ic_edit" />
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
android:id="@+id/deleteDraft"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:contentDescription="@string/menuDeleteText"
|
||||
android:src="@drawable/ic_delete" />
|
||||
|
||||
|
@ -412,6 +412,12 @@
|
||||
<string name="adminCreateNewUser">Add New User</string>
|
||||
<string name="adminUsers">System Users</string>
|
||||
<string name="userRoleAdmin">Admin</string>
|
||||
<string name="adminCron">Cron Tasks</string>
|
||||
<string name="adminCronScheduleHeader">Schedule</string>
|
||||
<string name="adminCronNextRunHeader">Next Run</string>
|
||||
<string name="adminCronLastRunHeader">Last Run</string>
|
||||
<string name="adminCronExecutionHeader">Executions</string>
|
||||
<string name="adminCronTaskSuccessMsg">Task %1$s is initiated successfully</string>
|
||||
<!-- admin -->
|
||||
|
||||
<!-- create user -->
|
||||
|
Loading…
Reference in New Issue
Block a user