Revolution #1
3 changed files with 346 additions and 1 deletions
88
lib/models/table_column_definition.dart
Normal file
88
lib/models/table_column_definition.dart
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
abstract class TableColumnDefinition {
|
||||
final String columnName;
|
||||
final bool isUnique;
|
||||
|
||||
TableColumnDefinition({
|
||||
required this.columnName,
|
||||
required this.isUnique,
|
||||
});
|
||||
|
||||
String get def => throw UnimplementedError("def getter not implemented");
|
||||
}
|
||||
|
||||
class SerialPrimaryColumnDefinition extends TableColumnDefinition {
|
||||
SerialPrimaryColumnDefinition({
|
||||
required super.columnName,
|
||||
}) : super(isUnique: true);
|
||||
|
||||
@override
|
||||
String get def => "$columnName:serial:primary";
|
||||
}
|
||||
|
||||
class TextColumnDefinition extends TableColumnDefinition {
|
||||
TextColumnDefinition({
|
||||
required super.columnName,
|
||||
required super.isUnique,
|
||||
});
|
||||
|
||||
@override
|
||||
String get def => "$columnName:str${isUnique ? ":unique" : ""}";
|
||||
}
|
||||
|
||||
class BooleanColumnDefinition extends TableColumnDefinition {
|
||||
BooleanColumnDefinition({
|
||||
required super.columnName,
|
||||
required super.isUnique,
|
||||
});
|
||||
|
||||
@override
|
||||
String get def => "$columnName:bool${isUnique ? ":unique" : ""}";
|
||||
}
|
||||
|
||||
class TimestampColumnDefinition extends TableColumnDefinition {
|
||||
TimestampColumnDefinition({
|
||||
required super.columnName,
|
||||
required super.isUnique,
|
||||
});
|
||||
|
||||
@override
|
||||
String get def => "$columnName:datetime${isUnique ? ":unique" : ""}";
|
||||
}
|
||||
|
||||
class DoubleColumnDefinition extends TableColumnDefinition {
|
||||
DoubleColumnDefinition({
|
||||
required super.columnName,
|
||||
required super.isUnique,
|
||||
});
|
||||
|
||||
@override
|
||||
String get def => "$columnName:float${isUnique ? ":unique" : ""}";
|
||||
}
|
||||
|
||||
class IntegerColumnDefinition extends TableColumnDefinition {
|
||||
IntegerColumnDefinition({
|
||||
required super.columnName,
|
||||
required super.isUnique,
|
||||
});
|
||||
|
||||
@override
|
||||
String get def => "$columnName:int${isUnique ? ":unique" : ""}";
|
||||
}
|
||||
|
||||
class UserRefColumnDefinition extends TableColumnDefinition {
|
||||
UserRefColumnDefinition({
|
||||
required super.columnName,
|
||||
}) : super(isUnique: false);
|
||||
|
||||
@override
|
||||
String get def => "$columnName:int-user";
|
||||
}
|
||||
|
||||
class AssetRefColumnDefinition extends TableColumnDefinition {
|
||||
AssetRefColumnDefinition({
|
||||
required super.columnName,
|
||||
}) : super(isUnique: false);
|
||||
|
||||
@override
|
||||
String get def => "$columnName:int-asset";
|
||||
}
|
||||
251
lib/pages/dialogs/create_table_dialog.dart
Normal file
251
lib/pages/dialogs/create_table_dialog.dart
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
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: "Text",
|
||||
BooleanColumnDefinition: "Boolean",
|
||||
TimestampColumnDefinition: "Date/Time",
|
||||
DoubleColumnDefinition: "Double",
|
||||
IntegerColumnDefinition: "Integer",
|
||||
UserRefColumnDefinition: "User reference",
|
||||
AssetRefColumnDefinition: "Asset reference",
|
||||
};
|
||||
|
||||
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("No data in response");
|
||||
}
|
||||
|
||||
Get.back(result: true);
|
||||
} on DioError catch (e) {
|
||||
final respData = e.response?.data;
|
||||
if (respData != null) {
|
||||
Get.snackbar(
|
||||
"Error trying to update tables access",
|
||||
"${respData['error']}",
|
||||
);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
"Error trying to update tables access",
|
||||
"$e",
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
"Error trying to update tables access",
|
||||
"$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("Create new column"),
|
||||
content: Wrap(
|
||||
runSpacing: 16,
|
||||
children: [
|
||||
FastTextField(
|
||||
name: "ColumnName",
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Column name",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
initialValue: columnName.value,
|
||||
onChanged: (value) => columnName.value = value ?? "",
|
||||
),
|
||||
FastDropdown(
|
||||
name: "ColumnTypes",
|
||||
hint: const Text("Select column type"),
|
||||
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: "Is Unique",
|
||||
initialValue: false,
|
||||
onChanged: (value) => columnIsUnique.value = value!,
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back(result: false);
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back(result: true);
|
||||
},
|
||||
child: const Text('Create'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirm != true) return;
|
||||
|
||||
TableColumnDefinition? ct;
|
||||
switch (columnType.value) {
|
||||
case "Serial ID":
|
||||
ct = SerialPrimaryColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
);
|
||||
break;
|
||||
case "Text":
|
||||
ct = TextColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
isUnique: columnIsUnique.value,
|
||||
);
|
||||
break;
|
||||
case "Boolean":
|
||||
ct = BooleanColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
isUnique: columnIsUnique.value,
|
||||
);
|
||||
break;
|
||||
case "Date/Time":
|
||||
ct = TimestampColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
isUnique: columnIsUnique.value,
|
||||
);
|
||||
break;
|
||||
case "Double":
|
||||
ct = DoubleColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
isUnique: columnIsUnique.value,
|
||||
);
|
||||
break;
|
||||
case "Integer":
|
||||
ct = IntegerColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
isUnique: columnIsUnique.value,
|
||||
);
|
||||
break;
|
||||
case "User reference":
|
||||
ct = UserRefColumnDefinition(
|
||||
columnName: columnName.value,
|
||||
);
|
||||
break;
|
||||
case "Asset reference":
|
||||
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('Creating new table'),
|
||||
content: Column(
|
||||
children: [
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Table name",
|
||||
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("Create column"),
|
||||
).expanded()
|
||||
].toRow(),
|
||||
],
|
||||
).constrained(width: Get.width * 0.9, height: Get.height * 0.9),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
Obx(
|
||||
() => TextButton(
|
||||
onPressed: controller.columnsDefinition.isEmpty
|
||||
? null
|
||||
: () => controller.createTable(),
|
||||
child: const Text('Create'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static Future<bool?> show() async {
|
||||
Get.lazyPut<CreateTableController>(() => CreateTableController());
|
||||
|
||||
return Get.dialog<bool>(
|
||||
const CreateTableDialog(),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import 'package:tuuli_api/tuuli_api.dart';
|
|||
import 'package:tuuli_app/api_controller.dart';
|
||||
import 'package:recase/recase.dart';
|
||||
import 'package:tuuli_app/models/db_column_definition.dart';
|
||||
import 'package:tuuli_app/pages/dialogs/create_table_dialog.dart';
|
||||
|
||||
class TablesListPanelController extends GetxController {
|
||||
@override
|
||||
|
|
@ -54,7 +55,12 @@ class TablesListPanelController extends GetxController {
|
|||
_isLoading.value = false;
|
||||
}
|
||||
|
||||
Future<void> createNewTable() async {}
|
||||
Future<void> createNewTable() async {
|
||||
final created = await CreateTableDialog.show();
|
||||
if (created == true) {
|
||||
refreshData();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> openTable(TableDefinition table) async {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue