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