admin panel worker info with block

This commit is contained in:
shipovnikaaa 2025-02-19 17:51:54 +03:00
parent 4912c972fd
commit 933ac87888
7 changed files with 414 additions and 1 deletions

View File

@ -0,0 +1,82 @@
kotlin version: 2.0.21
error message: Daemon compilation failed: null
java.lang.Exception
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:195)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:128)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:170)
at org.gradle.internal.Factories$1.create(Factories.java:31)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:131)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:136)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:165)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:134)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.nio.file.DirectoryNotEmptyException: C:\Users\User\AppData\Local\Temp\kotlin-backups17220056760637860906
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(Unknown Source)
at java.base/java.nio.file.Files.delete(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash$lambda$11$lambda$10$lambda$9(CompilationTransaction.kt:244)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
at java.base/java.util.ArrayList.forEach(Unknown Source)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(Unknown Source)
at java.base/java.util.stream.Sink$ChainedReference.end(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash(CompilationTransaction.kt:244)
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:254)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
... 3 more

View File

@ -0,0 +1,5 @@
package ru.myitschool.work.ui.admin
import kotlinx.serialization.Serializable
@Serializable
data object AdminDestination

View File

@ -0,0 +1,85 @@
package ru.myitschool.work.ui.admin
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.squareup.picasso.Picasso
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import ru.myitschool.work.R
import ru.myitschool.work.databinding.FragmentAdminBinding
import ru.myitschool.work.ui.main.MainDestination
import ru.myitschool.work.utils.collectWhenStarted
import ru.myitschool.work.utils.TextChangedListener
@AndroidEntryPoint
class AdminFragment : Fragment(R.layout.fragment_admin) {
private var _binding: FragmentAdminBinding? = null
private val binding: FragmentAdminBinding get() = _binding!!
private val picasso: Picasso by lazy { Picasso.get() }
private val viewModel: AdminViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentAdminBinding.bind(view)
binding.loginadmin.addTextChangedListener(TextChangedListener { viewModel.onUsernameChanged(it) })
subscribe()
binding.find.setOnClickListener {
login(binding.loginadmin.text.toString())
}
}
private fun login(username: String) {
viewModel.loadPersonInfo(username) {
viewModel.state.collectWhenStarted(this) { state ->
if (state.photo.isNotEmpty()) {
picasso.load(state.photo).into(binding.photoAdmin)
}
binding.fullnameAdmin.text = state.fullName
binding.positionAdmin.text = state.position
binding.lastEntryAdmin.text = state.lastVisit
setError(state.error)
}
}
}
private fun subscribe() {
// viewModel.state.collectWhenStarted(this) { state ->
// binding.login.isEnabled = state.isLoginEnabled
// if (state.error != null) {
// binding.error.visibility = View.VISIBLE
// binding.error.text = state.error
// } else {
// binding.error.visibility = View.GONE
// }
// }
// viewModel.savedUsername.collectWhenStarted(this) { username ->
// viewModel.savedPassword.collectWhenStarted(this) { password ->
// if (!username.isNullOrBlank() && !password.isNullOrBlank()) {
// login(username, password)
// }
// }
// }
println("akjshdfg")
}
private fun setError(error: String?) {
val showError = error != null
val views = listOf(binding.fullnameAdmin, binding.positionAdmin, binding.lastEntryAdmin, binding.photoAdmin)
views.forEach { it.visibility = if (showError) View.GONE else View.VISIBLE}
binding.errorAdmin.visibility = if (showError) View.VISIBLE else View.GONE
binding.block.visibility = if (showError) View.GONE else View.VISIBLE
binding.errorAdmin.text = error ?: ""
}
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}

View File

@ -0,0 +1,13 @@
package ru.myitschool.work.ui.admin
data class AdminState(
val isLoginEnabled: Boolean = false, val error: String? = null
)
data class AdminMainState(
val fullName: String = "",
val photo: String = "",
val position: String = "",
val lastVisit: String = "",
val error: String? = null
)

View File

@ -0,0 +1,86 @@
package ru.myitschool.work.ui.admin
import android.content.Context
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.GsonBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import retrofit2.HttpException
import ru.myitschool.work.data.remote.LoginApi
import ru.myitschool.work.data.remote.ErrorDto
import ru.myitschool.work.di.AppModule
import ru.myitschool.work.ui.admin.AdminState
import java.text.SimpleDateFormat
import javax.inject.Inject
@HiltViewModel
class AdminViewModel @Inject constructor(
@ApplicationContext private val context: Context,
private val api: LoginApi,
private val dataStoreManager: AppModule.DataStoreManager
) : ViewModel() {
private val _state = MutableStateFlow(AdminMainState())
val state = _state.asStateFlow()
private val _stateL = MutableStateFlow(AdminState())
val stateL = _stateL.asStateFlow()
private val dfo = SimpleDateFormat("yyyy-MM-dd HH:mm")
private val dfi= SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
fun loadPersonInfo(username: String, onSuccess: () -> Unit) {
viewModelScope.launch {
try {
val info = api.info(username)
_state.update {
AdminMainState(
fullName = info.name,
photo = info.photo,
position = info.position,
lastVisit = dfo.format(dfi.parse(info.lastVisit)!!),
error = null
)
}
onSuccess()
} catch (httpException: HttpException) {
try {
httpException.response()?.errorBody()?.string()?.let { errorString ->
val gson = GsonBuilder().create()
val errorDto = gson.fromJson(errorString, ErrorDto::class.java)
_state.update {
AdminMainState(
error = errorDto.error
)
}
}
} catch (e: Exception) {
_state.update { AdminMainState(error = httpException.message()) }
}
} catch (e: Exception) {
_state.update { AdminMainState(error = "Unknown error: ${e.message}") }
}
}
}
fun onUsernameChanged(username: String) =
_stateL.update { it.copy(isLoginEnabled = isUsernameValid(username), error = null) }
companion object {
fun isUsernameValid(username: String): Boolean {
if (username.isEmpty() || username.length < 3 || username.first().isDigit()) {
return false
}
return username.all { it.isLetterOrDigit() && it.isAsciiPrintable() }
}
private fun Char.isAsciiPrintable(): Boolean {
return this.code in 32..126
}
}
}

View File

@ -10,6 +10,7 @@ import com.squareup.picasso.Picasso
import dagger.hilt.android.AndroidEntryPoint
import ru.myitschool.work.R
import ru.myitschool.work.databinding.FragmentMainBinding
import ru.myitschool.work.ui.admin.AdminDestination
import ru.myitschool.work.ui.login.LoginDestination
import ru.myitschool.work.ui.qr.result.QrResultDestination
import ru.myitschool.work.ui.qr.scan.QrScanDestination
@ -43,7 +44,7 @@ class MainFragment: Fragment(R.layout.fragment_main) {
findNavController().navigate(QrScanDestination)
}
binding.admin.setOnClickListener{
findNavController().navigate(AdminDestination)
}
}
subscribe()

View File

@ -0,0 +1,141 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/admin_name"
android:layout_width="89dp"
android:layout_height="25dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.118" />
<Button
android:id="@+id/block"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_weight="1"
android:text="заблокировать"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@+id/loginadmin"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/loginadmin"
app:layout_constraintTop_toBottomOf="@+id/loginadmin" />
<TextView
android:id="@+id/errorAdmin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="TextView"
android:textSize="24sp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/block" />
<TextView
android:id="@+id/lastEntryAdmin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="TextView"
android:textSize="20sp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/positionAdmin" />
<TextView
android:id="@+id/fullnameAdmin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="24sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/errorAdmin"
app:layout_constraintVertical_bias="0.033" />
<TextView
android:id="@+id/positionAdmin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView"
android:textSize="20sp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/photoAdmin" />
<ScrollView
android:layout_width="409dp"
android:layout_height="438dp"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@+id/lastEntryAdmin"
tools:layout_editor_absoluteX="-2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
<ImageView
android:id="@+id/photoAdmin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fullnameAdmin"
tools:srcCompat="@tools:sample/avatars" />
<EditText
android:id="@+id/loginadmin"
android:layout_width="164dp"
android:layout_height="54dp"
android:layout_marginTop="12dp"
android:ems="10"
android:inputType="text"
android:hint = "@string/login_admin_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/admin_name" />
<Button
android:id="@+id/find"
android:layout_width="98dp"
android:layout_height="47dp"
android:text="Найти"
app:layout_constraintBottom_toBottomOf="@+id/loginadmin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/loginadmin"
app:layout_constraintTop_toTopOf="@+id/loginadmin" />
<Button
android:id="@+id/backAdmin"
android:layout_width="98dp"
android:layout_height="47dp"
android:text="назад"
app:layout_constraintBottom_toBottomOf="@+id/loginadmin"
app:layout_constraintEnd_toStartOf="@+id/loginadmin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/loginadmin"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>