tuuli_app/lib/pages/dialogs/create_table_dialog.dart

251 lines
7.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_fast_forms/flutter_fast_forms.dart';
import 'package:get/get.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:tuuli_app/api_controller.dart';
import 'package:tuuli_app/models/table_column_definition.dart';
const typeToNameMatcher = {
SerialPrimaryColumnDefinition: "Serial ID",
TextColumnDefinition: "Текст",
BooleanColumnDefinition: "Логическое значение",
TimestampColumnDefinition: "Дата/Время",
DoubleColumnDefinition: "Число с плавающей точкой",
IntegerColumnDefinition: "Целое число",
UserRefColumnDefinition: "Ссылка на пользователя",
AssetRefColumnDefinition: "Ссылка на ресурс",
};
class CreateTableController extends GetxController {
final _tableName = "".obs;
String get tableName => _tableName.value;
set tableName(String value) => _tableName.value = value;
final _columnsDefinition = <TableColumnDefinition>[].obs;
List<TableColumnDefinition> get columnsDefinition => _columnsDefinition;
Future<void> createTable() async {
try {
final resp = await ApiController.to.apiClient.createTable(
tableName: tableName,
columnsDefinition:
_columnsDefinition.map((e) => e.def).toList(growable: false),
);
final respData = resp.data;
if (respData == null) {
throw Exception("В ответе нет данных");
}
Get.back(result: true);
} on DioError catch (e) {
final respData = e.response?.data;
if (respData != null) {
Get.snackbar(
"Ошибка обновления доступа к таблице",
"${respData['error']}",
);
} else {
Get.snackbar(
"Ошибка обновления доступа к таблице",
"$e",
);
}
} catch (e) {
Get.snackbar(
"Ошибка обновления доступа к таблице",
"$e",
);
}
}
Future<void> createNewColumn() async {
final columnName = "".obs;
final columnType = "".obs;
final columnIsUnique = false.obs;
final confirm = await Get.dialog<bool>(
AlertDialog(
title: const Text("Создать новую колонку"),
content: Wrap(
runSpacing: 16,
children: [
FastTextField(
name: "ColumnName",
decoration: const InputDecoration(
labelText: "Название",
border: OutlineInputBorder(),
),
initialValue: columnName.value,
onChanged: (value) => columnName.value = value ?? "",
),
FastDropdown(
name: "ColumnTypes",
hint: const Text("Тип"),
items: typeToNameMatcher.keys.toList(growable: false),
itemsBuilder: (items, field) => items
.map(
(e) => DropdownMenuItem(
value: e,
child: Text(typeToNameMatcher[e]!),
),
)
.toList(),
onChanged: (value) =>
columnType.value = typeToNameMatcher[value] ?? "",
),
FastCheckbox(
name: "ColumnIsUnique",
titleText: "Уникальное значение?",
initialValue: false,
onChanged: (value) => columnIsUnique.value = value!,
),
],
),
actions: [
TextButton(
onPressed: () {
Get.back(result: false);
},
child: const Text("Отменить"),
),
TextButton(
onPressed: () {
Get.back(result: true);
},
child: const Text("Создать"),
),
],
),
);
if (confirm != true) return;
TableColumnDefinition? ct;
switch (columnType.value) {
case "Serial ID":
ct = SerialPrimaryColumnDefinition(
columnName: columnName.value,
);
break;
case "Текст":
ct = TextColumnDefinition(
columnName: columnName.value,
isUnique: columnIsUnique.value,
);
break;
case "Логическое значение":
ct = BooleanColumnDefinition(
columnName: columnName.value,
isUnique: columnIsUnique.value,
);
break;
case "Дата/Время":
ct = TimestampColumnDefinition(
columnName: columnName.value,
isUnique: columnIsUnique.value,
);
break;
case "Число с плавающей точкой":
ct = DoubleColumnDefinition(
columnName: columnName.value,
isUnique: columnIsUnique.value,
);
break;
case "Целое число":
ct = IntegerColumnDefinition(
columnName: columnName.value,
isUnique: columnIsUnique.value,
);
break;
case "Ссылка на пользователя":
ct = UserRefColumnDefinition(
columnName: columnName.value,
);
break;
case "Ссылка на ресурс":
ct = AssetRefColumnDefinition(
columnName: columnName.value,
);
break;
}
if (ct == null) return;
_columnsDefinition.add(ct);
}
void removeColumn(TableColumnDefinition e) {
_columnsDefinition.remove(e);
}
}
class CreateTableDialog extends GetView<CreateTableController> {
const CreateTableDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text("Создать новую таблицу"),
content: Column(
children: [
TextField(
decoration: const InputDecoration(
labelText: "Название",
border: OutlineInputBorder(),
),
onChanged: (value) => controller.tableName = value,
),
const Divider(),
Obx(
() => ListView(
children: controller.columnsDefinition
.map(
(e) => ListTile(
title: Text(e.columnName),
subtitle: Text(e.def),
trailing: IconButton(
onPressed: () => controller.removeColumn(e),
icon: const Icon(Icons.delete),
),
),
)
.toList(),
).expanded(),
),
const Divider(),
[
ElevatedButton(
onPressed: () => controller.createNewColumn(),
child: const Text("Создать колонку"),
).expanded()
].toRow(),
],
).constrained(width: Get.width * 0.9, height: Get.height * 0.9),
actions: [
TextButton(
onPressed: () {
Get.back();
},
child: const Text("Закрыть"),
),
Obx(
() => TextButton(
onPressed: controller.columnsDefinition.isEmpty
? null
: () => controller.createTable(),
child: const Text("Создать"),
),
),
],
);
}
static Future<bool?> show() async {
Get.lazyPut<CreateTableController>(() => CreateTableController());
return Get.dialog<bool>(
const CreateTableDialog(),
barrierDismissible: false,
);
}
}