many things done
This commit is contained in:
3
.idea/deploymentTargetSelector.xml
generated
3
.idea/deploymentTargetSelector.xml
generated
@@ -13,6 +13,9 @@
|
|||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
<DialogSelection />
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
|
<SelectionState runConfigName="ProjectActivity">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.dreamteam.timelapse
|
package com.dreamteam.timelapse
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@@ -7,6 +8,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|||||||
|
|
||||||
class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRefreshLayout(context, attrs) {
|
class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRefreshLayout(context, attrs) {
|
||||||
init {
|
init {
|
||||||
|
this.setEnabled(true)
|
||||||
|
this.setRefreshing(true)
|
||||||
Log.d("CustomSwipeRefreshLayout", "CustomSwipeRefreshLayout instancié")
|
Log.d("CustomSwipeRefreshLayout", "CustomSwipeRefreshLayout instancié")
|
||||||
}
|
}
|
||||||
override fun canChildScrollUp(): Boolean {
|
override fun canChildScrollUp(): Boolean {
|
||||||
@@ -15,4 +18,22 @@ class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRef
|
|||||||
//Log.i("CustomSwipeRefreshLayout", "canChildScrollUp: ${view?.canScrollVertically(-1)}")
|
//Log.i("CustomSwipeRefreshLayout", "canChildScrollUp: ${view?.canScrollVertically(-1)}")
|
||||||
return view != null && 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
|
package com.dreamteam.timelapse
|
||||||
|
|
||||||
import android.R
|
import android.content.DialogInterface
|
||||||
import com.dreamteam.timelapse.R as Rtmp
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.navigation.findNavController
|
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
import androidx.navigation.ui.AppBarConfiguration
|
||||||
import androidx.navigation.ui.navigateUp
|
|
||||||
import androidx.navigation.ui.setupActionBarWithNavController
|
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.dreamteam.timelapse.databinding.ActivityMainBinding
|
import com.dreamteam.timelapse.databinding.ActivityMainBinding
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
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() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
|
private lateinit var dialog: AlertDialog
|
||||||
|
private lateinit var projectRepository : ProjectRepository
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
// super.onCreate(savedInstanceState)
|
// 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")
|
Log.d("mainActivity", "La main activity est créée")
|
||||||
|
|
||||||
|
|
||||||
// setSupportActionBar(binding.toolbar)
|
|
||||||
//
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
//val navController = findNavController(R.id.nav_host_fragment_content_main)
|
//val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||||
//appBarConfiguration = AppBarConfiguration(navController.graph)
|
//appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||||
@@ -46,13 +56,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setContentView(Rtmp.layout.activity_main)
|
setContentView(Rtmp.layout.activity_main)
|
||||||
val tabLayout = findViewById<View>(Rtmp.id.tabLayout) as TabLayout
|
val tabLayout = findViewById<View>(Rtmp.id.tabLayout) as TabLayout
|
||||||
val viewPager = findViewById<View>(Rtmp.id.viewPager) as ViewPager2
|
val viewPager = findViewById<View>(Rtmp.id.viewPager) as ViewPager2
|
||||||
|
createDialog(findViewById<View>(Rtmp.id.fab))
|
||||||
|
|
||||||
|
|
||||||
// Configurer l'adapter pour ViewPager2
|
// Configurer l'adapter pour ViewPager2
|
||||||
var tabsAdapter = TabsAdapter(this)
|
var tabsAdapter = TabsAdapter(this)
|
||||||
viewPager.setAdapter(tabsAdapter)
|
viewPager.setAdapter(tabsAdapter)
|
||||||
|
|
||||||
|
|
||||||
// Connecter le ViewPager au TabLayout
|
// Connecter le ViewPager au TabLayout
|
||||||
TabLayoutMediator(
|
TabLayoutMediator(
|
||||||
tabLayout, viewPager
|
tabLayout, viewPager
|
||||||
@@ -63,12 +73,39 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}.attach()
|
}.attach()
|
||||||
|
|
||||||
// Bouton flottant
|
//Bouton flottant
|
||||||
// binding.fab.setOnClickListener { view ->
|
findViewById<View>(Rtmp.id.fab).setOnClickListener { view -> run {
|
||||||
// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
this.dialog.show()
|
||||||
// //.setAction("Action", null) //sert à rien
|
}
|
||||||
// .setAnchorView(R.id.fab).show() //au dessus du bouton mail
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
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 {
|
// override fun onSupportNavigateUp(): Boolean {
|
||||||
|
|||||||
@@ -1,61 +1,74 @@
|
|||||||
package com.dreamteam.timelapse
|
package com.dreamteam.timelapse
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.graphics.Rect
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
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.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.Entry
|
||||||
import com.github.mikephil.charting.data.LineData
|
import com.github.mikephil.charting.data.LineData
|
||||||
import com.github.mikephil.charting.data.LineDataSet
|
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() {
|
class ProjectActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ProjectBinding
|
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?) {
|
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é
|
val retrofit = Retrofit.Builder()
|
||||||
Log.d("project", "La project activity "+project?.id+" est créée")
|
.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)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ProjectBinding.inflate(layoutInflater)
|
this.binding = ProjectBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
// Initialisation du graphique
|
|
||||||
val temperatureHumidityChart = binding.temperatureHumidityChart
|
|
||||||
|
|
||||||
// Données fictives (température et humidité)
|
initProjectInfo()
|
||||||
val temperatureEntries = mutableListOf<Entry>()
|
|
||||||
val humidityEntries = mutableListOf<Entry>()
|
|
||||||
|
|
||||||
// Ajouter des points de données (exemples)
|
fetchMeasuresAndRebuildGraph()
|
||||||
temperatureEntries.add(Entry(0f, 25f)) // (temps, température)
|
val swipeRefreshLayout = binding.swipeRefreshLayout
|
||||||
humidityEntries.add(Entry(0f, 60f)) // (temps, humidité)
|
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
|
// .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.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
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>() {
|
class ProjectAdapter(private val projects: List<Project>, private val listener: OnEmptyStateListener) : RecyclerView.Adapter<ProjectAdapter.ProjectViewHolder>() {
|
||||||
|
init{
|
||||||
|
listener.onEmptyStateChanged(projects.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
interface OnEmptyStateListener {
|
interface OnEmptyStateListener {
|
||||||
fun onEmptyStateChanged(isEmpty: Boolean)
|
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)
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_project_card, parent, false)
|
||||||
|
|
||||||
//projects.isEmpty()
|
//projects.isEmpty()
|
||||||
listener.onEmptyStateChanged(projects.isEmpty())
|
|
||||||
|
|
||||||
return ProjectViewHolder(view)
|
return ProjectViewHolder(view)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,17 @@ package com.dreamteam.timelapse
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.util.TypedValue
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ListView
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.dreamteam.timelapse.data.ProjectRepository
|
import com.dreamteam.timelapse.data.ProjectRepository
|
||||||
import com.dreamteam.timelapse.databinding.FragmentProjetsBinding
|
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.ApiService
|
||||||
|
import com.dreamteam.timelapse.data.Project
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
@@ -50,11 +47,11 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
|||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
Log.d("ProjetsFrag", "Fragment Projets créé")
|
|
||||||
_binding = FragmentProjetsBinding.inflate(inflater, container, false)
|
_binding = FragmentProjetsBinding.inflate(inflater, container, false)
|
||||||
|
Log.d("ProjetsFrag", "Fragment Projets créé")
|
||||||
|
|
||||||
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
|
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
|
||||||
fetchProjects()
|
//fetchProjects()
|
||||||
|
|
||||||
return _binding?.root
|
return _binding?.root
|
||||||
}
|
}
|
||||||
@@ -68,6 +65,7 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
|||||||
fetchProjects()
|
fetchProjects()
|
||||||
Log.d("ProjetsFrag", "Actualisation des projets")
|
Log.d("ProjetsFrag", "Actualisation des projets")
|
||||||
}
|
}
|
||||||
|
fetchProjects()
|
||||||
|
|
||||||
recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView)
|
recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView)
|
||||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||||
@@ -77,8 +75,11 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
|||||||
|
|
||||||
private fun fetchProjects() {
|
private fun fetchProjects() {
|
||||||
// Simulez l'appel API
|
// 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")
|
Log.d("ProjetsFrag", "User has refreshed the projects list")
|
||||||
projectRepository.fetchProjects(
|
projectRepository.fetchProjects(
|
||||||
onSuccess = { projects ->
|
onSuccess = { projects ->
|
||||||
@@ -89,7 +90,12 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
|
|||||||
// Mettre à jour le RecyclerView ou autre traitement
|
// Mettre à jour le RecyclerView ou autre traitement
|
||||||
},
|
},
|
||||||
onError = { errorMessage ->
|
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
|
binding.swipeRefreshLayout.isRefreshing = false
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ class TabsAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
|
|||||||
else -> ProjetsFrag() // Par défaut
|
else -> ProjetsFrag() // Par défaut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,44 +1,112 @@
|
|||||||
package com.dreamteam.timelapse
|
package com.dreamteam.timelapse
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.util.TypedValue
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.dreamteam.timelapse.databinding.FragmentVideosBinding
|
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
|
private lateinit var projectRepository: ProjectRepository
|
||||||
// onDestroyView.
|
//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 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(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View? {
|
||||||
|
_binding = FragmentProjetsBinding.inflate(inflater, container, false)
|
||||||
|
Log.d("ProjetsFrag", "Fragment Projets créé")
|
||||||
|
|
||||||
_binding = FragmentVideosBinding.inflate(inflater, container, false)
|
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
|
||||||
return binding.root
|
//fetchProjects()
|
||||||
|
|
||||||
|
return _binding?.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
binding.buttonSecond.setOnClickListener {
|
val swipeRefreshLayout = binding.swipeRefreshLayout
|
||||||
findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
|
|
||||||
|
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
|
package com.dreamteam.timelapse.data
|
||||||
import com.dreamteam.timelapse.Project
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.Field
|
||||||
|
import retrofit2.http.FormUrlEncoded
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
|
|
||||||
interface ApiService {
|
interface ApiService {
|
||||||
@GET("projects") // Remplace par l'endpoint de ton API
|
@GET("projects")
|
||||||
fun getProjets(): Call<List<Project>>
|
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>
|
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
|
package com.dreamteam.timelapse.data
|
||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import java.util.Date
|
import android.util.Log
|
||||||
|
import com.dreamteam.timelapse.R
|
||||||
//{
|
import java.util.Date
|
||||||
// "id": 1,
|
|
||||||
// "creation": "2024-10-24T13:46:04.513Z",
|
//{
|
||||||
// "status": "test",
|
// "id": 1,
|
||||||
// "description": "Projet de Test",
|
// "creation": "2024-10-24T13:46:04.513Z",
|
||||||
// "titre": "Test Project"
|
// "status": "test",
|
||||||
//}
|
// "description": "Projet de Test",
|
||||||
data class Project(
|
// "titre": "Test Project"
|
||||||
val id: Int,
|
//}
|
||||||
val name: String,
|
data class Project(
|
||||||
val description: String,
|
val id: Int,
|
||||||
val start_date: Date,
|
val name: String,
|
||||||
val status: Int,
|
val description: String,
|
||||||
val thumbnail_url: String?
|
val start_date: Date,
|
||||||
) : Parcelable {
|
val status: Int,
|
||||||
|
val thumbnail_url: String?
|
||||||
fun getStatusText(): String{
|
) : Parcelable {
|
||||||
val statusArr = arrayOf("Brouillon", "En Cours", "Terminé", "Annulé")
|
|
||||||
return statusArr[status]
|
fun getStatusText(): String{
|
||||||
}
|
Log.i("Project", "Status $status being trasnlated")
|
||||||
fun getStatusColor(): Int{
|
val statusArr = arrayOf("Brouillon", "En Cours", "Terminé", "Annulé")
|
||||||
return when (status) {
|
return statusArr[status]
|
||||||
0 -> R.color.brouillon
|
}
|
||||||
1 -> R.color.en_cours
|
fun getStatusColor(): Int{
|
||||||
2 -> R.color.termine
|
return when (status) {
|
||||||
3 -> R.color.annule
|
0 -> R.color.brouillon
|
||||||
else -> R.color.default_badge
|
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() ?: "",
|
// Constructor to recreate from Parcel
|
||||||
parcel.readString() ?: "",
|
constructor(parcel: Parcel) : this(
|
||||||
Date(parcel.readLong()),
|
parcel.readInt(),
|
||||||
parcel.readInt(),
|
parcel.readString() ?: "",
|
||||||
parcel.readString()
|
parcel.readString() ?: "",
|
||||||
)
|
Date(parcel.readLong()),
|
||||||
|
parcel.readInt(),
|
||||||
// Write object to Parcel
|
parcel.readString()
|
||||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
)
|
||||||
parcel.writeInt(id)
|
|
||||||
parcel.writeString(name)
|
// Write object to Parcel
|
||||||
parcel.writeString(description)
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
parcel.writeString(start_date.toString())
|
parcel.writeInt(id)
|
||||||
parcel.writeInt(status)
|
parcel.writeString(name)
|
||||||
}
|
parcel.writeString(description)
|
||||||
|
parcel.writeLong(start_date.time)
|
||||||
// Describe the contents of the Parcel
|
parcel.writeInt(status)
|
||||||
override fun describeContents(): Int = 0
|
}
|
||||||
|
|
||||||
companion object CREATOR : Parcelable.Creator<Project> {
|
// Describe the contents of the Parcel
|
||||||
override fun createFromParcel(parcel: Parcel): Project {
|
override fun describeContents(): Int = 0
|
||||||
return Project(parcel)
|
|
||||||
}
|
companion object CREATOR : Parcelable.Creator<Project> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): Project {
|
||||||
override fun newArray(size: Int): Array<Project?> {
|
return Project(parcel)
|
||||||
return arrayOfNulls(size)
|
}
|
||||||
}
|
|
||||||
}
|
override fun newArray(size: Int): Array<Project?> {
|
||||||
// fun getThumbnail(): String {
|
return arrayOfNulls(size)
|
||||||
// return images[0]
|
}
|
||||||
// }
|
}
|
||||||
}
|
// fun getThumbnail(): String {
|
||||||
|
// return images[0]
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.dreamteam.timelapse.data
|
package com.dreamteam.timelapse.data
|
||||||
|
|
||||||
import com.dreamteam.timelapse.Project
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
class ProjectRepository(private val apiService: ApiService) {
|
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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -23,14 +24,14 @@
|
|||||||
|
|
||||||
<!-- useless now <include layout="@layout/content_main" />-->
|
<!-- useless now <include layout="@layout/content_main" />-->
|
||||||
|
|
||||||
<!-- <com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/fab"
|
android:id="@+id/fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:layout_marginEnd="@dimen/fab_margin"
|
android:layout_marginEnd="@dimen/fab_margin"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
app:srcCompat="@android:drawable/ic_dialog_email" /> -->
|
app:srcCompat="@android:drawable/ic_input_add" />
|
||||||
|
|
||||||
|
|
||||||
<!-- marge pour le appBar layout -->
|
<!-- 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>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<com.dreamteam.timelapse.CustomSwipeRefreshLayout
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
android:id="@+id/swipeRefreshLayout"
|
||||||
android:layout_width="match_parent"
|
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"
|
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
||||||
tools:context=".ProjectActivity">
|
tools:context=".ProjectActivity">
|
||||||
|
|
||||||
<!-- Description du projet -->
|
<androidx.core.widget.NestedScrollView
|
||||||
<TextView
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/project_description"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="0dp"
|
tools:context=".ProjectActivity">
|
||||||
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" />
|
|
||||||
|
|
||||||
<!-- Date de début du projet -->
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
<TextView
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/project_start_date"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
app:layout_constraintStart_toEndOf="@+id/appBarLayout"
|
||||||
android:layout_height="wrap_content"
|
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
||||||
android:layout_marginTop="8dp"
|
tools:context=".ProjectActivity">
|
||||||
android:text="Date de début"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/project_description" />
|
|
||||||
|
|
||||||
<!-- 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
|
||||||
<TextView
|
android:id="@+id/project_description"
|
||||||
android:id="@+id/video_header"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:text="Description du projet"
|
||||||
android:layout_marginTop="16dp"
|
android:visibility="gone"
|
||||||
android:text="Vidéos associées"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:textSize="18sp"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:textStyle="bold"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/project_status" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<TextView
|
||||||
android:id="@+id/videos_list"
|
android:id="@+id/project_start_date"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:layout_marginTop="8dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:text="Date de début"
|
||||||
app:layout_constraintTop_toBottomOf="@id/video_header" />
|
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
|
||||||
<TextView
|
android:id="@+id/project_status"
|
||||||
android:id="@+id/graph_header"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginTop="16dp"
|
android:text="Statut: En cours"
|
||||||
android:text="Graphique de Température et d'Hygrométrie"
|
android:textColor="@android:color/holo_green_dark"
|
||||||
android:textSize="18sp"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:textStyle="bold"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintTop_toBottomOf="@id/project_start_date" />
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
<TextView
|
||||||
app:layout_constraintTop_toBottomOf="@id/videos_list" />
|
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
|
<TextView
|
||||||
android:id="@+id/temperature_humidity_chart"
|
android:id="@+id/image_header"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="250dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:text="Images"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:textSize="18sp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/graph_header" />
|
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>
|
</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