Driver admin complete
- empty view for no users - edit user identifier - test for driver admin added
122
.idea/codeStyles/Project.xml
generated
@@ -1,122 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<codeStyleSettings language="XML">
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
<arrangement>
|
|
||||||
<rules>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:android</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:id</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>style</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
</rules>
|
|
||||||
</arrangement>
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
||||||
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="17" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
7
.idea/dictionaries/h_mal.xml
generated
@@ -1,7 +0,0 @@
|
|||||||
<component name="ProjectDictionaryState">
|
|
||||||
<dictionary name="h_mal">
|
|
||||||
<words>
|
|
||||||
<w>viewmodel</w>
|
|
||||||
</words>
|
|
||||||
</dictionary>
|
|
||||||
</component>
|
|
||||||
20
.idea/gradle.xml
generated
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="testRunner" value="GRADLE" />
|
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="gradleJvm" value="Android Studio java home" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
<option value="$PROJECT_DIR$/app" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="IllegalIdentifier" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
||||||
50
.idea/jarRepositories.xml
generated
@@ -1,50 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RemoteRepositoriesConfiguration">
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="central" />
|
|
||||||
<option name="name" value="Maven Central repository" />
|
|
||||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="jboss.community" />
|
|
||||||
<option name="name" value="JBoss Community repository" />
|
|
||||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="BintrayJCenter" />
|
|
||||||
<option name="name" value="BintrayJCenter" />
|
|
||||||
<option name="url" value="https://jcenter.bintray.com/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="maven" />
|
|
||||||
<option name="name" value="maven" />
|
|
||||||
<option name="url" value="https://jitpack.io" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="Google" />
|
|
||||||
<option name="name" value="Google" />
|
|
||||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="MavenRepo" />
|
|
||||||
<option name="name" value="MavenRepo" />
|
|
||||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\android\m2repository" />
|
|
||||||
<option name="name" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\android\m2repository" />
|
|
||||||
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\google\m2repository" />
|
|
||||||
<option name="name" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\google\m2repository" />
|
|
||||||
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/google/m2repository/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\m2repository" />
|
|
||||||
<option name="name" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\m2repository" />
|
|
||||||
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/m2repository/" />
|
|
||||||
</remote-repository>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
48
.idea/misc.xml
generated
@@ -1,48 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="NullableNotNullManager">
|
|
||||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
|
||||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
|
||||||
<option name="myNullables">
|
|
||||||
<value>
|
|
||||||
<list size="12">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
|
||||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
|
||||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
|
||||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
|
||||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
|
||||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
|
||||||
<item index="7" class="java.lang.String" itemvalue="android.annotation.Nullable" />
|
|
||||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
|
||||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
|
||||||
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
|
||||||
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="myNotNulls">
|
|
||||||
<value>
|
|
||||||
<list size="11">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
|
||||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
|
||||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
|
||||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
|
||||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
|
||||||
<item index="6" class="java.lang.String" itemvalue="android.annotation.NonNull" />
|
|
||||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
|
||||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
|
||||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
|
||||||
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectType">
|
|
||||||
<option name="id" value="Android" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
7
.idea/vcs.xml
generated
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$/driver_app_data" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
package h_mal.appttude.com.driver.application
|
package h_mal.appttude.com.driver.application
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.content.res.Resources
|
|
||||||
import h_mal.appttude.com.driver.data.FirebaseAuthSource
|
|
||||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
|
||||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
|
||||||
import h_mal.appttude.com.driver.data.prefs.PreferenceProvider
|
import h_mal.appttude.com.driver.data.prefs.PreferenceProvider
|
||||||
import org.kodein.di.Kodein
|
|
||||||
import org.kodein.di.KodeinAware
|
|
||||||
import org.kodein.di.android.x.androidXModule
|
|
||||||
import org.kodein.di.generic.bind
|
import org.kodein.di.generic.bind
|
||||||
import org.kodein.di.generic.instance
|
import org.kodein.di.generic.instance
|
||||||
import org.kodein.di.generic.provider
|
import org.kodein.di.generic.provider
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package h_mal.appttude.com.driver.model
|
||||||
|
|
||||||
|
import h_mal.appttude.com.driver.R
|
||||||
|
|
||||||
|
enum class DatabaseStatus(val drawable: Int, val header: Int, val subtext: Int) {
|
||||||
|
NO_CONNECTION(R.drawable.baseline_inbox_24, R.string.no_connection, R.string.no_connection_subtext),
|
||||||
|
NO_PERMISSION(
|
||||||
|
R.drawable.baseline_inbox_24,
|
||||||
|
R.string.no_permission,
|
||||||
|
R.string.no_permission_subtext
|
||||||
|
),
|
||||||
|
CANNOT_RETRIEVE(
|
||||||
|
R.drawable.baseline_inbox_24,
|
||||||
|
R.string.cannot_retrieve,
|
||||||
|
R.string.cannot_retrieve_subtext
|
||||||
|
),
|
||||||
|
NO_AUTHORIZATION(
|
||||||
|
R.drawable.baseline_inbox_24,
|
||||||
|
R.string.no_authorization,
|
||||||
|
R.string.no_authorization_subtext
|
||||||
|
),
|
||||||
|
EMPTY_RESULTS(
|
||||||
|
R.drawable.baseline_inbox_24,
|
||||||
|
R.string.no_drivers_to_show,
|
||||||
|
R.string.no_drivers_subtext
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
package h_mal.appttude.com.driver.objects
|
package h_mal.appttude.com.driver.objects
|
||||||
|
|
||||||
import h_mal.appttude.com.driver.model.*
|
import h_mal.appttude.com.driver.model.DriversLicense
|
||||||
|
import h_mal.appttude.com.driver.model.Insurance
|
||||||
|
import h_mal.appttude.com.driver.model.Logbook
|
||||||
|
import h_mal.appttude.com.driver.model.Mot
|
||||||
|
import h_mal.appttude.com.driver.model.PrivateHireLicense
|
||||||
|
import h_mal.appttude.com.driver.model.PrivateHireVehicle
|
||||||
|
import h_mal.appttude.com.driver.model.VehicleProfile
|
||||||
|
|
||||||
|
|
||||||
data class ArchiveObject(
|
data class ArchiveObject(
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package h_mal.appttude.com.driver.objects.wholeObject
|
package h_mal.appttude.com.driver.objects.wholeObject
|
||||||
|
|
||||||
import h_mal.appttude.com.driver.model.*
|
import h_mal.appttude.com.driver.model.Insurance
|
||||||
|
import h_mal.appttude.com.driver.model.Logbook
|
||||||
|
import h_mal.appttude.com.driver.model.Mot
|
||||||
|
import h_mal.appttude.com.driver.model.PrivateHireVehicle
|
||||||
import h_mal.appttude.com.driver.model.VehicleProfile
|
import h_mal.appttude.com.driver.model.VehicleProfile
|
||||||
|
|
||||||
data class VehicleProfile (
|
data class VehicleProfile (
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package h_mal.appttude.com.driver.ui
|
package h_mal.appttude.com.driver.ui
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import h_mal.appttude.com.driver.base.BaseFragment
|
import h_mal.appttude.com.driver.base.BaseFragment
|
||||||
import h_mal.appttude.com.driver.databinding.FragmentApproverBinding
|
import h_mal.appttude.com.driver.databinding.FragmentApproverBinding
|
||||||
import h_mal.appttude.com.driver.model.ApprovalStatus
|
import h_mal.appttude.com.driver.model.ApprovalStatus
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import h_mal.appttude.com.driver.base.CustomViewHolder
|
|||||||
import h_mal.appttude.com.driver.data.USER_CONST
|
import h_mal.appttude.com.driver.data.USER_CONST
|
||||||
import h_mal.appttude.com.driver.databinding.FragmentHomeSuperUserBinding
|
import h_mal.appttude.com.driver.databinding.FragmentHomeSuperUserBinding
|
||||||
import h_mal.appttude.com.driver.databinding.ListItemLayoutBinding
|
import h_mal.appttude.com.driver.databinding.ListItemLayoutBinding
|
||||||
|
import h_mal.appttude.com.driver.model.DatabaseStatus
|
||||||
|
import h_mal.appttude.com.driver.model.DatabaseStatus.*
|
||||||
import h_mal.appttude.com.driver.model.SortOption
|
import h_mal.appttude.com.driver.model.SortOption
|
||||||
import h_mal.appttude.com.driver.objects.UserObject
|
import h_mal.appttude.com.driver.objects.UserObject
|
||||||
import h_mal.appttude.com.driver.objects.WholeDriverObject
|
import h_mal.appttude.com.driver.objects.WholeDriverObject
|
||||||
@@ -27,7 +29,8 @@ import h_mal.appttude.com.driver.viewmodels.SuperUserViewModel
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuperUserBinding>(), MenuProvider {
|
class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuperUserBinding>(),
|
||||||
|
MenuProvider {
|
||||||
private lateinit var adapter: FirebaseRecyclerAdapter<WholeDriverObject, CustomViewHolder<ListItemLayoutBinding>>
|
private lateinit var adapter: FirebaseRecyclerAdapter<WholeDriverObject, CustomViewHolder<ListItemLayoutBinding>>
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -42,6 +45,17 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
|
|||||||
is FirebaseRecyclerOptions<*> -> setAdapterToRecyclerView(data)
|
is FirebaseRecyclerOptions<*> -> setAdapterToRecyclerView(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private fun setNonView(status: DatabaseStatus) {
|
||||||
|
applyBinding {
|
||||||
|
emptyView.run {
|
||||||
|
root.setOnClickListener(null)
|
||||||
|
root.visibility = View.VISIBLE
|
||||||
|
icon.setImageResource(status.drawable)
|
||||||
|
header.setText(status.header)
|
||||||
|
subtext.setText(status.subtext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun setAdapterToRecyclerView(options: FirebaseRecyclerOptions<*>) {
|
private fun setAdapterToRecyclerView(options: FirebaseRecyclerOptions<*>) {
|
||||||
@@ -74,8 +88,8 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createAdapter(options: FirebaseRecyclerOptions<WholeDriverObject>): BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding> {
|
private fun createAdapter(options: FirebaseRecyclerOptions<WholeDriverObject>): BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding> {
|
||||||
return object : BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding>(options, layoutInflater) {
|
return object :
|
||||||
|
BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding>(options, layoutInflater) {
|
||||||
override fun onBindViewHolder(
|
override fun onBindViewHolder(
|
||||||
holder: CustomViewHolder<ListItemLayoutBinding>,
|
holder: CustomViewHolder<ListItemLayoutBinding>,
|
||||||
position: Int,
|
position: Int,
|
||||||
@@ -87,7 +101,8 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
|
|||||||
usernameText.text = userDetails?.profileName
|
usernameText.text = userDetails?.profileName
|
||||||
emailaddressText.text = userDetails?.profileEmail
|
emailaddressText.text = userDetails?.profileEmail
|
||||||
driverNo.run {
|
driverNo.run {
|
||||||
val number = if (model.driver_number.isNullOrBlank()) "#N/A" else model.driver_number
|
val number =
|
||||||
|
if (model.driver_number.isNullOrBlank()) "#N/A" else model.driver_number
|
||||||
text = number
|
text = number
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
getKeyAtPosition(position)?.let { showChangeNumberDialog(number!!, it) }
|
getKeyAtPosition(position)?.let { showChangeNumberDialog(number!!, it) }
|
||||||
@@ -121,8 +136,24 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
|
|||||||
applyBinding { progressCircular.hide() }
|
applyBinding { progressCircular.hide() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun connectionLost() {
|
override fun authorizationError() {
|
||||||
showToast("No connection available")
|
setNonView(NO_AUTHORIZATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cannotRetrieve() {
|
||||||
|
setNonView(CANNOT_RETRIEVE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun noConnection() {
|
||||||
|
setNonView(NO_CONNECTION)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun permissionsDenied() {
|
||||||
|
setNonView(NO_PERMISSION)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun emptyList() {
|
||||||
|
setNonView(EMPTY_RESULTS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ import h_mal.appttude.com.driver.objects.ApprovalsObject
|
|||||||
import h_mal.appttude.com.driver.ui.driverprofile.DriverLicenseFragment
|
import h_mal.appttude.com.driver.ui.driverprofile.DriverLicenseFragment
|
||||||
import h_mal.appttude.com.driver.ui.driverprofile.DriverProfileFragment
|
import h_mal.appttude.com.driver.ui.driverprofile.DriverProfileFragment
|
||||||
import h_mal.appttude.com.driver.ui.driverprofile.PrivateHireLicenseFragment
|
import h_mal.appttude.com.driver.ui.driverprofile.PrivateHireLicenseFragment
|
||||||
import h_mal.appttude.com.driver.ui.vehicleprofile.*
|
import h_mal.appttude.com.driver.ui.vehicleprofile.InsuranceFragment
|
||||||
|
import h_mal.appttude.com.driver.ui.vehicleprofile.LogbookFragment
|
||||||
|
import h_mal.appttude.com.driver.ui.vehicleprofile.MotFragment
|
||||||
|
import h_mal.appttude.com.driver.ui.vehicleprofile.PrivateHireVehicleFragment
|
||||||
|
import h_mal.appttude.com.driver.ui.vehicleprofile.VehicleProfileFragment
|
||||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||||
import h_mal.appttude.com.driver.utils.FRAGMENT
|
import h_mal.appttude.com.driver.utils.FRAGMENT
|
||||||
import h_mal.appttude.com.driver.utils.getDataFromDatabaseRef
|
import h_mal.appttude.com.driver.utils.getDataFromDatabaseRef
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class SuperUserViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createFirebaseOptions(sort: SortOption? = null) {
|
fun createFirebaseOptions(sort: SortOption? = null) {
|
||||||
val ref = firebaseDatabaseSource.getUsersRef()
|
val ref = firebaseDatabaseSource.getUsersRef().orderByChild("role").startAt("driver").endAt("driver")
|
||||||
|
|
||||||
sort?.isNotNull { preferenceProvider.setSortOption(it.label) }
|
sort?.isNotNull { preferenceProvider.setSortOption(it.label) }
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class SuperUserViewModel(
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
val options = FirebaseRecyclerOptions.Builder<WholeDriverObject>()
|
val options = FirebaseRecyclerOptions.Builder<WholeDriverObject>()
|
||||||
.setQuery(ref.orderByKey(), WholeDriverObject::class.java)
|
.setQuery(ref, WholeDriverObject::class.java)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
onSuccess(options)
|
onSuccess(options)
|
||||||
|
|||||||
54
app/src/admin/res/layout/empty_users_view.xml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/background_with_curve"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:src="@drawable/splash_screen"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:paddingTop="@dimen/default_indicator_margin_horizontal"
|
||||||
|
android:layout_marginTop="@dimen/default_indicator_margin_horizontal"
|
||||||
|
app:layout_constraintHeight_percent="0.5"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:importantForAccessibility="no" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
style="@style/constraint_container">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/header"
|
||||||
|
android:src="@drawable/baseline_inbox_24"
|
||||||
|
android:contentDescription="@string/image_icon_for_feedback_view" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/header"
|
||||||
|
style="@style/headerStyle"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/no_drivers_to_show"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/subtext"
|
||||||
|
style="@style/subheader"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/header"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/no_drivers_subtext"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/container"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
tools:context=".ui.HomeSuperUserFragment">
|
tools:context=".ui.HomeSuperUserFragment">
|
||||||
|
|
||||||
@@ -28,9 +29,9 @@
|
|||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/empty_view"
|
android:id="@+id/empty_view"
|
||||||
layout="@layout/empty_layout"
|
layout="@layout/empty_users_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
@@ -38,5 +39,4 @@
|
|||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -24,7 +24,11 @@ import androidx.test.espresso.intent.Intents
|
|||||||
import androidx.test.espresso.intent.Intents.intending
|
import androidx.test.espresso.intent.Intents.intending
|
||||||
import androidx.test.espresso.intent.matcher.IntentMatchers
|
import androidx.test.espresso.intent.matcher.IntentMatchers
|
||||||
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
|
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withClassName
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import h_mal.appttude.com.driver.helpers.DataHelper
|
import h_mal.appttude.com.driver.helpers.DataHelper
|
||||||
import h_mal.appttude.com.driver.helpers.EspressoHelper.waitForView
|
import h_mal.appttude.com.driver.helpers.EspressoHelper.waitForView
|
||||||
import org.hamcrest.CoreMatchers.allOf
|
import org.hamcrest.CoreMatchers.allOf
|
||||||
@@ -33,6 +37,7 @@ import org.hamcrest.Matcher
|
|||||||
import org.hamcrest.Matchers
|
import org.hamcrest.Matchers
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
open class BaseTestRobot {
|
open class BaseTestRobot {
|
||||||
|
|
||||||
fun fillEditText(resId: Int, text: String?): ViewInteraction =
|
fun fillEditText(resId: Int, text: String?): ViewInteraction =
|
||||||
@@ -51,6 +56,9 @@ open class BaseTestRobot {
|
|||||||
fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction
|
fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction
|
||||||
.check(matches(withText(text)))
|
.check(matches(withText(text)))
|
||||||
|
|
||||||
|
fun matchText(viewId: Int, textId: Int): ViewInteraction = onView(withId(viewId))
|
||||||
|
.check(matches(withText(textId)))
|
||||||
|
|
||||||
fun matchText(resId: Int, text: String): ViewInteraction = matchText(matchView(resId), text)
|
fun matchText(resId: Int, text: String): ViewInteraction = matchText(matchView(resId), text)
|
||||||
|
|
||||||
fun clickListItem(listRes: Int, position: Int) {
|
fun clickListItem(listRes: Int, position: Int) {
|
||||||
|
|||||||
@@ -5,14 +5,19 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.test.core.app.ActivityScenario
|
import androidx.test.core.app.ActivityScenario
|
||||||
import androidx.test.espresso.*
|
|
||||||
import androidx.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import androidx.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.IdlingRegistry
|
||||||
|
import androidx.test.espresso.IdlingResource
|
||||||
|
import androidx.test.espresso.Root
|
||||||
|
import androidx.test.espresso.UiController
|
||||||
|
import androidx.test.espresso.ViewAction
|
||||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||||
import h_mal.appttude.com.driver.base.BaseActivity
|
import h_mal.appttude.com.driver.base.BaseActivity
|
||||||
import h_mal.appttude.com.driver.helpers.BaseViewAction
|
import h_mal.appttude.com.driver.helpers.BaseViewAction
|
||||||
@@ -61,7 +66,7 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
|
|||||||
fun waitFor(delay: Long) {
|
fun waitFor(delay: Long) {
|
||||||
onView(isRoot()).perform(object : ViewAction {
|
onView(isRoot()).perform(object : ViewAction {
|
||||||
override fun getConstraints(): Matcher<View> = isRoot()
|
override fun getConstraints(): Matcher<View> = isRoot()
|
||||||
override fun getDescription(): String? = "wait for $delay milliseconds"
|
override fun getDescription(): String = "wait for $delay milliseconds"
|
||||||
override fun perform(uiController: UiController, v: View?) {
|
override fun perform(uiController: UiController, v: View?) {
|
||||||
uiController.loopMainThreadForAtLeast(delay)
|
uiController.loopMainThreadForAtLeast(delay)
|
||||||
}
|
}
|
||||||
@@ -71,6 +76,8 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
|
|||||||
open fun beforeLaunch() {}
|
open fun beforeLaunch() {}
|
||||||
open fun afterLaunch(context: Context) {}
|
open fun afterLaunch(context: Context) {}
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
fun checkToastMessage(message: String) {
|
fun checkToastMessage(message: String) {
|
||||||
onView(withText(message)).inRoot(object : TypeSafeMatcher<Root>() {
|
onView(withText(message)).inRoot(object : TypeSafeMatcher<Root>() {
|
||||||
override fun describeTo(description: Description?) {
|
override fun describeTo(description: Description?) {
|
||||||
@@ -79,7 +86,7 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
|
|||||||
|
|
||||||
override fun matchesSafely(root: Root): Boolean {
|
override fun matchesSafely(root: Root): Boolean {
|
||||||
root.run {
|
root.run {
|
||||||
if (windowLayoutParams.get().type === WindowManager.LayoutParams.TYPE_TOAST) {
|
if (windowLayoutParams.get().type == WindowManager.LayoutParams.TYPE_TOAST) {
|
||||||
decorView.run {
|
decorView.run {
|
||||||
if (windowToken === applicationWindowToken) {
|
if (windowToken === applicationWindowToken) {
|
||||||
// windowToken == appToken means this window isn't contained by any other windows.
|
// windowToken == appToken means this window isn't contained by any other windows.
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package h_mal.appttude.com.driver.robots
|
|||||||
import androidx.test.espresso.Espresso.onData
|
import androidx.test.espresso.Espresso.onData
|
||||||
import androidx.test.espresso.action.ViewActions.click
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import h_mal.appttude.com.driver.BaseTestRobot
|
import h_mal.appttude.com.driver.BaseTestRobot
|
||||||
import h_mal.appttude.com.driver.R
|
import h_mal.appttude.com.driver.R
|
||||||
import org.hamcrest.CoreMatchers.anything
|
import org.hamcrest.CoreMatchers.anything
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withTagKey
|
|||||||
import h_mal.appttude.com.driver.BaseTestRobot
|
import h_mal.appttude.com.driver.BaseTestRobot
|
||||||
import h_mal.appttude.com.driver.R
|
import h_mal.appttude.com.driver.R
|
||||||
import h_mal.appttude.com.driver.base.CustomViewHolder
|
import h_mal.appttude.com.driver.base.CustomViewHolder
|
||||||
|
import h_mal.appttude.com.driver.model.DatabaseStatus
|
||||||
|
|
||||||
fun homeAdmin(func: HomeAdminRobot.() -> Unit) = HomeAdminRobot().apply { func() }
|
fun homeAdmin(func: HomeAdminRobot.() -> Unit) = HomeAdminRobot().apply { func() }
|
||||||
class HomeAdminRobot : BaseTestRobot() {
|
class HomeAdminRobot : BaseTestRobot() {
|
||||||
@@ -43,4 +44,9 @@ class HomeAdminRobot : BaseTestRobot() {
|
|||||||
// Click OK
|
// Click OK
|
||||||
onView(withId(android.R.id.button1)).perform(ViewActions.click())
|
onView(withId(android.R.id.button1)).perform(ViewActions.click())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showNoPermissionsDisplay() {
|
||||||
|
matchText(R.id.header, DatabaseStatus.NO_PERMISSION.header)
|
||||||
|
matchText(R.id.subtext, DatabaseStatus.NO_PERMISSION.subtext)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,6 @@ import h_mal.appttude.com.driver.ui.MainActivity
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
open class AdminBaseTest: FirebaseTest<MainActivity>(MainActivity::class.java) {
|
open class AdminBaseTest: FirebaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
login(ADMIN_EMAIL, PASSWORD)
|
login(ADMIN_EMAIL, PASSWORD)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package h_mal.appttude.com.driver.tests
|
package h_mal.appttude.com.driver.tests
|
||||||
|
|
||||||
import androidx.test.espresso.Espresso
|
import androidx.test.espresso.Espresso
|
||||||
|
import h_mal.appttude.com.driver.R
|
||||||
import h_mal.appttude.com.driver.robots.approver
|
import h_mal.appttude.com.driver.robots.approver
|
||||||
import h_mal.appttude.com.driver.robots.driverOverview
|
import h_mal.appttude.com.driver.robots.driverOverview
|
||||||
import h_mal.appttude.com.driver.robots.homeAdmin
|
import h_mal.appttude.com.driver.robots.homeAdmin
|
||||||
import h_mal.appttude.com.driver.R
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class DocumentApproverTest : AdminBaseTest() {
|
class DocumentApproverTest : AdminBaseTest() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package h_mal.appttude.com.driver.tests
|
package h_mal.appttude.com.driver.tests
|
||||||
|
|
||||||
import h_mal.appttude.com.driver.ADMIN_EMAIL
|
import h_mal.appttude.com.driver.ADMIN_EMAIL
|
||||||
|
import h_mal.appttude.com.driver.DRIVER_EMAIL
|
||||||
import h_mal.appttude.com.driver.FirebaseTest
|
import h_mal.appttude.com.driver.FirebaseTest
|
||||||
import h_mal.appttude.com.driver.robots.homeAdmin
|
import h_mal.appttude.com.driver.robots.homeAdmin
|
||||||
import h_mal.appttude.com.driver.robots.login
|
import h_mal.appttude.com.driver.robots.login
|
||||||
@@ -18,7 +19,17 @@ class UserListTest : FirebaseTest<LoginActivity>(LoginActivity::class.java) {
|
|||||||
homeAdmin {
|
homeAdmin {
|
||||||
clickOnDriverIdentifier("rsaif660@gmail.com")
|
clickOnDriverIdentifier("rsaif660@gmail.com")
|
||||||
submitDialog("ID45")
|
submitDialog("ID45")
|
||||||
waitFor(5000)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loginAsUser_unableToSeeDrivers_loggedIn() {
|
||||||
|
login {
|
||||||
|
waitFor(1100)
|
||||||
|
attemptLogin(DRIVER_EMAIL)
|
||||||
|
}
|
||||||
|
homeAdmin {
|
||||||
|
showNoPermissionsDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.app.Application
|
|||||||
import h_mal.appttude.com.driver.data.FirebaseAuthSource
|
import h_mal.appttude.com.driver.data.FirebaseAuthSource
|
||||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||||
import h_mal.appttude.com.driver.data.prefs.PreferenceProvider
|
|
||||||
import org.kodein.di.Kodein
|
import org.kodein.di.Kodein
|
||||||
import org.kodein.di.KodeinAware
|
import org.kodein.di.KodeinAware
|
||||||
import org.kodein.di.android.x.androidXModule
|
import org.kodein.di.android.x.androidXModule
|
||||||
|
|||||||
@@ -8,15 +8,20 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
|||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.firebase.ui.database.FirebaseRecyclerAdapter
|
import com.firebase.ui.database.FirebaseRecyclerAdapter
|
||||||
import com.firebase.ui.database.FirebaseRecyclerOptions
|
import com.firebase.ui.database.FirebaseRecyclerOptions
|
||||||
|
import com.google.firebase.database.DatabaseError
|
||||||
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
|
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
|
||||||
import h_mal.appttude.com.driver.utils.GenericsHelper.inflateBindingByType
|
import h_mal.appttude.com.driver.utils.GenericsHelper.inflateBindingByType
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
|
|
||||||
open class BaseFirebaseAdapter<T: Any, VB : ViewBinding>(options: FirebaseRecyclerOptions<T>, private val layoutInflater: LayoutInflater):
|
open class BaseFirebaseAdapter<T : Any, VB : ViewBinding>(
|
||||||
|
options: FirebaseRecyclerOptions<T>,
|
||||||
|
private val layoutInflater: LayoutInflater
|
||||||
|
) :
|
||||||
FirebaseRecyclerAdapter<T, CustomViewHolder<VB>>(options) {
|
FirebaseRecyclerAdapter<T, CustomViewHolder<VB>>(options) {
|
||||||
|
|
||||||
private val connectivityManager = layoutInflater.context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager
|
private val connectivityManager =
|
||||||
|
layoutInflater.context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager
|
||||||
|
|
||||||
private var _binding: VB? = null
|
private var _binding: VB? = null
|
||||||
val binding: VB
|
val binding: VB
|
||||||
@@ -50,6 +55,26 @@ open class BaseFirebaseAdapter<T: Any, VB : ViewBinding>(options: FirebaseRecycl
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun connectionLost() {}
|
open fun connectionLost() {}
|
||||||
|
override fun onDataChanged() {
|
||||||
|
super.onDataChanged()
|
||||||
|
if (itemCount == 0) emptyList()
|
||||||
|
}
|
||||||
|
override fun onError(error: DatabaseError) {
|
||||||
|
super.onError(error)
|
||||||
|
when (error.code) {
|
||||||
|
DatabaseError.PERMISSION_DENIED -> permissionsDenied()
|
||||||
|
DatabaseError.DISCONNECTED, DatabaseError.UNAVAILABLE, DatabaseError.NETWORK_ERROR -> noConnection()
|
||||||
|
DatabaseError.EXPIRED_TOKEN, DatabaseError.OPERATION_FAILED, DatabaseError.INVALID_TOKEN, DatabaseError.MAX_RETRIES -> authorizationError()
|
||||||
|
else -> cannotRetrieve()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun permissionsDenied() {}
|
||||||
|
open fun noConnection() {}
|
||||||
|
open fun cannotRetrieve() {}
|
||||||
|
open fun authorizationError() {}
|
||||||
|
open fun emptyList() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomViewHolder<VB : ViewBinding>(val viewBinding: VB) : ViewHolder(viewBinding.root)
|
class CustomViewHolder<VB : ViewBinding>(val viewBinding: VB) : ViewHolder(viewBinding.root)
|
||||||
@@ -20,6 +20,9 @@ abstract class BaseViewModel : ViewModel() {
|
|||||||
uiState.postValue(ViewState.HasError(Event(error)))
|
uiState.postValue(ViewState.HasError(Event(error)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All in one function for trying an operation and handling its start and failure
|
||||||
|
*/
|
||||||
suspend fun doTryOperation(
|
suspend fun doTryOperation(
|
||||||
defaultErrorMessage: String?,
|
defaultErrorMessage: String?,
|
||||||
operation: suspend () -> Unit
|
operation: suspend () -> Unit
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ package h_mal.appttude.com.driver.data
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.google.android.gms.tasks.Task
|
import com.google.android.gms.tasks.Task
|
||||||
import com.google.firebase.auth.*
|
import com.google.firebase.auth.AuthResult
|
||||||
|
import com.google.firebase.auth.EmailAuthProvider
|
||||||
|
import com.google.firebase.auth.FirebaseAuth
|
||||||
|
import com.google.firebase.auth.FirebaseUser
|
||||||
|
import com.google.firebase.auth.UserProfileChangeRequest
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class FirebaseAuthSource : FirebaseAuthentication {
|
class FirebaseAuthSource : FirebaseAuthentication {
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package h_mal.appttude.com.driver.utils
|
||||||
|
|
||||||
|
import com.google.firebase.database.DatabaseError
|
||||||
|
|
||||||
|
class FirebaseException(
|
||||||
|
private val databaseError: DatabaseError
|
||||||
|
) : RuntimeException(databaseError.message, databaseError.toException()) {
|
||||||
|
|
||||||
|
fun getCode() = databaseError.code
|
||||||
|
fun getDetails() = databaseError.details
|
||||||
|
|
||||||
|
fun getErrorStatus(): Status {
|
||||||
|
return Status.getByScore(getCode()) ?: Status.UNKNOWN_ERROR
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Status(private val code: Int) {
|
||||||
|
DATA_STALE(-1),
|
||||||
|
/** The server indicated that this operation failed */
|
||||||
|
OPERATION_FAILED(-2),
|
||||||
|
/** This client does not have permission to perform this operation */
|
||||||
|
PERMISSION_DENIED(-3),
|
||||||
|
/** The operation had to be aborted due to a network disconnect */
|
||||||
|
DISCONNECTED(-4),
|
||||||
|
/** The supplied auth token has expired */
|
||||||
|
EXPIRED_TOKEN (-6),
|
||||||
|
/**
|
||||||
|
* The specified authentication token is invalid. This can occur when the token is malformed,
|
||||||
|
* expired, or the secret that was used to generate it has been revoked.
|
||||||
|
*/
|
||||||
|
INVALID_TOKEN(-7),
|
||||||
|
/** The transaction had too many retries */
|
||||||
|
MAX_RETRIES(-8),
|
||||||
|
/** The transaction was overridden by a subsequent set */
|
||||||
|
OVERRIDDEN_BY_SET(-9),
|
||||||
|
/** The service is unavailable */
|
||||||
|
UNAVAILABLE(-10),
|
||||||
|
/** An exception occurred in user code */
|
||||||
|
USER_CODE_EXCEPTION(-11),
|
||||||
|
/** The operation could not be performed due to a network error. */
|
||||||
|
NETWORK_ERROR(-24),
|
||||||
|
/** The write was canceled locally */
|
||||||
|
WRITE_CANCELED(-25),
|
||||||
|
/**
|
||||||
|
* An unknown error occurred. Please refer to the error message and error details for more
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
UNKNOWN_ERROR(-999);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
infix fun getByScore(value: Int): Status? =
|
||||||
|
Status.values().firstOrNull { it.code == value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -30,7 +30,6 @@ suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCorouti
|
|||||||
/**
|
/**
|
||||||
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
|
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @return T
|
* @return T
|
||||||
*/
|
*/
|
||||||
suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef(): T? {
|
suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef(): T? {
|
||||||
@@ -39,7 +38,23 @@ suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef():
|
|||||||
response.snapshot.getValue(T::class.java)
|
response.snapshot.getValue(T::class.java)
|
||||||
}
|
}
|
||||||
is EventResponse.Cancelled -> {
|
is EventResponse.Cancelled -> {
|
||||||
throw response.error.toException()
|
throw FirebaseException(response.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
|
||||||
|
*
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
suspend inline fun <reified T : Any> DatabaseReference.getListDataFromDatabaseRef(): List<T?> {
|
||||||
|
return when (val response: EventResponse = singleValueEvent()) {
|
||||||
|
is EventResponse.Changed -> {
|
||||||
|
response.snapshot.children.map { it.getValue(T::class.java) }
|
||||||
|
}
|
||||||
|
is EventResponse.Cancelled -> {
|
||||||
|
throw FirebaseException(response.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +65,7 @@ suspend fun <T: Any> DatabaseReference.getDataFromDatabaseRef(clazz : Class<T>):
|
|||||||
response.snapshot.getValue(clazz)
|
response.snapshot.getValue(clazz)
|
||||||
}
|
}
|
||||||
is EventResponse.Cancelled -> {
|
is EventResponse.Cancelled -> {
|
||||||
throw response.error.toException()
|
throw FirebaseException(response.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@ package h_mal.appttude.com.driver.utils
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
@@ -16,7 +15,6 @@ import android.view.inputmethod.InputMethodManager
|
|||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
|||||||
BIN
app/src/main/res/drawable-hdpi/splash_screen.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
app/src/main/res/drawable-mdpi/splash_screen.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
app/src/main/res/drawable-xhdpi/splash_screen.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
app/src/main/res/drawable-xxhdpi/splash_screen.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/splash_screen.png
Normal file
|
After Width: | Height: | Size: 185 KiB |
5
app/src/main/res/drawable/baseline_inbox_24.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="72dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="72dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,3L4.99,3c-1.11,0 -1.98,0.89 -1.98,2L3,19c0,1.1 0.88,2 1.99,2L19,21c1.1,0 2,-0.9 2,-2L21,5c0,-1.11 -0.9,-2 -2,-2zM19,15h-4c0,1.66 -1.35,3 -3,3s-3,-1.34 -3,-3L4.99,15L4.99,5L19,5v10z"/>
|
||||||
|
</vector>
|
||||||
@@ -105,4 +105,15 @@
|
|||||||
<string name="approve">Approve</string>
|
<string name="approve">Approve</string>
|
||||||
<string name="deny">Deny</string>
|
<string name="deny">Deny</string>
|
||||||
<string name="decline">Decline</string>
|
<string name="decline">Decline</string>
|
||||||
|
<string name="no_drivers_to_show">No drivers to show</string>
|
||||||
|
<string name="no_drivers_subtext">There are no drivers present for your organisation.</string>
|
||||||
|
<string name="no_permission">You do not have permissions to view</string>
|
||||||
|
<string name="no_permission_subtext">You are not a super user. Contact us to get super user access.</string>
|
||||||
|
<string name="cannot_retrieve">Cannot retrieve data.</string>
|
||||||
|
<string name="cannot_retrieve_subtext">Check you are logged in correctly and have a working connection.</string>
|
||||||
|
<string name="no_connection">No connection</string>
|
||||||
|
<string name="no_connection_subtext">Make you have a valid internet connection.</string>
|
||||||
|
<string name="no_authorization">Authentication has failed</string>
|
||||||
|
<string name="no_authorization_subtext">There is a problem with authentication.</string>
|
||||||
|
<string name="image_icon_for_feedback_view">Image icon for feedback view.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
{
|
{
|
||||||
"rules": {
|
"rules": {
|
||||||
".read": true,
|
"user": {
|
||||||
".write": true
|
".read": "root.child('user').child(auth.uid).child('role').val() == 'admin'",
|
||||||
|
"$user_id": {
|
||||||
|
".write": "$user_id === auth.uid",
|
||||||
|
".read": "$user_id === auth.uid",
|
||||||
|
"driver_number": {
|
||||||
|
".write": "root.child('user').child(auth.uid).child('role').val() == 'admin'",
|
||||||
|
".read": "root.child('user').child(auth.uid).child('role').val() == 'admin'"
|
||||||
|
},
|
||||||
|
"approvalsObject": {
|
||||||
|
".write": "root.child('user').child(auth.uid).child('role').val() == 'admin'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "identitytoolkit#DownloadAccountResponse",
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"localId": "zMoJiXJfG6hkzbo2okyZfurFZcA2",
|
|
||||||
"lastLoginAt": "1683571061431",
|
|
||||||
"displayName": "",
|
|
||||||
"photoUrl": "",
|
|
||||||
"emailVerified": false,
|
|
||||||
"email": "admin@driver.com",
|
|
||||||
"salt": "fakeSaltUnq9EmXjgHjuCkthZxWg",
|
|
||||||
"passwordHash": "fakeHash:salt=fakeSaltUnq9EmXjgHjuCkthZxWg:password=test123456",
|
|
||||||
"passwordUpdatedAt": 1683577711815,
|
|
||||||
"validSince": "1683577711",
|
|
||||||
"createdAt": "1683571061431",
|
|
||||||
"providerUserInfo": [
|
|
||||||
{
|
|
||||||
"providerId": "password",
|
|
||||||
"email": "admin@driver.com",
|
|
||||||
"federatedId": "admin@driver.com",
|
|
||||||
"rawId": "admin@driver.com",
|
|
||||||
"displayName": "Admin",
|
|
||||||
"photoUrl": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"initialEmail": "test-user-1234@domain.com",
|
|
||||||
"customAttributes": "",
|
|
||||||
"lastRefreshAt": "2023-05-08T20:28:31.821Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"localId": "ajIKGtLVYXWlmnKrhDRSJHEKbnT2",
|
|
||||||
"createdAt": "1683501517092",
|
|
||||||
"lastLoginAt": "1683576853029",
|
|
||||||
"passwordHash": "fakeHash:salt=fakeSaltbteVu3VkZRQNIoW3kLfx:password=test123456",
|
|
||||||
"salt": "fakeSaltbteVu3VkZRQNIoW3kLfx",
|
|
||||||
"passwordUpdatedAt": 1683577693985,
|
|
||||||
"providerUserInfo": [
|
|
||||||
{
|
|
||||||
"providerId": "password",
|
|
||||||
"email": "existing-driver@driver.com",
|
|
||||||
"federatedId": "existing-driver@driver.com",
|
|
||||||
"rawId": "existing-driver@driver.com",
|
|
||||||
"displayName": "Existing Driver",
|
|
||||||
"photoUrl": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validSince": "1683577693",
|
|
||||||
"email": "existing-driver@driver.com",
|
|
||||||
"emailVerified": false,
|
|
||||||
"disabled": false,
|
|
||||||
"displayName": "",
|
|
||||||
"photoUrl": "",
|
|
||||||
"customAttributes": "",
|
|
||||||
"lastRefreshAt": "2023-05-08T20:28:13.994Z",
|
|
||||||
"initialEmail": "test-12312341234@test.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"signIn":{"allowDuplicateEmails":false}}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "11.16.1",
|
|
||||||
"database": {
|
|
||||||
"version": "4.11.0",
|
|
||||||
"path": "database_export"
|
|
||||||
},
|
|
||||||
"auth": {
|
|
||||||
"version": "11.16.1",
|
|
||||||
"path": "auth_export"
|
|
||||||
},
|
|
||||||
"storage": {
|
|
||||||
"version": "11.16.1",
|
|
||||||
"path": "storage_export"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
--boundary
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{"contentType":"text/plain"}
|
|
||||||
--boundary
|
|
||||||
Content-Type: text/plain
|
|
||||||
|
|
||||||
--boundary--
|
|
||||||
|
Before Width: | Height: | Size: 797 KiB |
|
Before Width: | Height: | Size: 472 KiB |
|
Before Width: | Height: | Size: 485 KiB |
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"buckets": [
|
|
||||||
{
|
|
||||||
"id": "driver-8f4a1.appspot.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "images/",
|
|
||||||
"bucket": "driver-8f4a1.appspot.com",
|
|
||||||
"metageneration": 1,
|
|
||||||
"generation": 1683551806682,
|
|
||||||
"contentType": "application/octet-stream",
|
|
||||||
"storageClass": "STANDARD",
|
|
||||||
"downloadTokens": [],
|
|
||||||
"etag": "NcqbeHuAupLobMTaRYOZ/x8enig",
|
|
||||||
"timeCreated": "2023-05-08T13:16:46.683Z",
|
|
||||||
"updated": "2023-05-08T13:16:46.683Z",
|
|
||||||
"size": 130,
|
|
||||||
"md5Hash": "iUpceipDkyQhwwUflucD5w==",
|
|
||||||
"crc32c": "3108464614"
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "images/9lOskPBmh3TYMs2qiZ3Q82KXFvB2/private_hire/private_hire20190130_1357.jpg",
|
|
||||||
"bucket": "driver-8f4a1.appspot.com",
|
|
||||||
"metageneration": 1,
|
|
||||||
"generation": 1683568267475,
|
|
||||||
"contentType": "image/jpeg",
|
|
||||||
"storageClass": "STANDARD",
|
|
||||||
"contentDisposition": "inline",
|
|
||||||
"downloadTokens": [
|
|
||||||
"2b3a82a2-399c-47f4-8e92-42e4b0596a99"
|
|
||||||
],
|
|
||||||
"etag": "EERbKfXWaNq1YOtfGA+DNYdiCRs",
|
|
||||||
"customMetadata": {},
|
|
||||||
"timeCreated": "2023-05-08T17:51:07.475Z",
|
|
||||||
"updated": "2023-05-08T17:51:07.475Z",
|
|
||||||
"size": 815900,
|
|
||||||
"md5Hash": "qfRQ4iMDJ1PqTYs7ZgrdpQ==",
|
|
||||||
"crc32c": "166652588"
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "images/9lOskPBmh3TYMs2qiZ3Q82KXFvB2/insurance_details/insurance_details20190128_2237.jpg",
|
|
||||||
"bucket": "driver-8f4a1.appspot.com",
|
|
||||||
"metageneration": 1,
|
|
||||||
"generation": 1683552616857,
|
|
||||||
"contentType": "image/jpeg",
|
|
||||||
"storageClass": "STANDARD",
|
|
||||||
"contentDisposition": "inline",
|
|
||||||
"downloadTokens": [
|
|
||||||
"05adb212-7d90-476b-95c3-ee8994926304"
|
|
||||||
],
|
|
||||||
"etag": "8vp7WfaGgmHxb9z7tb2er5PKEZU",
|
|
||||||
"customMetadata": {},
|
|
||||||
"timeCreated": "2023-05-08T13:30:16.857Z",
|
|
||||||
"updated": "2023-05-08T13:30:16.857Z",
|
|
||||||
"size": 483618,
|
|
||||||
"md5Hash": "+YPWiWjS5IXrIrW/SVUMxg==",
|
|
||||||
"crc32c": "1336424719"
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "images/9lOskPBmh3TYMs2qiZ3Q82KXFvB2/driver_license/driver_license20190126_1158.jpg",
|
|
||||||
"bucket": "driver-8f4a1.appspot.com",
|
|
||||||
"metageneration": 1,
|
|
||||||
"generation": 1683551991075,
|
|
||||||
"contentType": "image/jpeg",
|
|
||||||
"storageClass": "STANDARD",
|
|
||||||
"contentDisposition": "inline",
|
|
||||||
"downloadTokens": [
|
|
||||||
"bd571934-7b2b-47da-88e9-57262dcf6a9a"
|
|
||||||
],
|
|
||||||
"etag": "JopF4/sHrSPja4lob6BOxDLtsmM",
|
|
||||||
"customMetadata": {},
|
|
||||||
"timeCreated": "2023-05-08T13:19:51.075Z",
|
|
||||||
"updated": "2023-05-08T13:19:51.075Z",
|
|
||||||
"size": 496645,
|
|
||||||
"md5Hash": "M4gyQ2HkzHPhonCo6NB/3Q==",
|
|
||||||
"crc32c": "2741797550"
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 386 KiB |
|
Before Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 432 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 45 KiB |