many things done
This commit is contained in:
3
.idea/deploymentTargetSelector.xml
generated
3
.idea/deploymentTargetSelector.xml
generated
@@ -13,6 +13,9 @@
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="ProjectActivity">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dreamteam.timelapse
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
@@ -7,6 +8,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
|
||||
class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRefreshLayout(context, attrs) {
|
||||
init {
|
||||
this.setEnabled(true)
|
||||
this.setRefreshing(true)
|
||||
Log.d("CustomSwipeRefreshLayout", "CustomSwipeRefreshLayout instancié")
|
||||
}
|
||||
override fun canChildScrollUp(): Boolean {
|
||||
@@ -15,4 +18,22 @@ class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRef
|
||||
//Log.i("CustomSwipeRefreshLayout", "canChildScrollUp: ${view?.canScrollVertically(-1)}")
|
||||
return view != null && view.canScrollVertically(-1)
|
||||
}
|
||||
private var mMeasured = false
|
||||
private var mPreMeasureRefreshing = false
|
||||
|
||||
|
||||
// fun dragDown(){
|
||||
// this.post {
|
||||
// Log.i("SwipeRefreshLayout", "Je suis delanché par le code")
|
||||
// val distanceToMove = 200 // La distance que l'on veut faire descendre l'élément, ajustable
|
||||
// val valueAnimator = ValueAnimator.ofInt(0, distanceToMove)
|
||||
// valueAnimator.addUpdateListener { animation ->
|
||||
// val value = animation.animatedValue as Int
|
||||
// // Manipule le mouvement de l'animation du rafraîchissement
|
||||
// this.setProgressViewOffset(false, 0, value)
|
||||
// }
|
||||
// valueAnimator.duration = 500 // Durée de l'animation
|
||||
// valueAnimator.start()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
62
app/src/main/java/com/dreamteam/timelapse/ImageAdapter.kt
Normal file
62
app/src/main/java/com/dreamteam/timelapse/ImageAdapter.kt
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.dreamteam.timelapse
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
|
||||
|
||||
|
||||
class ImageAdapter(private val imageUrls: List<String>) : RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() {
|
||||
|
||||
// ViewHolder qui contient l'ImageView
|
||||
class ImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val imageView: ImageView = itemView.findViewById(R.id.imageView)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_image, parent, false)
|
||||
return ImageViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
|
||||
val imageUrl = imageUrls[position]
|
||||
//Log.e("ImageAdapter", imageUrl)
|
||||
Glide.with(holder.itemView.context)
|
||||
.load(imageUrl) // Charge l'image via Glide
|
||||
.into(holder.imageView) // Affiche l'image dans l'ImageView
|
||||
}
|
||||
private fun downloadImage(url: String, context: Context) {
|
||||
Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.into(object : SimpleTarget<Bitmap>() {
|
||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||
// Save the image to the app's internal storage
|
||||
val file = File(context.filesDir, "downloaded_image.jpg")
|
||||
try {
|
||||
val fileOutputStream = FileOutputStream(file)
|
||||
resource.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
|
||||
fileOutputStream.flush()
|
||||
fileOutputStream.close()
|
||||
Toast.makeText(context, "Image downloaded successfully", Toast.LENGTH_SHORT).show()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, "Error downloading image", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
override fun getItemCount(): Int = imageUrls.size
|
||||
}
|
||||
@@ -1,36 +1,46 @@
|
||||
package com.dreamteam.timelapse
|
||||
|
||||
import android.R
|
||||
import com.dreamteam.timelapse.R as Rtmp
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.dreamteam.timelapse.databinding.ActivityMainBinding
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.dreamteam.timelapse.R as Rtmp
|
||||
import com.dreamteam.timelapse.R
|
||||
import com.dreamteam.timelapse.data.ApiService
|
||||
import com.dreamteam.timelapse.data.ProjectRepository
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var projectRepository : ProjectRepository
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// super.onCreate(savedInstanceState)
|
||||
//
|
||||
|
||||
val retrofit = Retrofit.Builder()
|
||||
.baseUrl("https://timelapse.kerboul.me/api/")
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
projectRepository = ProjectRepository(retrofit.create(ApiService::class.java))
|
||||
Log.d("mainActivity", "La main activity est créée")
|
||||
|
||||
|
||||
// setSupportActionBar(binding.toolbar)
|
||||
//
|
||||
super.onCreate(savedInstanceState)
|
||||
//val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
//appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||
@@ -46,13 +56,13 @@ class MainActivity : AppCompatActivity() {
|
||||
setContentView(Rtmp.layout.activity_main)
|
||||
val tabLayout = findViewById<View>(Rtmp.id.tabLayout) as TabLayout
|
||||
val viewPager = findViewById<View>(Rtmp.id.viewPager) as ViewPager2
|
||||
createDialog(findViewById<View>(Rtmp.id.fab))
|
||||
|
||||
|
||||
// Configurer l'adapter pour ViewPager2
|
||||
var tabsAdapter = TabsAdapter(this)
|
||||
viewPager.setAdapter(tabsAdapter)
|
||||
|
||||
|
||||
// Connecter le ViewPager au TabLayout
|
||||
TabLayoutMediator(
|
||||
tabLayout, viewPager
|
||||
@@ -63,12 +73,39 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}.attach()
|
||||
|
||||
// Bouton flottant
|
||||
// binding.fab.setOnClickListener { view ->
|
||||
// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
// //.setAction("Action", null) //sert à rien
|
||||
// .setAnchorView(R.id.fab).show() //au dessus du bouton mail
|
||||
// }
|
||||
//Bouton flottant
|
||||
findViewById<View>(Rtmp.id.fab).setOnClickListener { view -> run {
|
||||
this.dialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createDialog(viewfortoast: View){
|
||||
//Preparing views
|
||||
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
val layout: View = inflater.inflate(
|
||||
R.layout.project_create_dialog_layout,
|
||||
findViewById<LinearLayout>(R.id.layout_root)
|
||||
)
|
||||
|
||||
val project_name = layout.findViewById<View>(Rtmp.id.project_name_dialog) as EditText
|
||||
val project_desc = layout.findViewById<View>(Rtmp.id.project_desc_dialog) as EditText
|
||||
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
|
||||
builder.setView(layout)
|
||||
builder.setPositiveButton("Save",
|
||||
DialogInterface.OnClickListener { dialog, which ->
|
||||
val onSuccess : () -> Unit = {dialog.dismiss() ; Snackbar.make(viewfortoast, "Nouveau projet créé", Snackbar.LENGTH_LONG).setAnchorView(Rtmp.id.fab).show() ; }
|
||||
val onError : (s:String) -> Unit = { s-> Snackbar.make(viewfortoast, "Erreur lors de la création du projet. ${s}", Snackbar.LENGTH_LONG).setAnchorView(Rtmp.id.fab).show() }
|
||||
|
||||
projectRepository.createProject(project_name.text.toString(), project_desc.text.toString(), onSuccess, onError)
|
||||
|
||||
})
|
||||
builder.setNegativeButton("Cancel",
|
||||
DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })
|
||||
val dialog: AlertDialog = builder.create()
|
||||
this.dialog = dialog
|
||||
|
||||
}
|
||||
|
||||
// override fun onSupportNavigateUp(): Boolean {
|
||||
|
||||
@@ -1,61 +1,74 @@
|
||||
package com.dreamteam.timelapse
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||
import com.dreamteam.timelapse.data.ApiService
|
||||
import com.dreamteam.timelapse.data.Measurement
|
||||
import com.dreamteam.timelapse.data.Project
|
||||
import com.dreamteam.timelapse.data.ProjectRepository
|
||||
import com.dreamteam.timelapse.databinding.ProjectBinding
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.dreamteam.timelapse.R
|
||||
import com.github.mikephil.charting.charts.LineChart
|
||||
import com.github.mikephil.charting.data.Entry
|
||||
import com.github.mikephil.charting.data.LineData
|
||||
import com.github.mikephil.charting.data.LineDataSet
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
class ProjectActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ProjectBinding
|
||||
private lateinit var projectRepository: ProjectRepository
|
||||
private lateinit var apiService: ApiService // Déclare l'apiService
|
||||
private var measures: List<Measurement> = emptyList() // Déclare une liste de projets vide
|
||||
private var project: Project? = null
|
||||
private var imageUrls = emptyList<String>()
|
||||
|
||||
private class GridSpacingItemDecoration(private val spacing: Int) : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
||||
val position = parent.getChildAdapterPosition(view) // Position de l'item
|
||||
if (position == RecyclerView.NO_POSITION) return
|
||||
|
||||
outRect.left = spacing / 2
|
||||
outRect.right = spacing / 2
|
||||
outRect.top = spacing
|
||||
}
|
||||
}
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val project = intent.getParcelableExtra<Project>("PROJECT") // -1 est la valeur par défaut si l'ID n'est pas trouvé
|
||||
Log.d("project", "La project activity "+project?.id+" est créée")
|
||||
val retrofit = Retrofit.Builder()
|
||||
.baseUrl("https://timelapse.kerboul.me/api/")
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
apiService = retrofit.create(ApiService::class.java) // Crée une instance d'ApiService
|
||||
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
|
||||
|
||||
this.project = intent.getParcelableExtra<Project>("PROJECT") // -1 est la valeur par défaut si l'ID n'est pas trouvé
|
||||
Log.d("project", "La project activity "+this.project?.id+" est créée")
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ProjectBinding.inflate(layoutInflater)
|
||||
this.binding = ProjectBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
// Initialisation du graphique
|
||||
val temperatureHumidityChart = binding.temperatureHumidityChart
|
||||
|
||||
// Données fictives (température et humidité)
|
||||
val temperatureEntries = mutableListOf<Entry>()
|
||||
val humidityEntries = mutableListOf<Entry>()
|
||||
initProjectInfo()
|
||||
|
||||
// Ajouter des points de données (exemples)
|
||||
temperatureEntries.add(Entry(0f, 25f)) // (temps, température)
|
||||
humidityEntries.add(Entry(0f, 60f)) // (temps, humidité)
|
||||
fetchMeasuresAndRebuildGraph()
|
||||
val swipeRefreshLayout = binding.swipeRefreshLayout
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
fetchMeasuresAndRebuildGraph()
|
||||
Log.d("ProjetsFrag", "Actualisation des projets")
|
||||
}
|
||||
|
||||
// Créer des LineDataSet pour chaque série de données
|
||||
val temperatureDataSet = LineDataSet(temperatureEntries, "Température")
|
||||
val humidityDataSet = LineDataSet(humidityEntries, "Hygrométrie")
|
||||
|
||||
// Ajouter les datasets au graphique
|
||||
val lineData = LineData(temperatureDataSet, humidityDataSet)
|
||||
temperatureHumidityChart.data = lineData
|
||||
|
||||
// Personnaliser le graphique (par exemple, couleur, légende, etc.)
|
||||
temperatureDataSet.color = Color.RED
|
||||
humidityDataSet.color = Color.BLUE
|
||||
|
||||
temperatureHumidityChart.invalidate() // Rafraîchir le graphique
|
||||
|
||||
//super.onCreate(savedInstanceState)
|
||||
val nameview = findViewById<TextView>(R.id.project_name)
|
||||
val descriptionview = findViewById<TextView>(R.id.project_name)
|
||||
val beginview = findViewById<TextView>(R.id.project_start_date)
|
||||
val statusview = findViewById<TextView>(R.id.project_status)
|
||||
|
||||
|
||||
|
||||
@@ -66,4 +79,92 @@ class ProjectActivity : AppCompatActivity() {
|
||||
// .setAnchorView(R.id.fab).show() //au dessus du bouton mail
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
fun fetchMeasuresAndRebuildGraph(){
|
||||
this.project?.let{
|
||||
projectRepository.fetchMeasurementsOfProject(it.id,
|
||||
onSuccess = { measures ->
|
||||
Log.d("ProjectActivity", "Mesures reçus : $measures")
|
||||
this.measures = measures
|
||||
if(this.measures.size > 0)
|
||||
initGraph(this.measures)
|
||||
|
||||
val adapter = ImageAdapter(this.measures.map { m-> "https://timelapse.kerboul.me/api/images/${m.project_id}/${m.order_id}"}) //ImageAdapter(imageUrls)
|
||||
binding.imagesList.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL)
|
||||
binding.imagesList.addItemDecoration(GridSpacingItemDecoration(16)) // 16px spacing
|
||||
binding.imagesList.adapter = adapter
|
||||
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
//this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
|
||||
//this.recyclerView.adapter = this.projectAdapter
|
||||
// Mettre à jour le RecyclerView ou autre traitement
|
||||
},
|
||||
onError = { errorMessage ->
|
||||
Log.e("ProjectActivity", errorMessage)
|
||||
fetchMeasuresAndRebuildGraph()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun initGraph(lm : List<Measurement>){
|
||||
val temperatureHumidityChart = this.binding.temperatureHumidityChart
|
||||
|
||||
val temperatures = lm.sortedBy { p -> p.order_id }
|
||||
.map { m -> Pair(m.temperature, m.timestamp) }
|
||||
val humidities = lm.sortedBy { p -> p.order_id }
|
||||
.map { m -> Pair(m.humidity, m.timestamp) }
|
||||
|
||||
// Ajouter des points de données (exemples)
|
||||
val temperatureEntries = temperatures.map { pair ->
|
||||
Entry((pair.second.time).toFloat(), pair.first) // (timestamp, température)
|
||||
}
|
||||
|
||||
val humidityEntries = humidities.map { pair ->
|
||||
Entry((pair.second.time).toFloat(), pair.first) // (timestamp, humidité)
|
||||
}
|
||||
|
||||
// Créer des LineDataSet pour chaque série de données
|
||||
val temperatureDataSet = LineDataSet(temperatureEntries, "Température")
|
||||
val humidityDataSet = LineDataSet(humidityEntries, "Hygrométrie")
|
||||
Log.i("ProjectActivity", temperatureEntries.toString())
|
||||
val minX = temperatureEntries.minOf { it.x } // La valeur minimale de x
|
||||
val maxX = temperatureEntries.maxOf { it.x } // La valeur maximale de x
|
||||
val xAxis = temperatureHumidityChart.xAxis
|
||||
xAxis.valueFormatter = object : ValueFormatter() {
|
||||
override fun getFormattedValue(value: Float): String {
|
||||
val date = Date(value.toLong())
|
||||
val sdf = SimpleDateFormat("hh:mm", Locale.getDefault())
|
||||
return sdf.format(date)
|
||||
}
|
||||
}
|
||||
xAxis.axisMinimum = minX
|
||||
xAxis.axisMaximum = maxX
|
||||
// Ajouter les datasets au graphique
|
||||
val dataSets: MutableList<ILineDataSet> = ArrayList()
|
||||
dataSets.add(temperatureDataSet)
|
||||
dataSets.add(humidityDataSet)
|
||||
// val lineData = LineData(temperatureDataSet, humidityDataSet)
|
||||
//Log.e("Graph", lineData.getDataSetByIndex(0).entryCount.toString())
|
||||
temperatureHumidityChart.data = LineData(dataSets)
|
||||
|
||||
|
||||
// Personnaliser le graphique (par exemple, couleur, légende, etc.)
|
||||
temperatureDataSet.color = Color.RED
|
||||
humidityDataSet.color = Color.BLUE
|
||||
|
||||
temperatureHumidityChart.invalidate() // Rafraîchir le graphique
|
||||
}
|
||||
|
||||
fun initProjectInfo(){
|
||||
val nameview = findViewById<TextView>(R.id.project_name)
|
||||
val descriptionview = findViewById<TextView>(R.id.project_description)
|
||||
val beginview = findViewById<TextView>(R.id.project_start_date)
|
||||
val statusview = findViewById<TextView>(R.id.project_status)
|
||||
|
||||
nameview.text = project!!.name
|
||||
descriptionview.text = project!!.description
|
||||
beginview.text = project!!.start_date.toString()
|
||||
statusview.text = project!!.getStatusText()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,12 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.dreamteam.timelapse.data.Project
|
||||
|
||||
class ProjectAdapter(private val projects: List<Project>, private val listener: OnEmptyStateListener) : RecyclerView.Adapter<ProjectAdapter.ProjectViewHolder>() {
|
||||
init{
|
||||
listener.onEmptyStateChanged(projects.isEmpty())
|
||||
}
|
||||
|
||||
interface OnEmptyStateListener {
|
||||
fun onEmptyStateChanged(isEmpty: Boolean)
|
||||
@@ -30,7 +34,6 @@ class ProjectAdapter(private val projects: List<Project>, private val listener:
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_project_card, parent, false)
|
||||
|
||||
//projects.isEmpty()
|
||||
listener.onEmptyStateChanged(projects.isEmpty())
|
||||
|
||||
return ProjectViewHolder(view)
|
||||
}
|
||||
|
||||
@@ -2,20 +2,17 @@ package com.dreamteam.timelapse
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ListView
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.dreamteam.timelapse.data.ProjectRepository
|
||||
import com.dreamteam.timelapse.databinding.FragmentProjetsBinding
|
||||
import com.dreamteam.timelapse.databinding.FragmentVideosBinding
|
||||
import kotlinx.coroutines.delay
|
||||
import com.dreamteam.timelapse.data.ApiService
|
||||
import com.dreamteam.timelapse.data.Project
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
@@ -50,11 +47,11 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
Log.d("ProjetsFrag", "Fragment Projets créé")
|
||||
_binding = FragmentProjetsBinding.inflate(inflater, container, false)
|
||||
Log.d("ProjetsFrag", "Fragment Projets créé")
|
||||
|
||||
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
|
||||
fetchProjects()
|
||||
//fetchProjects()
|
||||
|
||||
return _binding?.root
|
||||
}
|
||||
@@ -68,6 +65,7 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
||||
fetchProjects()
|
||||
Log.d("ProjetsFrag", "Actualisation des projets")
|
||||
}
|
||||
fetchProjects()
|
||||
|
||||
recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView)
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
@@ -77,8 +75,11 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
||||
|
||||
private fun fetchProjects() {
|
||||
// Simulez l'appel API
|
||||
binding.swipeRefreshLayout.isRefreshing = true
|
||||
binding.swipeRefreshLayout.setEnabled(true)
|
||||
binding.swipeRefreshLayout.setRefreshing(true)
|
||||
//binding.swipeRefreshLayout.
|
||||
|
||||
//binding.swipeRefreshLayout.dragDown()
|
||||
Log.d("ProjetsFrag", "User has refreshed the projects list")
|
||||
projectRepository.fetchProjects(
|
||||
onSuccess = { projects ->
|
||||
@@ -89,7 +90,12 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
||||
// Mettre à jour le RecyclerView ou autre traitement
|
||||
},
|
||||
onError = { errorMessage ->
|
||||
Log.e("ProjetsFrag", errorMessage)
|
||||
Log.e("ProjetsFrag prout", errorMessage)
|
||||
//onEmptyStateChanged(true)
|
||||
this.projects = listOf<Project>()
|
||||
this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
|
||||
this.recyclerView.adapter = this.projectAdapter
|
||||
|
||||
}
|
||||
)
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
|
||||
@@ -17,4 +17,5 @@ class TabsAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
|
||||
else -> ProjetsFrag() // Par défaut
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +1,112 @@
|
||||
package com.dreamteam.timelapse
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dreamteam.timelapse.databinding.FragmentVideosBinding
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.dreamteam.timelapse.data.ProjectRepository
|
||||
import com.dreamteam.timelapse.databinding.FragmentProjetsBinding
|
||||
import com.dreamteam.timelapse.data.ApiService
|
||||
import com.dreamteam.timelapse.data.Project
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the second destination in the navigation.
|
||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||
*/
|
||||
class VideoFrag : Fragment() {
|
||||
|
||||
private var _binding: FragmentVideosBinding? = null
|
||||
class VideoFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private lateinit var projectRepository: ProjectRepository
|
||||
//private lateinit var listView: ListView
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var projectAdapter: ProjectAdapter
|
||||
private var _binding: FragmentProjetsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private lateinit var apiService: ApiService // Déclare l'apiService
|
||||
private var projects: List<Project> = emptyList() // Déclare une liste de projets vide
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Initialiser apiService ici, par exemple, en utilisant Retrofit
|
||||
val retrofit = Retrofit.Builder()
|
||||
.baseUrl("https://timelapse.kerboul.me/api/")
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
|
||||
apiService = retrofit.create(ApiService::class.java) // Crée une instance d'ApiService
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
): View? {
|
||||
_binding = FragmentProjetsBinding.inflate(inflater, container, false)
|
||||
Log.d("ProjetsFrag", "Fragment Projets créé")
|
||||
|
||||
_binding = FragmentVideosBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
|
||||
//fetchProjects()
|
||||
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.buttonSecond.setOnClickListener {
|
||||
findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
|
||||
val swipeRefreshLayout = binding.swipeRefreshLayout
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
fetchProjects()
|
||||
Log.d("ProjetsFrag", "Actualisation des projets")
|
||||
}
|
||||
fetchProjects()
|
||||
|
||||
recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView)
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun fetchProjects() {
|
||||
// Simulez l'appel API
|
||||
binding.swipeRefreshLayout.setEnabled(true)
|
||||
binding.swipeRefreshLayout.setRefreshing(true)
|
||||
//binding.swipeRefreshLayout.
|
||||
|
||||
//binding.swipeRefreshLayout.dragDown()
|
||||
Log.d("ProjetsFrag", "User has refreshed the projects list")
|
||||
projectRepository.fetchProjects(
|
||||
onSuccess = { projects ->
|
||||
Log.d("ProjetsFrag", "Projets reçus : $projects")
|
||||
this.projects = projects
|
||||
this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
|
||||
this.recyclerView.adapter = this.projectAdapter
|
||||
// Mettre à jour le RecyclerView ou autre traitement
|
||||
},
|
||||
onError = { errorMessage ->
|
||||
Log.e("ProjetsFrag prout", errorMessage)
|
||||
//onEmptyStateChanged(true)
|
||||
this.projects = listOf<Project>()
|
||||
this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
|
||||
this.recyclerView.adapter = this.projectAdapter
|
||||
|
||||
}
|
||||
)
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
override fun onEmptyStateChanged(isEmpty: Boolean) {
|
||||
// Afficher ou masquer le message
|
||||
if (isEmpty) {
|
||||
binding.noProjectsText.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.noProjectsText.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
package com.dreamteam.timelapse.data
|
||||
import com.dreamteam.timelapse.Project
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface ApiService {
|
||||
@GET("projects") // Remplace par l'endpoint de ton API
|
||||
@GET("projects")
|
||||
fun getProjets(): Call<List<Project>>
|
||||
@GET("projects/{id}") // Remplace par l'endpoint de ton API
|
||||
@GET("projects/{id}")
|
||||
fun getProjet(@Path("id") projectId: Int): Call<Project>
|
||||
@GET("projects/{id}/measurements") // Remplace par l'endpoint de ton API
|
||||
fun getMeasurements(@Path("id") projectId: Int): Call<List<Measurement>>
|
||||
@POST("projects/")
|
||||
fun createProject(@Body project: Project): Call<Confirmation>
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.dreamteam.timelapse.data
|
||||
|
||||
data class Confirmation (
|
||||
val message: String,
|
||||
val id: Int
|
||||
){
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dreamteam.timelapse.data
|
||||
|
||||
import java.util.Date
|
||||
|
||||
data class Measurement(
|
||||
val id: Int,
|
||||
val project_id: Int,
|
||||
val timestamp: Date,
|
||||
val path: String,
|
||||
val temperature: Float,
|
||||
val humidity: Float,
|
||||
val order_id: Int
|
||||
) {
|
||||
}
|
||||
@@ -1,71 +1,74 @@
|
||||
package com.dreamteam.timelapse
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import java.util.Date
|
||||
|
||||
//{
|
||||
// "id": 1,
|
||||
// "creation": "2024-10-24T13:46:04.513Z",
|
||||
// "status": "test",
|
||||
// "description": "Projet de Test",
|
||||
// "titre": "Test Project"
|
||||
//}
|
||||
data class Project(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val start_date: Date,
|
||||
val status: Int,
|
||||
val thumbnail_url: String?
|
||||
) : Parcelable {
|
||||
|
||||
fun getStatusText(): String{
|
||||
val statusArr = arrayOf("Brouillon", "En Cours", "Terminé", "Annulé")
|
||||
return statusArr[status]
|
||||
}
|
||||
fun getStatusColor(): Int{
|
||||
return when (status) {
|
||||
0 -> R.color.brouillon
|
||||
1 -> R.color.en_cours
|
||||
2 -> R.color.termine
|
||||
3 -> R.color.annule
|
||||
else -> R.color.default_badge
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor to recreate from Parcel
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString() ?: "",
|
||||
parcel.readString() ?: "",
|
||||
Date(parcel.readLong()),
|
||||
parcel.readInt(),
|
||||
parcel.readString()
|
||||
)
|
||||
|
||||
// Write object to Parcel
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(id)
|
||||
parcel.writeString(name)
|
||||
parcel.writeString(description)
|
||||
parcel.writeString(start_date.toString())
|
||||
parcel.writeInt(status)
|
||||
}
|
||||
|
||||
// Describe the contents of the Parcel
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Project> {
|
||||
override fun createFromParcel(parcel: Parcel): Project {
|
||||
return Project(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Project?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
// fun getThumbnail(): String {
|
||||
// return images[0]
|
||||
// }
|
||||
}
|
||||
package com.dreamteam.timelapse.data
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import com.dreamteam.timelapse.R
|
||||
import java.util.Date
|
||||
|
||||
//{
|
||||
// "id": 1,
|
||||
// "creation": "2024-10-24T13:46:04.513Z",
|
||||
// "status": "test",
|
||||
// "description": "Projet de Test",
|
||||
// "titre": "Test Project"
|
||||
//}
|
||||
data class Project(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val start_date: Date,
|
||||
val status: Int,
|
||||
val thumbnail_url: String?
|
||||
) : Parcelable {
|
||||
|
||||
fun getStatusText(): String{
|
||||
Log.i("Project", "Status $status being trasnlated")
|
||||
val statusArr = arrayOf("Brouillon", "En Cours", "Terminé", "Annulé")
|
||||
return statusArr[status]
|
||||
}
|
||||
fun getStatusColor(): Int{
|
||||
return when (status) {
|
||||
0 -> R.color.brouillon
|
||||
1 -> R.color.en_cours
|
||||
2 -> R.color.termine
|
||||
3 -> R.color.annule
|
||||
else -> R.color.default_badge
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor to recreate from Parcel
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString() ?: "",
|
||||
parcel.readString() ?: "",
|
||||
Date(parcel.readLong()),
|
||||
parcel.readInt(),
|
||||
parcel.readString()
|
||||
)
|
||||
|
||||
// Write object to Parcel
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(id)
|
||||
parcel.writeString(name)
|
||||
parcel.writeString(description)
|
||||
parcel.writeLong(start_date.time)
|
||||
parcel.writeInt(status)
|
||||
}
|
||||
|
||||
// Describe the contents of the Parcel
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Project> {
|
||||
override fun createFromParcel(parcel: Parcel): Project {
|
||||
return Project(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Project?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
// fun getThumbnail(): String {
|
||||
// return images[0]
|
||||
// }
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.dreamteam.timelapse.data
|
||||
|
||||
import com.dreamteam.timelapse.Project
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import java.util.Date
|
||||
|
||||
class ProjectRepository(private val apiService: ApiService) {
|
||||
|
||||
@@ -26,4 +26,41 @@ class ProjectRepository(private val apiService: ApiService) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun fetchMeasurementsOfProject(pid: Int, onSuccess: (List<Measurement>) -> Unit, onError: (String) -> Unit) {
|
||||
val call = apiService.getMeasurements(pid)
|
||||
call.enqueue(object : Callback<List<Measurement>> {
|
||||
override fun onResponse(call: Call<List<Measurement>>, response: Response<List<Measurement>>) {
|
||||
if (response.isSuccessful) {
|
||||
val measures = response.body()
|
||||
measures?.let {
|
||||
onSuccess(it)
|
||||
} ?: onError("Aucune mesure trouvé")
|
||||
} else {
|
||||
onError("Erreur : ${response.code()}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Measurement>>, t: Throwable) {
|
||||
onError("Échec de l'appel API : ${t.message}")
|
||||
}
|
||||
})
|
||||
}
|
||||
fun createProject(name: String, description: String, onSuccess: () -> Unit, onError: (String) -> Unit) {
|
||||
val call = apiService.createProject(Project(0, name, description, Date(), 0, null))
|
||||
call.enqueue(object : Callback<Confirmation> {
|
||||
override fun onResponse(call: Call<Confirmation>, response: Response<Confirmation>) {
|
||||
if (response.isSuccessful) {
|
||||
onSuccess()
|
||||
} else {
|
||||
onError("Erreur : ${response.code()}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<Confirmation>, t: Throwable) {
|
||||
onError("Échec de l'appel API : ${t.message}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
12
app/src/main/java/com/dreamteam/timelapse/data/Video.kt
Normal file
12
app/src/main/java/com/dreamteam/timelapse/data/Video.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.dreamteam.timelapse.data
|
||||
|
||||
data class Video (
|
||||
val id: Int,
|
||||
val project_id: Int,
|
||||
val measurement_ids: List<Int>,
|
||||
val video_file: String?,
|
||||
val resolution:String,
|
||||
val duration: Int,
|
||||
val status: Int, //0 pas fini, 1 fini
|
||||
val name: String
|
||||
){}
|
||||
@@ -4,7 +4,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".MainActivity">
|
||||
tools:context=".MainActivity"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -23,14 +24,14 @@
|
||||
|
||||
<!-- useless now <include layout="@layout/content_main" />-->
|
||||
|
||||
<!-- <com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="@dimen/fab_margin"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:srcCompat="@android:drawable/ic_dialog_email" /> -->
|
||||
app:srcCompat="@android:drawable/ic_input_add" />
|
||||
|
||||
|
||||
<!-- marge pour le appBar layout -->
|
||||
|
||||
7
app/src/main/res/layout/item_image.xml
Normal file
7
app/src/main/res/layout/item_image.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"/>
|
||||
@@ -31,90 +31,125 @@
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<com.dreamteam.timelapse.CustomSwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/appBarLayout"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
||||
tools:context=".ProjectActivity">
|
||||
|
||||
<!-- Description du projet -->
|
||||
<TextView
|
||||
android:id="@+id/project_description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Description du projet"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_name" />
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ProjectActivity">
|
||||
|
||||
<!-- Date de début du projet -->
|
||||
<TextView
|
||||
android:id="@+id/project_start_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Date de début"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_description" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toEndOf="@+id/appBarLayout"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
||||
tools:context=".ProjectActivity">
|
||||
|
||||
<!-- Statut du projet -->
|
||||
<TextView
|
||||
android:id="@+id/project_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Statut: En cours"
|
||||
android:textColor="@android:color/holo_green_dark"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_start_date" />
|
||||
|
||||
<!-- Liste des vidéos liées au projet -->
|
||||
<TextView
|
||||
android:id="@+id/video_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Vidéos associées"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_status" />
|
||||
<TextView
|
||||
android:id="@+id/project_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Description du projet"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/videos_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/video_header" />
|
||||
<TextView
|
||||
android:id="@+id/project_start_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Date de début"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_description" />
|
||||
|
||||
<!-- Graphique de température et d'hygrométrie -->
|
||||
<TextView
|
||||
android:id="@+id/graph_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Graphique de Température et d'Hygrométrie"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/videos_list" />
|
||||
<TextView
|
||||
android:id="@+id/project_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Statut: En cours"
|
||||
android:textColor="@android:color/holo_green_dark"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_start_date" />
|
||||
<TextView
|
||||
android:id="@+id/graph_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Graphique de Température et d'Hygrométrie"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/project_status" />
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/temperature_humidity_chart"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="250dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/graph_header" />
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/temperature_humidity_chart"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="250dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/graph_header" />
|
||||
<TextView
|
||||
android:id="@+id/image_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Images"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/temperature_humidity_chart" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/imagesList"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_percent="0.30"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_header" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/video_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Vidéos associées"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/imagesList" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/videos_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_percent="0.30"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/video_header" />
|
||||
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</com.dreamteam.timelapse.CustomSwipeRefreshLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
31
app/src/main/res/layout/project_create_dialog_layout.xml
Normal file
31
app/src/main/res/layout/project_create_dialog_layout.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="37dp"
|
||||
android:textSize="25dp"
|
||||
android:text="Creation d'un projet" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/project_name_dialog"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Nom du projet"
|
||||
android:inputType="text" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/project_desc_dialog"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Description du projet"
|
||||
android:inputType="text"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user