251 lines
7.6 KiB
Dart
251 lines
7.6 KiB
Dart
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,
|
||
);
|
||
}
|
||
}
|