Compare commits
19 commits
revolution
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 30f15dc40c | |||
| 159a88f006 | |||
| 1051ac57e0 | |||
| 10ac93eeb6 | |||
| 0a37ce249e | |||
| d9e0f9bdfd | |||
| 35712844c8 | |||
| 31190a78a7 | |||
| 89bd7cbfcb | |||
| 93b599137b | |||
| 1eccf30c10 | |||
| 374196699a | |||
| 8a3030addf | |||
| 7f7bbd9441 | |||
| badbf6c986 | |||
| 40bb982c74 | |||
| 53320d9d0f | |||
| 12ff1e953a | |||
| a01a66c88d |
21 changed files with 377 additions and 305 deletions
|
|
@ -1,3 +0,0 @@
|
||||||
extension TryCastExtension<T> on Object {
|
|
||||||
T? tryCast<T>() => this is T ? this as T : null;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class AppbarProviderInterface {
|
|
||||||
AppBar get appBar =>
|
|
||||||
throw UnimplementedError("appBar getter not implemented");
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
|
import 'package:flu_console/flu_console.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get_storage/get_storage.dart';
|
import 'package:get_storage/get_storage.dart';
|
||||||
import 'package:tuuli_app/api_controller.dart';
|
import 'package:tuuli_app/api_controller.dart';
|
||||||
import 'package:tuuli_app/pages/checkup_page.dart';
|
import 'package:tuuli_app/pages/checkup_page.dart';
|
||||||
import 'package:tuuli_app/pages/home_page.dart';
|
import 'package:tuuli_app/pages/home_page.dart';
|
||||||
import 'package:tuuli_app/pages/home_panels/tables_list_panel.dart';
|
|
||||||
import 'package:tuuli_app/pages/home_panels/users_list_panel.dart';
|
|
||||||
import 'package:tuuli_app/pages/login_page.dart';
|
import 'package:tuuli_app/pages/login_page.dart';
|
||||||
import 'package:tuuli_app/pages/not_found_page.dart';
|
import 'package:tuuli_app/pages/not_found_page.dart';
|
||||||
|
|
||||||
|
|
@ -26,7 +25,9 @@ void main() async {
|
||||||
fenix: true,
|
fenix: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
runApp(const MainApp());
|
FluConsole.run(() {
|
||||||
|
runApp(const MainApp());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainApp extends StatelessWidget {
|
class MainApp extends StatelessWidget {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class CheckupPage extends GetView<CheckupPageController> {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Checking credentials...',
|
'Проверяем ключ доступа...',
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ import 'package:tuuli_app/models/table_column_definition.dart';
|
||||||
|
|
||||||
const typeToNameMatcher = {
|
const typeToNameMatcher = {
|
||||||
SerialPrimaryColumnDefinition: "Serial ID",
|
SerialPrimaryColumnDefinition: "Serial ID",
|
||||||
TextColumnDefinition: "Text",
|
TextColumnDefinition: "Текст",
|
||||||
BooleanColumnDefinition: "Boolean",
|
BooleanColumnDefinition: "Логическое значение",
|
||||||
TimestampColumnDefinition: "Date/Time",
|
TimestampColumnDefinition: "Дата/Время",
|
||||||
DoubleColumnDefinition: "Double",
|
DoubleColumnDefinition: "Число с плавающей точкой",
|
||||||
IntegerColumnDefinition: "Integer",
|
IntegerColumnDefinition: "Целое число",
|
||||||
UserRefColumnDefinition: "User reference",
|
UserRefColumnDefinition: "Ссылка на пользователя",
|
||||||
AssetRefColumnDefinition: "Asset reference",
|
AssetRefColumnDefinition: "Ссылка на ресурс",
|
||||||
};
|
};
|
||||||
|
|
||||||
class CreateTableController extends GetxController {
|
class CreateTableController extends GetxController {
|
||||||
|
|
@ -35,7 +35,7 @@ class CreateTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.back(result: true);
|
Get.back(result: true);
|
||||||
|
|
@ -43,18 +43,18 @@ class CreateTableController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления доступа к таблице",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления доступа к таблице",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления доступа к таблице",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -67,14 +67,14 @@ class CreateTableController extends GetxController {
|
||||||
|
|
||||||
final confirm = await Get.dialog<bool>(
|
final confirm = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Create new column"),
|
title: const Text("Создать новую колонку"),
|
||||||
content: Wrap(
|
content: Wrap(
|
||||||
runSpacing: 16,
|
runSpacing: 16,
|
||||||
children: [
|
children: [
|
||||||
FastTextField(
|
FastTextField(
|
||||||
name: "ColumnName",
|
name: "ColumnName",
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Column name",
|
labelText: "Название",
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
initialValue: columnName.value,
|
initialValue: columnName.value,
|
||||||
|
|
@ -82,7 +82,7 @@ class CreateTableController extends GetxController {
|
||||||
),
|
),
|
||||||
FastDropdown(
|
FastDropdown(
|
||||||
name: "ColumnTypes",
|
name: "ColumnTypes",
|
||||||
hint: const Text("Select column type"),
|
hint: const Text("Тип"),
|
||||||
items: typeToNameMatcher.keys.toList(growable: false),
|
items: typeToNameMatcher.keys.toList(growable: false),
|
||||||
itemsBuilder: (items, field) => items
|
itemsBuilder: (items, field) => items
|
||||||
.map(
|
.map(
|
||||||
|
|
@ -97,7 +97,7 @@ class CreateTableController extends GetxController {
|
||||||
),
|
),
|
||||||
FastCheckbox(
|
FastCheckbox(
|
||||||
name: "ColumnIsUnique",
|
name: "ColumnIsUnique",
|
||||||
titleText: "Is Unique",
|
titleText: "Уникальное значение?",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
onChanged: (value) => columnIsUnique.value = value!,
|
onChanged: (value) => columnIsUnique.value = value!,
|
||||||
),
|
),
|
||||||
|
|
@ -108,13 +108,13 @@ class CreateTableController extends GetxController {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: false);
|
Get.back(result: false);
|
||||||
},
|
},
|
||||||
child: const Text('Close'),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: true);
|
Get.back(result: true);
|
||||||
},
|
},
|
||||||
child: const Text('Create'),
|
child: const Text("Создать"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -129,42 +129,42 @@ class CreateTableController extends GetxController {
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Text":
|
case "Текст":
|
||||||
ct = TextColumnDefinition(
|
ct = TextColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
isUnique: columnIsUnique.value,
|
isUnique: columnIsUnique.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Boolean":
|
case "Логическое значение":
|
||||||
ct = BooleanColumnDefinition(
|
ct = BooleanColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
isUnique: columnIsUnique.value,
|
isUnique: columnIsUnique.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Date/Time":
|
case "Дата/Время":
|
||||||
ct = TimestampColumnDefinition(
|
ct = TimestampColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
isUnique: columnIsUnique.value,
|
isUnique: columnIsUnique.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Double":
|
case "Число с плавающей точкой":
|
||||||
ct = DoubleColumnDefinition(
|
ct = DoubleColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
isUnique: columnIsUnique.value,
|
isUnique: columnIsUnique.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Integer":
|
case "Целое число":
|
||||||
ct = IntegerColumnDefinition(
|
ct = IntegerColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
isUnique: columnIsUnique.value,
|
isUnique: columnIsUnique.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "User reference":
|
case "Ссылка на пользователя":
|
||||||
ct = UserRefColumnDefinition(
|
ct = UserRefColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Asset reference":
|
case "Ссылка на ресурс":
|
||||||
ct = AssetRefColumnDefinition(
|
ct = AssetRefColumnDefinition(
|
||||||
columnName: columnName.value,
|
columnName: columnName.value,
|
||||||
);
|
);
|
||||||
|
|
@ -185,12 +185,12 @@ class CreateTableDialog extends GetView<CreateTableController> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('Creating new table'),
|
title: const Text("Создать новую таблицу"),
|
||||||
content: Column(
|
content: Column(
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Table name",
|
labelText: "Название",
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
onChanged: (value) => controller.tableName = value,
|
onChanged: (value) => controller.tableName = value,
|
||||||
|
|
@ -216,7 +216,7 @@ class CreateTableDialog extends GetView<CreateTableController> {
|
||||||
[
|
[
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => controller.createNewColumn(),
|
onPressed: () => controller.createNewColumn(),
|
||||||
child: const Text("Create column"),
|
child: const Text("Создать колонку"),
|
||||||
).expanded()
|
).expanded()
|
||||||
].toRow(),
|
].toRow(),
|
||||||
],
|
],
|
||||||
|
|
@ -226,14 +226,14 @@ class CreateTableDialog extends GetView<CreateTableController> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
Get.back();
|
||||||
},
|
},
|
||||||
child: const Text('Close'),
|
child: const Text("Закрыть"),
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
() => TextButton(
|
() => TextButton(
|
||||||
onPressed: controller.columnsDefinition.isEmpty
|
onPressed: controller.columnsDefinition.isEmpty
|
||||||
? null
|
? null
|
||||||
: () => controller.createTable(),
|
: () => controller.createTable(),
|
||||||
child: const Text('Create'),
|
child: const Text("Создать"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class GroupACLController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tables.clear();
|
_tables.clear();
|
||||||
|
|
@ -56,18 +56,18 @@ class GroupACLController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables",
|
"Ошибка запроса таблиц",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables",
|
"Ошибка запроса таблиц",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables",
|
"Ошибка запроса таблиц",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +96,7 @@ class GroupACLController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respData.isNotEmpty) {
|
if (respData.isNotEmpty) {
|
||||||
|
|
@ -111,18 +111,18 @@ class GroupACLController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables access",
|
"Ошибка запроса информации доступа к таблицам",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables access",
|
"Ошибка запроса информации доступа к таблицам",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables access",
|
"Ошибка запроса информации доступа к таблицам",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +187,7 @@ class GroupACLController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTableAccess(table);
|
refreshTableAccess(table);
|
||||||
|
|
@ -195,18 +195,18 @@ class GroupACLController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления информации доступа к таблицам",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления информации доступа к таблицам",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления информации доступа к таблицам",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +234,7 @@ class GroupACLController extends GetxController {
|
||||||
|
|
||||||
final confirm = await Get.dialog<bool>(
|
final confirm = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Allowed columns"),
|
title: const Text("Разрешённые колонки"),
|
||||||
content: Obx(
|
content: Obx(
|
||||||
() => Wrap(
|
() => Wrap(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -244,7 +244,7 @@ class GroupACLController extends GetxController {
|
||||||
selectedColumns[column] = !selectedColumns[column]!;
|
selectedColumns[column] = !selectedColumns[column]!;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Text("Swap all"),
|
child: const Text("Перевернуть"),
|
||||||
),
|
),
|
||||||
...selectedColumns.entries.map((e) {
|
...selectedColumns.entries.map((e) {
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
|
|
@ -259,11 +259,11 @@ class GroupACLController extends GetxController {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Ok"),
|
child: const Text("Ок"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -274,12 +274,12 @@ class GroupACLController extends GetxController {
|
||||||
if (selectedColumns.values.every((e) => !e)) {
|
if (selectedColumns.values.every((e) => !e)) {
|
||||||
await Get.dialog(
|
await Get.dialog(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Error"),
|
title: const Text("Ошибка"),
|
||||||
content: const Text("At least one column must be selected"),
|
content: const Text("Необходимо выбрать хотя бы одну колонку"),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(),
|
onPressed: () => Get.back(),
|
||||||
child: const Text("Ok"),
|
child: const Text("Ок"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -306,7 +306,7 @@ class GroupACLController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTableAccess(table);
|
refreshTableAccess(table);
|
||||||
|
|
@ -314,18 +314,18 @@ class GroupACLController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления информации доступа к таблицам",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления информации доступа к таблицам",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update tables access",
|
"Ошибка обновления информации доступа к таблицам",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -338,16 +338,16 @@ class GroupACLDialog extends GetView<GroupACLController> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('Group ACL'),
|
title: const Text('Доступ группы'),
|
||||||
content: Obx(
|
content: Obx(
|
||||||
() => DataTable2(
|
() => DataTable2(
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn2(label: Text('Table'), size: ColumnSize.L),
|
DataColumn2(label: Text('Таблица'), size: ColumnSize.L),
|
||||||
DataColumn2(label: Text('Read'), size: ColumnSize.S),
|
DataColumn2(label: Text('Чтение'), size: ColumnSize.S),
|
||||||
DataColumn2(label: Text('Write'), size: ColumnSize.S),
|
DataColumn2(label: Text('Запись'), size: ColumnSize.S),
|
||||||
DataColumn2(label: Text('Allowed columns'), size: ColumnSize.S),
|
DataColumn2(label: Text('Колонки'), size: ColumnSize.S),
|
||||||
],
|
],
|
||||||
empty: const Text("No tables"),
|
empty: const Text("Нет таблиц"),
|
||||||
rows: controller.access.entries.map((e) {
|
rows: controller.access.entries.map((e) {
|
||||||
final table = controller.tables.firstWhere(
|
final table = controller.tables.firstWhere(
|
||||||
(element) => element.tableId == e.key,
|
(element) => element.tableId == e.key,
|
||||||
|
|
@ -390,7 +390,7 @@ class GroupACLDialog extends GetView<GroupACLController> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
Get.back();
|
||||||
},
|
},
|
||||||
child: const Text('Close'),
|
child: const Text("Закрыть"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:data_table_2/data_table_2.dart';
|
import 'package:data_table_2/data_table_2.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_fast_forms/flutter_fast_forms.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:omni_datetime_picker/omni_datetime_picker.dart';
|
import 'package:omni_datetime_picker/omni_datetime_picker.dart';
|
||||||
import 'package:recase/recase.dart';
|
import 'package:recase/recase.dart';
|
||||||
|
|
@ -70,7 +69,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tableData.clear();
|
_tableData.clear();
|
||||||
|
|
@ -79,18 +78,18 @@ class OpenTableController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get table data",
|
"Ошибка получения данных таблицы",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get table data",
|
"Ошибка получения данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get table data",
|
"Ошибка получения данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +100,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final user = await Get.dialog<UserDefinition>(
|
final user = await Get.dialog<UserDefinition>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Select user"),
|
title: const Text("Выберите пользователя"),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -110,7 +109,7 @@ class OpenTableController extends GetxController {
|
||||||
username.value = value;
|
username.value = value;
|
||||||
},
|
},
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Username",
|
labelText: "Логин",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
|
|
@ -140,7 +139,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
return respData
|
return respData
|
||||||
|
|
@ -187,7 +186,7 @@ class OpenTableController extends GetxController {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: false);
|
Get.back(result: false);
|
||||||
},
|
},
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -201,7 +200,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final asset = await Get.dialog<Asset>(
|
final asset = await Get.dialog<Asset>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Select asset"),
|
title: const Text("Выберите ресурс"),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -210,7 +209,7 @@ class OpenTableController extends GetxController {
|
||||||
name.value = value;
|
name.value = value;
|
||||||
},
|
},
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Filename",
|
labelText: "Имя файла",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
|
|
@ -241,7 +240,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
return respData
|
return respData
|
||||||
|
|
@ -291,7 +290,7 @@ class OpenTableController extends GetxController {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: null);
|
Get.back(result: null);
|
||||||
},
|
},
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -309,7 +308,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
clearNewRowData();
|
clearNewRowData();
|
||||||
|
|
@ -318,18 +317,18 @@ class OpenTableController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get table data",
|
"Ошибка получения данных таблицы",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get table data",
|
"Ошибка получения данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get table data",
|
"Ошибка получения данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -357,7 +356,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTableData();
|
refreshTableData();
|
||||||
|
|
@ -365,18 +364,18 @@ class OpenTableController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update table data",
|
"Ошибка обновления данных таблицы",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update table data",
|
"Ошибка обновления данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update table data",
|
"Ошибка обновления данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -408,7 +407,7 @@ class OpenTableController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTableData();
|
refreshTableData();
|
||||||
|
|
@ -416,18 +415,18 @@ class OpenTableController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update table data",
|
"Ошибка удаления данных таблицы",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update table data",
|
"Ошибка удаления данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to update table data",
|
"Ошибка удаления данных таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -465,9 +464,9 @@ class OpenTableDialog extends GetView<OpenTableController> {
|
||||||
col.name.pascalCase,
|
col.name.pascalCase,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const DataColumn(label: Text("Actions")),
|
const DataColumn(label: Text("Действия")),
|
||||||
],
|
],
|
||||||
empty: const Text("No data"),
|
empty: const Text("Нет данных"),
|
||||||
rows: [
|
rows: [
|
||||||
DataRow(
|
DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
|
|
@ -699,7 +698,7 @@ class OpenTableDialog extends GetView<OpenTableController> {
|
||||||
final msg = () {
|
final msg = () {
|
||||||
final dt = e[col.name];
|
final dt = e[col.name];
|
||||||
if (dt == null) {
|
if (dt == null) {
|
||||||
return "#error#";
|
return "###";
|
||||||
}
|
}
|
||||||
if (dt is String) {
|
if (dt is String) {
|
||||||
final rdt = DateTime.parse(dt);
|
final rdt = DateTime.parse(dt);
|
||||||
|
|
@ -805,7 +804,7 @@ class OpenTableDialog extends GetView<OpenTableController> {
|
||||||
if (ud == null ||
|
if (ud == null ||
|
||||||
ud.isEmpty ||
|
ud.isEmpty ||
|
||||||
ud.first["username"] == null) {
|
ud.first["username"] == null) {
|
||||||
return "#error#";
|
return "###";
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.putUserInCache(UserDefinition(
|
controller.putUserInCache(UserDefinition(
|
||||||
|
|
@ -824,9 +823,9 @@ class OpenTableDialog extends GetView<OpenTableController> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: snapshot.data ?? "#error#",
|
message: snapshot.data ?? "###",
|
||||||
child: Text(
|
child: Text(
|
||||||
snapshot.data ?? "#error#",
|
snapshot.data ?? "###",
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
|
|
@ -873,7 +872,7 @@ class OpenTableDialog extends GetView<OpenTableController> {
|
||||||
if (ad == null ||
|
if (ad == null ||
|
||||||
ad.isEmpty ||
|
ad.isEmpty ||
|
||||||
ad.first["name"] == null) {
|
ad.first["name"] == null) {
|
||||||
return "#error#";
|
return "###";
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.putAssetInCache(Asset(
|
controller.putAssetInCache(Asset(
|
||||||
|
|
@ -894,9 +893,9 @@ class OpenTableDialog extends GetView<OpenTableController> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: snapshot.data ?? "#error#",
|
message: snapshot.data ?? "###",
|
||||||
child: Text(
|
child: Text(
|
||||||
snapshot.data ?? "#error#",
|
snapshot.data ?? "###",
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get_storage/get_storage.dart';
|
|
||||||
import 'package:tuuli_app/api_controller.dart';
|
import 'package:tuuli_app/api_controller.dart';
|
||||||
import 'package:tuuli_app/c.dart';
|
import 'package:tuuli_app/c.dart';
|
||||||
import 'package:tuuli_app/pages/home_panels/assets_panel.dart';
|
import 'package:tuuli_app/pages/home_panels/assets_panel.dart';
|
||||||
|
|
@ -25,11 +24,11 @@ class HomePageController extends GetxController {
|
||||||
String get currentPageName => pageNames[currentPage]!;
|
String get currentPageName => pageNames[currentPage]!;
|
||||||
|
|
||||||
final pageNames = {
|
final pageNames = {
|
||||||
PageType.none: "Home",
|
PageType.none: "Домашняя",
|
||||||
PageType.tables: "Tables",
|
PageType.tables: "Таблицы",
|
||||||
PageType.users: "Users",
|
PageType.users: "Пользователи",
|
||||||
PageType.assets: "Assets",
|
PageType.assets: "Ресурсы",
|
||||||
PageType.settings: "Settings",
|
PageType.settings: "Настройки",
|
||||||
};
|
};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -91,7 +90,7 @@ class HomePage extends GetView<HomePageController> {
|
||||||
Obx(
|
Obx(
|
||||||
() => ListTile(
|
() => ListTile(
|
||||||
leading: const Icon(Icons.table_chart),
|
leading: const Icon(Icons.table_chart),
|
||||||
title: const Text("Tables"),
|
title: const Text("Таблицы"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
controller.currentPage = PageType.tables;
|
controller.currentPage = PageType.tables;
|
||||||
},
|
},
|
||||||
|
|
@ -101,7 +100,7 @@ class HomePage extends GetView<HomePageController> {
|
||||||
Obx(
|
Obx(
|
||||||
() => ListTile(
|
() => ListTile(
|
||||||
leading: const Icon(Icons.person),
|
leading: const Icon(Icons.person),
|
||||||
title: const Text("Users"),
|
title: const Text("Пользователи"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
controller.currentPage = PageType.users;
|
controller.currentPage = PageType.users;
|
||||||
},
|
},
|
||||||
|
|
@ -111,7 +110,7 @@ class HomePage extends GetView<HomePageController> {
|
||||||
Obx(
|
Obx(
|
||||||
() => ListTile(
|
() => ListTile(
|
||||||
leading: const Icon(Icons.dataset_outlined),
|
leading: const Icon(Icons.dataset_outlined),
|
||||||
title: const Text("Assets"),
|
title: const Text("Ресурсы"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
controller.currentPage = PageType.assets;
|
controller.currentPage = PageType.assets;
|
||||||
},
|
},
|
||||||
|
|
@ -121,7 +120,7 @@ class HomePage extends GetView<HomePageController> {
|
||||||
Obx(
|
Obx(
|
||||||
() => ListTile(
|
() => ListTile(
|
||||||
leading: const Icon(Icons.settings),
|
leading: const Icon(Icons.settings),
|
||||||
title: const Text("Settings"),
|
title: const Text("Настройки"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
controller.currentPage = PageType.settings;
|
controller.currentPage = PageType.settings;
|
||||||
},
|
},
|
||||||
|
|
@ -131,7 +130,7 @@ class HomePage extends GetView<HomePageController> {
|
||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.logout),
|
leading: const Icon(Icons.logout),
|
||||||
title: const Text("Logout"),
|
title: const Text("Выйти"),
|
||||||
onTap: () => controller.logout(),
|
onTap: () => controller.logout(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_assetsList.clear();
|
_assetsList.clear();
|
||||||
|
|
@ -61,18 +61,18 @@ class AssetsPagePanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get assets",
|
"Ошибка получения ресурсов",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get assets",
|
"Ошибка получения ресурсов",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get assets",
|
"Ошибка получения ресурсов",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tagsList.clear();
|
_tagsList.clear();
|
||||||
|
|
@ -93,18 +93,18 @@ class AssetsPagePanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tags",
|
"Ошибка получения тегов",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tags",
|
"Ошибка получения тегов",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tags",
|
"Ошибка получения тегов",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -145,11 +145,11 @@ class AssetsPagePanelController extends GetxController {
|
||||||
Get.back(result: file);
|
Get.back(result: file);
|
||||||
},
|
},
|
||||||
onError: (value) {
|
onError: (value) {
|
||||||
Get.snackbar("Error", value.toString());
|
Get.snackbar("Ошибка", value.toString());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: const Text("Drop file here")
|
child: const Text("Перенесите файл сюда")
|
||||||
.paddingAll(8)
|
.paddingAll(8)
|
||||||
.fittedBox()
|
.fittedBox()
|
||||||
.constrained(height: 200, width: 200),
|
.constrained(height: 200, width: 200),
|
||||||
|
|
@ -157,7 +157,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: null),
|
onPressed: () => Get.back(result: null),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -195,7 +195,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -203,18 +203,18 @@ class AssetsPagePanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to put asset",
|
"Ошибка загрузки ресурса",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to put asset",
|
"Ошибка загрузки ресурса",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to put asset",
|
"Ошибка загрузки ресурса",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -228,7 +228,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final confirm = await Get.dialog<bool>(
|
final confirm = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Edit asset"),
|
title: const Text("Изменение ресурса"),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
|
@ -237,7 +237,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
controller: TextEditingController(text: description.value),
|
controller: TextEditingController(text: description.value),
|
||||||
onChanged: (value) => description.value = value,
|
onChanged: (value) => description.value = value,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Description",
|
labelText: "Описание",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
|
|
@ -245,7 +245,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
onChanged: (value) => tags.value =
|
onChanged: (value) => tags.value =
|
||||||
value.split(",").map((e) => e.trim()).toList(growable: false),
|
value.split(",").map((e) => e.trim()).toList(growable: false),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Tags",
|
labelText: "Теги",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
@ -253,23 +253,23 @@ class AssetsPagePanelController extends GetxController {
|
||||||
() => Wrap(
|
() => Wrap(
|
||||||
children: tags
|
children: tags
|
||||||
.where((p0) => p0.isNotEmpty)
|
.where((p0) => p0.isNotEmpty)
|
||||||
.map((tag) => Chip(label: Text(tag)))
|
.map((tag) => Chip(label: Text(tag)).paddingAll(2))
|
||||||
.toList(growable: false),
|
.toList(growable: false),
|
||||||
).paddingAll(8).card(color: Colors.blueGrey.shade200).expanded(),
|
).paddingAll(8).card(color: Colors.blueGrey.shade200).expanded(),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => previewAsset(e),
|
onPressed: () => previewAsset(e),
|
||||||
child: const Text("View asset")),
|
child: const Text("Предпросмотр")),
|
||||||
],
|
],
|
||||||
).constrained(width: Get.width * 0.5, height: Get.width * 0.5),
|
).constrained(width: Get.width * 0.5, height: Get.width * 0.5),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Confirm"),
|
child: const Text("Подтвердить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -287,7 +287,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -295,18 +295,18 @@ class AssetsPagePanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to edit asset",
|
"Ошибка изменения ресурса",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to edit asset",
|
"Ошибка изменения ресурса",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to edit asset",
|
"Ошибка изменения ресурса",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -318,23 +318,24 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final confirm = await Get.dialog<bool>(
|
final confirm = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Remove asset"),
|
title: const Text("Удаление ресурса"),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Text("You are about to remove an asset."),
|
const Text(
|
||||||
|
"Вы планируете удалить ресурс. Это действие нельзя отменить."),
|
||||||
Obx(
|
Obx(
|
||||||
() => CheckboxListTile(
|
() => CheckboxListTile(
|
||||||
value: checkReferences.value,
|
value: checkReferences.value,
|
||||||
onChanged: (value) => checkReferences.value = value ?? false,
|
onChanged: (value) => checkReferences.value = value ?? false,
|
||||||
title: const Text("Check references"),
|
title: const Text("Проверить ссылки"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
() => CheckboxListTile(
|
() => CheckboxListTile(
|
||||||
value: deleteReferencing.value,
|
value: deleteReferencing.value,
|
||||||
onChanged: (value) => deleteReferencing.value = value ?? false,
|
onChanged: (value) => deleteReferencing.value = value ?? false,
|
||||||
title: const Text("Delete referencing"),
|
title: const Text("Удалить ссылающиеся сущности"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -342,11 +343,11 @@ class AssetsPagePanelController extends GetxController {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Remove"),
|
child: const Text("Удалить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -363,7 +364,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -371,18 +372,18 @@ class AssetsPagePanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to remove asset",
|
"Ошибка удаления ресурса",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to remove asset",
|
"Ошибка удаления ресурса",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to remove asset",
|
"Ошибка удаления ресурса",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -404,7 +405,7 @@ class AssetsPagePanelController extends GetxController {
|
||||||
url: "${ApiController.to.endPoint}/assets/${e.fid}",
|
url: "${ApiController.to.endPoint}/assets/${e.fid}",
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
const Text("Unsupported media type")
|
const Text("На данный момент этот тип не поддерживает предпросмотр")
|
||||||
.fontSize(16)
|
.fontSize(16)
|
||||||
.paddingAll(8)
|
.paddingAll(8)
|
||||||
.card()
|
.card()
|
||||||
|
|
@ -439,7 +440,7 @@ class AssetsPagePanel extends GetView<AssetsPagePanelController> {
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
title: Row(
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
const Text("Tags:"),
|
const Text("Теги:"),
|
||||||
Obx(
|
Obx(
|
||||||
() => FastChipsInput(
|
() => FastChipsInput(
|
||||||
name: "FastChipsInput",
|
name: "FastChipsInput",
|
||||||
|
|
@ -496,13 +497,13 @@ class AssetsPagePanel extends GetView<AssetsPagePanelController> {
|
||||||
horizontalScrollController: controller.scrollController,
|
horizontalScrollController: controller.scrollController,
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn2(label: Text(""), fixedWidth: 16),
|
DataColumn2(label: Text(""), fixedWidth: 16),
|
||||||
DataColumn2(label: Text("Filename"), size: ColumnSize.M),
|
DataColumn2(label: Text("Имя файла"), size: ColumnSize.M),
|
||||||
DataColumn2(label: Text("Description"), size: ColumnSize.L),
|
DataColumn2(label: Text("Описание"), size: ColumnSize.L),
|
||||||
DataColumn2(label: Text("File ID"), size: ColumnSize.M),
|
DataColumn2(label: Text("ID файла"), size: ColumnSize.M),
|
||||||
DataColumn2(label: Text("Tags"), size: ColumnSize.L),
|
DataColumn2(label: Text("Теги"), size: ColumnSize.L),
|
||||||
DataColumn2(label: Text("Actions")),
|
DataColumn2(label: Text("Действия")),
|
||||||
],
|
],
|
||||||
empty: const Text("No assets found"),
|
empty: const Text("Ресурсы не найдены"),
|
||||||
rows: controller.assetsList
|
rows: controller.assetsList
|
||||||
.where((element) {
|
.where((element) {
|
||||||
if (controller.filterTags.isEmpty) return true;
|
if (controller.filterTags.isEmpty) return true;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ class NonePanel extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Use the menu for navigation',
|
"Используйте меню слева для навигации",
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flu_console/flu_console.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:tuuli_app/api_controller.dart';
|
||||||
|
import 'package:tuuli_app/pages/home_page.dart';
|
||||||
|
|
||||||
class SettingsPanel extends StatefulWidget {
|
class SettingsPanel extends StatefulWidget {
|
||||||
const SettingsPanel({super.key});
|
const SettingsPanel({super.key});
|
||||||
|
|
@ -16,21 +21,53 @@ class _SettingsPanelState extends State<SettingsPanel> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(
|
|
||||||
child: IntrinsicHeight(
|
|
||||||
child: _buildBody(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildBody() {
|
|
||||||
return Column(
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text("Ключ доступа пользователя:")
|
||||||
'Settings',
|
.textStyle(Get.textTheme.bodySmall!),
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
[
|
||||||
),
|
Text(ApiController.to.token)
|
||||||
|
.textStyle(Get.textTheme.titleSmall!)
|
||||||
|
.expanded(),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await Clipboard.setData(
|
||||||
|
ClipboardData(text: ApiController.to.token),
|
||||||
|
);
|
||||||
|
Get.snackbar(
|
||||||
|
"Скопировано",
|
||||||
|
"Ключ скопирован в буфер обмена",
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.copy),
|
||||||
|
),
|
||||||
|
].toRow(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
[
|
||||||
|
TextFormField(
|
||||||
|
enabled: false,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Адрес бэкенда',
|
||||||
|
hintText: 'Введите адрес бэкенда',
|
||||||
|
),
|
||||||
|
initialValue: ApiController.to.endPoint,
|
||||||
|
).expanded(),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Get.find<HomePageController>().logout(),
|
||||||
|
child: const Text("Выйти и изменить"),
|
||||||
|
)
|
||||||
|
].toRow(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
[
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Get.bottomSheet(const LogPrintPanel()),
|
||||||
|
child: const Text("Показать лог приложения"),
|
||||||
|
).expanded(),
|
||||||
|
].toRow(),
|
||||||
],
|
],
|
||||||
);
|
).paddingAll(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class TablesListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tables.clear();
|
_tables.clear();
|
||||||
|
|
@ -38,18 +38,18 @@ class TablesListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables",
|
"Ошибка получения таблиц",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables",
|
"Ошибка получения таблиц",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get tables",
|
"Ошибка получения таблиц",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -68,6 +68,31 @@ class TablesListPanelController extends GetxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteTable(TableDefinition table) async {
|
Future<void> deleteTable(TableDefinition table) async {
|
||||||
|
final accept = await Get.dialog<bool>(
|
||||||
|
AlertDialog(
|
||||||
|
title: const Text("Удалить таблицу"),
|
||||||
|
content: Text(
|
||||||
|
"Вы действительно хотите удалить таблицу ${table.tableName.pascalCase}?",
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Get.back(result: false);
|
||||||
|
},
|
||||||
|
child: const Text("Отменить"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Get.back(result: true);
|
||||||
|
},
|
||||||
|
child: const Text("Удалить"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (accept != true) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final resp = await ApiController.to.apiClient.dropTable(
|
final resp = await ApiController.to.apiClient.dropTable(
|
||||||
tableName: table.tableName,
|
tableName: table.tableName,
|
||||||
|
|
@ -75,30 +100,30 @@ class TablesListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Table deleted",
|
"Таблица удалена",
|
||||||
"${table.tableName.pascalCase} was deleted",
|
"Таблица ${table.tableName.pascalCase} была удалена",
|
||||||
);
|
);
|
||||||
refreshData();
|
refreshData();
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete table",
|
"Ошибка удаления таблицы",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete table",
|
"Ошибка удаления таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete table",
|
"Ошибка удаления таблицы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +226,7 @@ class TablesListPanel extends GetView<TablesListPanelController> {
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
table.system ? "System" : "Userland",
|
table.system ? "Системная" : "Пользовательская",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
|
|
@ -211,7 +236,7 @@ class TablesListPanel extends GetView<TablesListPanelController> {
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"${table.parsedColumns.length} column(s)",
|
"${table.parsedColumns.length} колонок(ки)",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
|
|
@ -222,7 +247,7 @@ class TablesListPanel extends GetView<TablesListPanelController> {
|
||||||
if (!table.system)
|
if (!table.system)
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => controller.deleteTable(table),
|
onPressed: () => controller.deleteTable(table),
|
||||||
child: const Text("Delete"),
|
child: const Text("Удалить"),
|
||||||
).paddingOnly(top: 8)
|
).paddingOnly(top: 8)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import 'package:built_collection/built_collection.dart';
|
|
||||||
import 'package:built_value/json_object.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
@ -68,7 +66,7 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_users.clear();
|
_users.clear();
|
||||||
|
|
@ -82,18 +80,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get users",
|
"Ошибка получения пользователей",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get users",
|
"Ошибка получения пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get users",
|
"Ошибка получения пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +108,7 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
_groups.clear();
|
_groups.clear();
|
||||||
|
|
@ -123,18 +121,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get groups",
|
"Ошибка получения групп пользователей",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get groups",
|
"Ошибка получения групп пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to get groups",
|
"Ошибка получения групп пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -149,8 +147,8 @@ class UserListPanelController extends GetxController {
|
||||||
final accept = await Get.dialog<bool>(
|
final accept = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: user == null
|
title: user == null
|
||||||
? const Text("Create new user")
|
? const Text("Создание нового пользователя")
|
||||||
: const Text("Edit user"),
|
: const Text("Редактирование пользователя"),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -159,14 +157,14 @@ class UserListPanelController extends GetxController {
|
||||||
? TextEditingController(text: user.username)
|
? TextEditingController(text: user.username)
|
||||||
: null,
|
: null,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Username",
|
labelText: "Логин",
|
||||||
),
|
),
|
||||||
readOnly: user != null,
|
readOnly: user != null,
|
||||||
onChanged: (value) => username.value = value,
|
onChanged: (value) => username.value = value,
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Password",
|
labelText: "Пароль",
|
||||||
),
|
),
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
onChanged: (value) => password.value = value,
|
onChanged: (value) => password.value = value,
|
||||||
|
|
@ -176,11 +174,12 @@ class UserListPanelController extends GetxController {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: user == null ? const Text("Create") : const Text("Save"),
|
child:
|
||||||
|
user == null ? const Text("Создать") : const Text("Сохранить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -210,7 +209,7 @@ class UserListPanelController extends GetxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -218,18 +217,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to create user",
|
"Ошибка создания пользователя",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to create user",
|
"Ошибка создания пользователя",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to create user",
|
"Ошибка создания пользователя",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -240,19 +239,19 @@ class UserListPanelController extends GetxController {
|
||||||
final groupDescription = "".obs;
|
final groupDescription = "".obs;
|
||||||
final accept = await Get.dialog<bool>(
|
final accept = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Create new group"),
|
title: const Text("Создание группы пользователей"),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Group name",
|
labelText: "Название",
|
||||||
),
|
),
|
||||||
onChanged: (value) => groupName.value = value,
|
onChanged: (value) => groupName.value = value,
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Group description (optional)",
|
labelText: "Описание (опционально)",
|
||||||
),
|
),
|
||||||
onChanged: (value) => groupDescription.value = value,
|
onChanged: (value) => groupDescription.value = value,
|
||||||
),
|
),
|
||||||
|
|
@ -261,11 +260,11 @@ class UserListPanelController extends GetxController {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Create"),
|
child: const Text("Создать"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -284,12 +283,12 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Group created",
|
"Группа создана",
|
||||||
"Group $groupName created",
|
"Группа $groupName создана",
|
||||||
);
|
);
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -297,18 +296,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to create group",
|
"Ошибка создания группы пользователей",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to create group",
|
"Ошибка создания группы пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to create group",
|
"Ошибка создания группы пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +330,7 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
final data = respData
|
final data = respData
|
||||||
|
|
@ -356,7 +355,7 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final selectedUser = await Get.dialog<UserDefinition>(
|
final selectedUser = await Get.dialog<UserDefinition>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Select user to add to group"),
|
title: const Text("Какого пользователя добавить в группу"),
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: 400,
|
width: 400,
|
||||||
height: 400,
|
height: 400,
|
||||||
|
|
@ -374,7 +373,7 @@ class UserListPanelController extends GetxController {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: null),
|
onPressed: () => Get.back(result: null),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -393,12 +392,12 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"User added to group",
|
"Пользователь добавлен в группу",
|
||||||
"User ${selectedUser.username} added to group ${group.name}",
|
"Пользователь ${selectedUser.username} добавлен в группу ${group.name}",
|
||||||
);
|
);
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -406,18 +405,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to add user to group",
|
"Ошибка добавления пользователя в группу",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to add user to group",
|
"Ошибка добавления пользователя в группу",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to add user to group",
|
"Ошибка добавления пользователя в группу",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -429,17 +428,17 @@ class UserListPanelController extends GetxController {
|
||||||
) async {
|
) async {
|
||||||
final accept = await Get.dialog<bool>(
|
final accept = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Remove user from group"),
|
title: const Text("Удаление пользователя из группы"),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"Are you sure you want to remove this user from the group?"),
|
"Вы действительно хотите удалить этого пользователя из группы?"),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Remove"),
|
child: const Text("Удалить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -466,12 +465,12 @@ class UserListPanelController extends GetxController {
|
||||||
|
|
||||||
final respData = resp.data;
|
final respData = resp.data;
|
||||||
if (respData == null) {
|
if (respData == null) {
|
||||||
throw Exception("No data in response");
|
throw Exception("В ответе нет данных");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"User removed from group",
|
"Пользователь удалён из группы",
|
||||||
"User ${user.username} removed from group ${group.name}",
|
"Пользователь ${user.username} удалён из группы ${group.name}",
|
||||||
);
|
);
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -479,18 +478,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to remove user from group",
|
"Ошибка удаления пользователя из группы",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to remove user from group",
|
"Ошибка удаления пользователя из группы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to remove user from group",
|
"Ошибка удаления пользователя из группы",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -499,17 +498,16 @@ class UserListPanelController extends GetxController {
|
||||||
Future<void> deleteGroup(GroupDefinition group) async {
|
Future<void> deleteGroup(GroupDefinition group) async {
|
||||||
final accept = await Get.dialog<bool>(
|
final accept = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Delete group"),
|
title: const Text("Удаление группы"),
|
||||||
content: const Text(
|
content: const Text("Вы действительно хотите удалить эту группу?"),
|
||||||
"Are you sure you want to delete this group? This action cannot be undone."),
|
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Delete"),
|
child: const Text("Удалить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -530,7 +528,7 @@ class UserListPanelController extends GetxController {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (resp1.data == null) {
|
if (resp1.data == null) {
|
||||||
throw Exception("Could not delete users from group");
|
throw Exception("Не удалось удалить пользователей из группы");
|
||||||
}
|
}
|
||||||
|
|
||||||
final resp2 = await ApiController.to.apiClient.deleteItemFromTable(
|
final resp2 = await ApiController.to.apiClient.deleteItemFromTable(
|
||||||
|
|
@ -545,12 +543,12 @@ class UserListPanelController extends GetxController {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (resp2.data == null) {
|
if (resp2.data == null) {
|
||||||
throw Exception("Could not delete group");
|
throw Exception("Не удалось удалить группу пользователей");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Group deleted",
|
"Группа пользователей удалена",
|
||||||
"Group ${group.name} deleted",
|
"Группа ${group.name} удалена",
|
||||||
);
|
);
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -558,18 +556,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete group",
|
"Ошибка удаления группы пользователей",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete group",
|
"Ошибка удаления группы пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete group",
|
"Ошибка удаления группы пользователей",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -582,19 +580,18 @@ class UserListPanelController extends GetxController {
|
||||||
Future<void> deleteUser(UserDefinition user) async {
|
Future<void> deleteUser(UserDefinition user) async {
|
||||||
final accept = await Get.dialog<bool>(
|
final accept = await Get.dialog<bool>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Delete user"),
|
title: const Text("Удалить пользователя"),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"Are you sure you want to delete this user? This action cannot be undone.\n"
|
"Вы уверены, что хотите удалить этого пользователя?",
|
||||||
"Note: This will not remove references to this user in other tables.",
|
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: false),
|
onPressed: () => Get.back(result: false),
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Get.back(result: true),
|
onPressed: () => Get.back(result: true),
|
||||||
child: const Text("Delete"),
|
child: const Text("Удалить"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -615,7 +612,7 @@ class UserListPanelController extends GetxController {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (resp1.data == null) {
|
if (resp1.data == null) {
|
||||||
throw Exception("Could not delete users from group");
|
throw Exception("Не удалось удалить пользователя из групп");
|
||||||
}
|
}
|
||||||
|
|
||||||
final resp2 = await ApiController.to.apiClient.removeUser(
|
final resp2 = await ApiController.to.apiClient.removeUser(
|
||||||
|
|
@ -623,12 +620,12 @@ class UserListPanelController extends GetxController {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (resp2.data == null) {
|
if (resp2.data == null) {
|
||||||
throw Exception("Could not delete group");
|
throw Exception("Не удалось удалить пользователя");
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"User deleted",
|
"Пользователь удалён",
|
||||||
"User ${user.username} deleted",
|
"Пользователь ${user.username} удалён",
|
||||||
);
|
);
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|
@ -636,18 +633,18 @@ class UserListPanelController extends GetxController {
|
||||||
final respData = e.response?.data;
|
final respData = e.response?.data;
|
||||||
if (respData != null) {
|
if (respData != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete user",
|
"Ошибка удаления пользователя",
|
||||||
"${respData['error']}",
|
"${respData['error']}",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete user",
|
"Ошибка удаления пользователя",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Error trying to delete user",
|
"Ошибка удаления пользователя",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -674,11 +671,11 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
items: const [
|
items: const [
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
value: UserListPanelTab.users,
|
value: UserListPanelTab.users,
|
||||||
child: Text("Users"),
|
child: Text("Пользователи"),
|
||||||
),
|
),
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
value: UserListPanelTab.groups,
|
value: UserListPanelTab.groups,
|
||||||
child: Text("Groups"),
|
child: Text("Группы"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
value: controller.currentTab,
|
value: controller.currentTab,
|
||||||
|
|
@ -721,11 +718,12 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget get usersPanel => Obx(() =>
|
Widget get usersPanel => Obx(() => controller.users.isEmpty
|
||||||
controller.users.isEmpty ? whenNoSomething("No users found") : cardList);
|
? whenNoSomething("Пользователи не найдены")
|
||||||
|
: cardList);
|
||||||
|
|
||||||
Widget get groupsPanel => Obx(() => controller.groups.isEmpty
|
Widget get groupsPanel => Obx(() => controller.groups.isEmpty
|
||||||
? whenNoSomething("No groups found")
|
? whenNoSomething("Группы не найдены")
|
||||||
: groupsList);
|
: groupsList);
|
||||||
|
|
||||||
Widget whenNoSomething(message) => Center(
|
Widget whenNoSomething(message) => Center(
|
||||||
|
|
@ -785,7 +783,7 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
onPressed: () => controller.editUser(user),
|
onPressed: () => controller.editUser(user),
|
||||||
icon: const Icon(Icons.edit_attributes),
|
icon: const Icon(Icons.edit_attributes),
|
||||||
label: const Text("Edit user"),
|
label: const Text("Редактировать"),
|
||||||
).paddingAll(8).expanded(),
|
).paddingAll(8).expanded(),
|
||||||
Obx(
|
Obx(
|
||||||
() {
|
() {
|
||||||
|
|
@ -807,7 +805,7 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
final btn = ElevatedButton.icon(
|
final btn = ElevatedButton.icon(
|
||||||
onPressed: () => controller.deleteUser(user),
|
onPressed: () => controller.deleteUser(user),
|
||||||
icon: const Icon(Icons.delete_forever),
|
icon: const Icon(Icons.delete_forever),
|
||||||
label: const Text("Delete user"),
|
label: const Text("Удалить"),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.redAccent,
|
backgroundColor: Colors.redAccent,
|
||||||
),
|
),
|
||||||
|
|
@ -815,7 +813,7 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
|
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: "Please note that this user is an admin",
|
message: "Данный пользователь является администратором",
|
||||||
child: btn,
|
child: btn,
|
||||||
).paddingAll(8).expanded();
|
).paddingAll(8).expanded();
|
||||||
}
|
}
|
||||||
|
|
@ -876,7 +874,7 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
final groupData = controller.usersInGroups[group];
|
final groupData = controller.usersInGroups[group];
|
||||||
if (group.id == 1) {
|
if (group.id == 1) {
|
||||||
return const ListTile(
|
return const ListTile(
|
||||||
title: Text("No users can be added to this group"),
|
title: Text("В эту группу нельзя добавить пользователей"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (groupData == null) {
|
if (groupData == null) {
|
||||||
|
|
@ -886,7 +884,7 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
}
|
}
|
||||||
if (groupData.isEmpty) {
|
if (groupData.isEmpty) {
|
||||||
return const ListTile(
|
return const ListTile(
|
||||||
title: Text("No users in group"),
|
title: Text("В группе нет пользователей"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
|
@ -897,7 +895,7 @@ class UsersListPanel extends GetView<UserListPanelController> {
|
||||||
final isYou = user.accessToken == ApiController.to.token;
|
final isYou = user.accessToken == ApiController.to.token;
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(user.username),
|
title: Text(user.username),
|
||||||
subtitle: isYou ? const Text("You") : null,
|
subtitle: isYou ? const Text("Вы") : null,
|
||||||
trailing: isYou &&
|
trailing: isYou &&
|
||||||
(group.id == 2 ||
|
(group.id == 2 ||
|
||||||
group.name.toLowerCase() == "admin")
|
group.name.toLowerCase() == "admin")
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ class LoginPageController extends GetxController {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Login failed",
|
"Ошибка входа",
|
||||||
resp.statusMessage ?? "Unknown error",
|
resp.statusMessage ?? "Неизвестная ошибка",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
|
|
@ -57,19 +57,19 @@ class LoginPageController extends GetxController {
|
||||||
final error = errorData["error"];
|
final error = errorData["error"];
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Login failed",
|
"Ошибка входа",
|
||||||
"$error",
|
"$error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Login failed",
|
"Ошибка входа",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
"Login failed",
|
"Ошибка входа",
|
||||||
"$e",
|
"$e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -109,14 +109,14 @@ class LoginPage extends GetView<LoginPageController> {
|
||||||
TextFormField(
|
TextFormField(
|
||||||
enabled: !controller.submitted,
|
enabled: !controller.submitted,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Endpoint',
|
labelText: 'Адрес бэкенда',
|
||||||
hintText: 'Enter Tuuli Endpoint',
|
hintText: 'Введите адрес бэкенда Tuuli',
|
||||||
),
|
),
|
||||||
initialValue: ApiController.to.endPoint,
|
initialValue: ApiController.to.endPoint,
|
||||||
onChanged: (value) => controller.endpoint = value,
|
onChanged: (value) => controller.endpoint = value,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter Tuuli Endpoint';
|
return 'Пожалуйста, введите адрес бэкенда Tuuli';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
@ -124,13 +124,13 @@ class LoginPage extends GetView<LoginPageController> {
|
||||||
TextFormField(
|
TextFormField(
|
||||||
enabled: !controller.submitted,
|
enabled: !controller.submitted,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Login',
|
labelText: 'Логин',
|
||||||
hintText: 'Enter your username',
|
hintText: 'Введите логин',
|
||||||
),
|
),
|
||||||
onChanged: (value) => controller.username = value,
|
onChanged: (value) => controller.username = value,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your Login';
|
return 'Пожалуйста, введите логин';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
@ -139,13 +139,13 @@ class LoginPage extends GetView<LoginPageController> {
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
enabled: !controller.submitted,
|
enabled: !controller.submitted,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Пароль',
|
||||||
hintText: 'Enter your password',
|
hintText: 'Введите пароль',
|
||||||
),
|
),
|
||||||
onChanged: (value) => controller.password = value,
|
onChanged: (value) => controller.password = value,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your password';
|
return 'Пожалуйста, введите пароль';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
@ -156,7 +156,7 @@ class LoginPage extends GetView<LoginPageController> {
|
||||||
!controller.isFormValid || controller.submitted
|
!controller.isFormValid || controller.submitted
|
||||||
? null
|
? null
|
||||||
: () => controller.submitForm(),
|
: () => controller.submitForm(),
|
||||||
child: const Text('Login'),
|
child: const Text('Войти'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class _NotFoundPageState extends State<NotFoundPage>
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Page not found',
|
'Страница не найдена',
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -30,14 +30,14 @@ class _NotFoundPageState extends State<NotFoundPage>
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(canPop: false);
|
Get.back(canPop: false);
|
||||||
},
|
},
|
||||||
child: const Text('Go back'),
|
child: const Text('Назад'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.offAllNamed("/");
|
Get.offAllNamed("/");
|
||||||
},
|
},
|
||||||
child: const Text('Go home'),
|
child: const Text('Домой'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class AudioPlayerWidget extends GetView<AudioPlayerWidgetController> {
|
||||||
icon: const Icon(Icons.play_arrow),
|
icon: const Icon(Icons.play_arrow),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: const Text("Playing"),
|
title: const Text("Проигрывается"),
|
||||||
subtitle: Text(controller.title),
|
subtitle: Text(controller.title),
|
||||||
).card().paddingAll(16).center();
|
).card().paddingAll(16).center();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Future<String?> showStringInputDialog({String? originalValue}) async {
|
||||||
final strVal = (originalValue ?? "").obs;
|
final strVal = (originalValue ?? "").obs;
|
||||||
return await Get.dialog<String>(
|
return await Get.dialog<String>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Enter a string"),
|
title: const Text("Введите строку"),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
controller: TextEditingController(text: originalValue),
|
controller: TextEditingController(text: originalValue),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
|
@ -18,13 +18,13 @@ Future<String?> showStringInputDialog({String? originalValue}) async {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: null);
|
Get.back(result: null);
|
||||||
},
|
},
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: strVal.value);
|
Get.back(result: strVal.value);
|
||||||
},
|
},
|
||||||
child: const Text("OK"),
|
child: const Text("Ок"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -35,7 +35,7 @@ Future<double?> showDoubleInputDialog({double? originalValue}) async {
|
||||||
final strVal = (originalValue?.toString() ?? "").obs;
|
final strVal = (originalValue?.toString() ?? "").obs;
|
||||||
return await Get.dialog<double>(
|
return await Get.dialog<double>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Enter a number"),
|
title: const Text("Введите плавающее число"),
|
||||||
content: FastTextField(
|
content: FastTextField(
|
||||||
name: "Number",
|
name: "Number",
|
||||||
initialValue: originalValue?.toString(),
|
initialValue: originalValue?.toString(),
|
||||||
|
|
@ -43,11 +43,11 @@ Future<double?> showDoubleInputDialog({double? originalValue}) async {
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return "Please enter a number";
|
return "Пожалуйста, введите плавающее число";
|
||||||
}
|
}
|
||||||
final parsed = double.tryParse(value);
|
final parsed = double.tryParse(value);
|
||||||
if (parsed == null) {
|
if (parsed == null) {
|
||||||
return "Please enter a valid number";
|
return "Пожалуйста, введите настоящее плавающее число";
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
@ -60,7 +60,7 @@ Future<double?> showDoubleInputDialog({double? originalValue}) async {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: null);
|
Get.back(result: null);
|
||||||
},
|
},
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|
@ -71,7 +71,7 @@ Future<double?> showDoubleInputDialog({double? originalValue}) async {
|
||||||
Get.back(result: null);
|
Get.back(result: null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Text("OK"),
|
child: const Text("Ок"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -82,7 +82,7 @@ Future<int?> showIntInputDialog({int? originalValue}) async {
|
||||||
final strVal = (originalValue?.toString() ?? "").obs;
|
final strVal = (originalValue?.toString() ?? "").obs;
|
||||||
return await Get.dialog<int>(
|
return await Get.dialog<int>(
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title: const Text("Enter a number"),
|
title: const Text("Введите целое число"),
|
||||||
content: FastTextField(
|
content: FastTextField(
|
||||||
name: "Number",
|
name: "Number",
|
||||||
initialValue: originalValue?.toString(),
|
initialValue: originalValue?.toString(),
|
||||||
|
|
@ -90,11 +90,11 @@ Future<int?> showIntInputDialog({int? originalValue}) async {
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return "Please enter a number";
|
return "Пожалуйста, введите целое число";
|
||||||
}
|
}
|
||||||
final parsed = int.tryParse(value);
|
final parsed = int.tryParse(value);
|
||||||
if (parsed == null) {
|
if (parsed == null) {
|
||||||
return "Please enter a valid number";
|
return "Пожалуйста, введите настоящее целое число";
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +107,7 @@ Future<int?> showIntInputDialog({int? originalValue}) async {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back(result: null);
|
Get.back(result: null);
|
||||||
},
|
},
|
||||||
child: const Text("Cancel"),
|
child: const Text("Отменить"),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|
@ -118,7 +118,7 @@ Future<int?> showIntInputDialog({int? originalValue}) async {
|
||||||
Get.back(result: null);
|
Get.back(result: null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Text("OK"),
|
child: const Text("Ок"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
16
pubspec.lock
16
pubspec.lock
|
|
@ -305,6 +305,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
flu_console:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flu_console
|
||||||
|
sha256: a6d9c70366fffd69c69f486677f86ec290dd72ca7cb1110271d6ddeda51ca769
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
@ -472,6 +480,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
logger:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logger
|
||||||
|
sha256: db2ff852ed77090ba9f62d3611e4208a3d11dfa35991a81ae724c113fcb3e3f7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ dependencies:
|
||||||
data_table_2: ^2.4.2
|
data_table_2: ^2.4.2
|
||||||
dio: ^5.1.1
|
dio: ^5.1.1
|
||||||
file_icon: ^1.0.0
|
file_icon: ^1.0.0
|
||||||
|
flu_console: ^0.0.1
|
||||||
flutter_chips_input: ^2.0.0
|
flutter_chips_input: ^2.0.0
|
||||||
flutter_fast_forms: ^10.0.0
|
flutter_fast_forms: ^10.0.0
|
||||||
get: ^4.6.5
|
get: ^4.6.5
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,15 @@
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||||
|
#include <flu_console/flu_console_plugin_c_api.h>
|
||||||
#include <irondash_engine_context/irondash_engine_context_plugin_c_api.h>
|
#include <irondash_engine_context/irondash_engine_context_plugin_c_api.h>
|
||||||
#include <super_native_extensions/super_native_extensions_plugin_c_api.h>
|
#include <super_native_extensions/super_native_extensions_plugin_c_api.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
AudioplayersWindowsPluginRegisterWithRegistrar(
|
AudioplayersWindowsPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
||||||
|
FluConsolePluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FluConsolePluginCApi"));
|
||||||
IrondashEngineContextPluginCApiRegisterWithRegistrar(
|
IrondashEngineContextPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("IrondashEngineContextPluginCApi"));
|
registry->GetRegistrarForPlugin("IrondashEngineContextPluginCApi"));
|
||||||
SuperNativeExtensionsPluginCApiRegisterWithRegistrar(
|
SuperNativeExtensionsPluginCApiRegisterWithRegistrar(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
audioplayers_windows
|
audioplayers_windows
|
||||||
|
flu_console
|
||||||
irondash_engine_context
|
irondash_engine_context
|
||||||
super_native_extensions
|
super_native_extensions
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue