Added Enter and projet/glossary name verification (unauthorized characters)
parent
b42780ac92
commit
ab24995360
|
@ -13,8 +13,10 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.input.key.*
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.*
|
import androidx.compose.ui.window.*
|
||||||
|
@ -34,7 +36,7 @@ object AppState {
|
||||||
var selectedProject: Project? = null
|
var selectedProject: Project? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun app() {
|
fun app() {
|
||||||
|
@ -53,10 +55,7 @@ fun app() {
|
||||||
val isEmptySnackbarVisibleState = remember { mutableStateOf(false) }
|
val isEmptySnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
val containsSpaceSnackbarVisibleState = remember { mutableStateOf(false) }
|
val containsSpaceSnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
val glossaryAlreadyExistsSnackbarVisibleState = remember { mutableStateOf(false) }
|
val glossaryAlreadyExistsSnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
|
val invalidCharacterSnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when (currentPage.value) {
|
when (currentPage.value) {
|
||||||
|
@ -191,10 +190,41 @@ fun app() {
|
||||||
TextField(
|
TextField(
|
||||||
value = nouveauGlossaireName,
|
value = nouveauGlossaireName,
|
||||||
onValueChange = { nouveauGlossaireName = it },
|
onValueChange = { nouveauGlossaireName = it },
|
||||||
|
singleLine = true,
|
||||||
label = { Text("Nom du nouveau glossaire") },
|
label = { Text("Nom du nouveau glossaire") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth()
|
||||||
|
.onKeyEvent { event ->
|
||||||
|
if (event.key == Key.Enter && event.type == KeyEventType.KeyDown) {
|
||||||
|
// Handle the Enter key event by calling the common function
|
||||||
|
if (nouveauGlossaireName.isEmpty()) {
|
||||||
|
println("Veuillez saisir un nom pour le nouveau glossaire")
|
||||||
|
isEmptySnackbarVisibleState.value = true
|
||||||
|
} else if (nouveauGlossaireName.contains(" ")) {
|
||||||
|
println("Le nom du glossaire ne doit pas contenir d'espace")
|
||||||
|
containsSpaceSnackbarVisibleState.value = true
|
||||||
|
} else if (glossaries.any { it.name == nouveauGlossaireName }) {
|
||||||
|
println("Le nom du glossaire existe déjà")
|
||||||
|
glossaryAlreadyExistsSnackbarVisibleState.value = true
|
||||||
|
} else if (!isValidFileName(nouveauGlossaireName)) {
|
||||||
|
println("Le nom du glossaire contient des caractères non autorisés")
|
||||||
|
invalidCharacterSnackbarVisibleState.value = true
|
||||||
|
} else {
|
||||||
|
val newGlossary = Glossary(nouveauGlossaireName, "$nouveauGlossaireName.json")
|
||||||
|
glossaries = glossaries + newGlossary
|
||||||
|
// create new json file
|
||||||
|
val newFile = File(glossaryPath + (appState.selectedProject?.name) + "/" + newGlossary.jsonFilePath)
|
||||||
|
newFile.createNewFile()
|
||||||
|
// update glossaries list
|
||||||
|
glossaries = loadGlossaries(appState.selectedProject!!)
|
||||||
|
currentPage.value = "glossaires" // Revenir à la liste des glossaires
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
backgroundColor = Color.White,
|
backgroundColor = Color.White,
|
||||||
focusedIndicatorColor = customRedColor,
|
focusedIndicatorColor = customRedColor,
|
||||||
|
@ -204,34 +234,30 @@ fun app() {
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
// Ajouter le code pour créer un nouveau glossaire avec le nom saisi
|
// Handle the Enter key event by calling the common function
|
||||||
//first check if the name is not empty, if there is space or if the name already exists
|
|
||||||
if (nouveauGlossaireName.isEmpty()) {
|
if (nouveauGlossaireName.isEmpty()) {
|
||||||
println("Veuillez saisir un nom pour le nouveau glossaire")
|
println("Veuillez saisir un nom pour le nouveau glossaire")
|
||||||
isEmptySnackbarVisibleState.value = true
|
isEmptySnackbarVisibleState.value = true
|
||||||
return@Button
|
} else if (nouveauGlossaireName.contains(" ")) {
|
||||||
}
|
|
||||||
if (nouveauGlossaireName.contains(" ")) {
|
|
||||||
println("Le nom du glossaire ne doit pas contenir d'espace")
|
println("Le nom du glossaire ne doit pas contenir d'espace")
|
||||||
containsSpaceSnackbarVisibleState.value = true
|
containsSpaceSnackbarVisibleState.value = true
|
||||||
return@Button
|
} else if (glossaries.any { it.name == nouveauGlossaireName }) {
|
||||||
|
println("Le nom du glossaire existe déjà")
|
||||||
|
glossaryAlreadyExistsSnackbarVisibleState.value = true
|
||||||
|
} else if (!isValidFileName(nouveauGlossaireName)) {
|
||||||
|
println("Le nom du glossaire contient des caractères non autorisés")
|
||||||
|
invalidCharacterSnackbarVisibleState.value = true
|
||||||
|
} else {
|
||||||
|
val newGlossary = Glossary(nouveauGlossaireName, "$nouveauGlossaireName.json")
|
||||||
|
glossaries = glossaries + newGlossary
|
||||||
|
// create new json file
|
||||||
|
val newFile =
|
||||||
|
File(glossaryPath + (appState.selectedProject?.name) + "/" + newGlossary.jsonFilePath)
|
||||||
|
newFile.createNewFile()
|
||||||
|
// update glossaries list
|
||||||
|
glossaries = loadGlossaries(appState.selectedProject!!)
|
||||||
|
currentPage.value = "glossaires" // Revenir à la liste des glossaires
|
||||||
}
|
}
|
||||||
glossaries.forEach { glossary ->
|
|
||||||
nouveauGlossaireName = nouveauGlossaireName.lowercase(Locale.getDefault())
|
|
||||||
if (glossary.name == nouveauGlossaireName) {
|
|
||||||
println("Le nom du glossaire existe déjà")
|
|
||||||
glossaryAlreadyExistsSnackbarVisibleState.value = true
|
|
||||||
return@Button
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val newGlossary = Glossary(nouveauGlossaireName, "$nouveauGlossaireName.json")
|
|
||||||
glossaries = glossaries + newGlossary
|
|
||||||
//create new json file
|
|
||||||
val newFile = File(glossaryPath + (appState.selectedProject?.name ) + "/" + newGlossary.jsonFilePath)
|
|
||||||
newFile.createNewFile()
|
|
||||||
//update glossaries list
|
|
||||||
glossaries = loadGlossaries(appState.selectedProject!!)
|
|
||||||
currentPage.value = "glossaires" // Revenir à la liste des glossaires
|
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(200.dp),
|
.width(200.dp),
|
||||||
|
@ -425,10 +451,33 @@ fun app() {
|
||||||
Text("Ce glossaire existe déjà.")
|
Text("Ce glossaire existe déjà.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (invalidCharacterSnackbarVisibleState.value) {
|
||||||
|
Snackbar(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
action = {
|
||||||
|
Button(
|
||||||
|
onClick = { invalidCharacterSnackbarVisibleState.value = false },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = customRedColor,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Le nom du glossaire contient des caractères non autorisés (caractères spéciaux).")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isValidFileName(name: String): Boolean {
|
||||||
|
val regex = Regex("[^a-zA-Z0-9._-]")
|
||||||
|
return !regex.containsMatchIn(name)
|
||||||
|
}
|
||||||
|
|
||||||
fun loadGlossaries(project: Project): List<Glossary> {
|
fun loadGlossaries(project: Project): List<Glossary> {
|
||||||
val glossaries = mutableListOf<Glossary>()
|
val glossaries = mutableListOf<Glossary>()
|
||||||
//Récupérer tous les fichiers json à la racine du projet
|
//Récupérer tous les fichiers json à la racine du projet
|
||||||
|
|
|
@ -9,8 +9,10 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.input.key.*
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
@ -123,12 +125,18 @@ fun projectsPage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun newProject(
|
fun newProject(
|
||||||
currentPage: MutableState<String>
|
currentPage: MutableState<String>
|
||||||
){
|
){
|
||||||
var projectName by remember { mutableStateOf("") }
|
var projectName by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
val isEmptySnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
|
val containsSpaceSnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
|
val glossaryAlreadyExistsSnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
|
val invalidCharacterSnackbarVisibleState = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
|
@ -137,24 +145,65 @@ fun newProject(
|
||||||
Text("Nom du projet", style = MaterialTheme.typography.h5)
|
Text("Nom du projet", style = MaterialTheme.typography.h5)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
val projectsList = loadProjects()
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = projectName,
|
value = projectName,
|
||||||
|
singleLine = true,
|
||||||
onValueChange = { projectName = it },
|
onValueChange = { projectName = it },
|
||||||
label = { Text("Nom du projet") },
|
label = { Text("Nom du projet") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(300.dp)
|
.width(300.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
.onKeyEvent { event ->
|
||||||
|
if (event.key == Key.Enter && event.type == KeyEventType.KeyDown) {
|
||||||
|
if (projectName.isEmpty()) {
|
||||||
|
println("Veuillez saisir un nom pour le nouveau projet")
|
||||||
|
isEmptySnackbarVisibleState.value = true
|
||||||
|
} else if (projectName.contains(" ")) {
|
||||||
|
println("Le nom du projet ne doit pas contenir d'espace")
|
||||||
|
containsSpaceSnackbarVisibleState.value = true
|
||||||
|
} else if (projectsList.any { it.name == projectName }) {
|
||||||
|
println("Le nom du projet existe déjà")
|
||||||
|
glossaryAlreadyExistsSnackbarVisibleState.value = true
|
||||||
|
} else if (!isValidFileName(projectName)) {
|
||||||
|
println("Le nom du projet contient des caractères non autorisés")
|
||||||
|
invalidCharacterSnackbarVisibleState.value = true
|
||||||
|
} else {
|
||||||
|
val directory = File("src/main/resources/projects/$projectName/")
|
||||||
|
directory.mkdirs()
|
||||||
|
println("Project $projectName created")
|
||||||
|
currentPage.value = "projects"
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
val directory = File("src/main/resources/projects/$projectName/")
|
if (projectName.isEmpty()) {
|
||||||
directory.mkdirs()
|
println("Veuillez saisir un nom pour le nouveau projet")
|
||||||
println("Project $projectName created")
|
isEmptySnackbarVisibleState.value = true
|
||||||
currentPage.value = "projects"
|
} else if (projectName.contains(" ")) {
|
||||||
|
println("Le nom du projet ne doit pas contenir d'espace")
|
||||||
|
containsSpaceSnackbarVisibleState.value = true
|
||||||
|
} else if (projectsList.any { it.name == projectName }) {
|
||||||
|
println("Le nom du projet existe déjà")
|
||||||
|
glossaryAlreadyExistsSnackbarVisibleState.value = true
|
||||||
|
} else if (!isValidFileName(projectName)) {
|
||||||
|
println("Le nom du projet contient des caractères non autorisés")
|
||||||
|
invalidCharacterSnackbarVisibleState.value = true
|
||||||
|
} else {
|
||||||
|
val directory = File("src/main/resources/projects/$projectName/")
|
||||||
|
directory.mkdirs()
|
||||||
|
println("Project $projectName created")
|
||||||
|
currentPage.value = "projects"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(300.dp),
|
.width(300.dp),
|
||||||
|
@ -181,6 +230,79 @@ fun newProject(
|
||||||
) {
|
) {
|
||||||
Text("Retour")
|
Text("Retour")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isEmptySnackbarVisibleState.value) {
|
||||||
|
Snackbar(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
action = {
|
||||||
|
Button(
|
||||||
|
onClick = { isEmptySnackbarVisibleState.value = false },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = customRedColor,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Veuillez entrer un nom de glossaire.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (containsSpaceSnackbarVisibleState.value) {
|
||||||
|
Snackbar(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
action = {
|
||||||
|
Button(
|
||||||
|
onClick = { containsSpaceSnackbarVisibleState.value = false },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = customRedColor,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Veuillez ne pas mettre d'espace dans le nom du glossaire.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (glossaryAlreadyExistsSnackbarVisibleState.value) {
|
||||||
|
Snackbar(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
action = {
|
||||||
|
Button(
|
||||||
|
onClick = { glossaryAlreadyExistsSnackbarVisibleState.value = false },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = customRedColor,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Ce glossaire existe déjà.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (invalidCharacterSnackbarVisibleState.value) {
|
||||||
|
Snackbar(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
action = {
|
||||||
|
Button(
|
||||||
|
onClick = { invalidCharacterSnackbarVisibleState.value = false },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = customRedColor,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Le nom du glossaire contient des caractères non autorisés (caractères spéciaux).")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue