Fix conflicts and issues.

This commit is contained in:
Igor Kulikov
2022-08-12 15:13:53 +03:00
23 changed files with 1482 additions and 87 deletions

View File

@@ -43,7 +43,7 @@ const tbDarkMatIndigo = MaterialColor(
},
);
final ThemeData theme = ThemeData();
final ThemeData theme = ThemeData(primarySwatch: tbMatIndigo);
ThemeData tbTheme = ThemeData(
primarySwatch: tbMatIndigo,
@@ -73,7 +73,10 @@ ThemeData tbTheme = ThemeData(
TargetPlatform.android: FadeOpenPageTransitionsBuilder(),
}));
final ThemeData darkTheme =
ThemeData(primarySwatch: tbDarkMatIndigo, brightness: Brightness.dark);
ThemeData tbDarkTheme = ThemeData(
primarySwatch: tbDarkMatIndigo,
colorScheme: theme.colorScheme.copyWith(secondary: Colors.deepOrange),
colorScheme: darkTheme.colorScheme.copyWith(secondary: Colors.deepOrange),
brightness: Brightness.dark);

View File

@@ -8,6 +8,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
import 'package:thingsboard_app/constants/assets_path.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/widgets/tb_progress_indicator.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
@@ -67,11 +68,12 @@ class _LoginPageState extends TbPageState<LoginPage> {
ThingsboardImage.thingsBoardWithTitle,
height: 25,
color: Theme.of(context).primaryColor,
semanticsLabel: 'ThingsBoard Logo')
semanticsLabel:
'${S.of(context).logoDefaultValue}')
]),
SizedBox(height: 32),
Row(children: [
Text('Login to your account',
Text('${S.of(context).loginNotification}',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 28,
@@ -91,7 +93,7 @@ class _LoginPageState extends TbPageState<LoginPage> {
Padding(
padding: EdgeInsets.symmetric(
horizontal: 16),
child: Text('OR'),
child: Text('${S.of(context).OR}'),
),
Flexible(child: Divider())
],
@@ -108,14 +110,16 @@ class _LoginPageState extends TbPageState<LoginPage> {
validator:
FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText: 'Email is required.'),
errorText:
'${S.of(context).emailRequireText}'),
FormBuilderValidators.email(
errorText:
'Invalid email format.')
'${S.of(context).emailInvalidText}')
]),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email'),
labelText:
'${S.of(context).email}'),
),
SizedBox(height: 28),
ValueListenableBuilder(
@@ -130,7 +134,7 @@ class _LoginPageState extends TbPageState<LoginPage> {
.compose([
FormBuilderValidators.required(
errorText:
'Password is required.')
'${S.of(context).passwordRequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -145,7 +149,8 @@ class _LoginPageState extends TbPageState<LoginPage> {
},
),
border: OutlineInputBorder(),
labelText: 'Password'),
labelText:
'${S.of(context).password}'),
);
})
],
@@ -158,7 +163,7 @@ class _LoginPageState extends TbPageState<LoginPage> {
_forgotPassword();
},
child: Text(
'Forgot Password?',
'${S.of(context).passwordForgotText}',
style: TextStyle(
color: Theme.of(context)
.colorScheme
@@ -172,7 +177,7 @@ class _LoginPageState extends TbPageState<LoginPage> {
),
Spacer(),
ElevatedButton(
child: Text('Log In'),
child: Text('${S.of(context).login}'),
style: ElevatedButton.styleFrom(
padding:
EdgeInsets.symmetric(vertical: 16)),

View File

@@ -4,6 +4,7 @@ import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:thingsboard_app/core/auth/login/login_page_background.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
import 'package:thingsboard_app/widgets/tb_progress_indicator.dart';
@@ -31,7 +32,7 @@ class _ResetPasswordRequestPageState
backgroundColor: Colors.transparent,
appBar: TbAppBar(
tbContext,
title: Text('Reset password'),
title: Text('${S.of(context).passwordReset}'),
),
body: Stack(children: [
SizedBox.expand(
@@ -45,7 +46,7 @@ class _ResetPasswordRequestPageState
children: [
SizedBox(height: 16),
Text(
'Enter the email associated with your account and we\'ll send an email with password reset link',
'${S.of(context).passwordResetText}',
textAlign: TextAlign.center,
style: TextStyle(
color: Color(0xFFAFAFAF),
@@ -58,17 +59,20 @@ class _ResetPasswordRequestPageState
autofocus: true,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText: 'Email is required.'),
errorText:
'${S.of(context).emailRequireText}'),
FormBuilderValidators.email(
errorText: 'Invalid email format.')
errorText:
'${S.of(context).emailInvalidText}')
]),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email *'),
labelText: '${S.of(context).email} *'),
),
Spacer(),
ElevatedButton(
child: Text('Request password reset'),
child: Text(
'${S.of(context).requestPasswordReset}'),
style: ElevatedButton.styleFrom(
padding:
EdgeInsets.symmetric(vertical: 16)),
@@ -104,7 +108,8 @@ class _ResetPasswordRequestPageState
await Future.delayed(Duration(milliseconds: 300));
await tbClient.sendResetPasswordLink(email);
_isLoadingNotifier.value = false;
showSuccessNotification('Password reset link was successfully sent!');
showSuccessNotification(
'${S.of(context).passwordResetLinkSuccessfullySentNotification}');
} catch (e) {
_isLoadingNotifier.value = false;
}

View File

@@ -5,6 +5,7 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:intl/intl.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/utils.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
@@ -54,15 +55,15 @@ mixin EntitiesBase<T, P> on HasTbContext {
Key? getKey(T entity) => null;
Widget buildEntityListCard(BuildContext context, T entity) {
return Text('Not implemented!');
return Text('${S.of(context).notImplemented}');
}
Widget buildEntityListWidgetCard(BuildContext context, T entity) {
return Text('Not implemented!');
return Text('${S.of(context).notImplemented}');
}
Widget buildEntityGridCard(BuildContext context, T entity) {
return Text('Not implemented!');
return Text('${S.of(context).notImplemented}');
}
double? gridChildAspectRatio() => null;
@@ -337,7 +338,7 @@ abstract class BaseEntitiesState<T, P>
Widget noItemsFoundIndicatorBuilder(BuildContext context) {
return FirstPageExceptionIndicator(
title: widget.noItemsFoundText,
message: 'The list is currently empty.',
message: '${S.of(context).listIsEmptyText}',
onTryAgain: widget.searchMode ? null : () => pagingController.refresh(),
);
}
@@ -391,8 +392,8 @@ class FirstPageExceptionIndicator extends StatelessWidget {
Icons.refresh,
color: Colors.white,
),
label: const Text(
'Try Again',
label: Text(
'${S.of(context).tryAgain}',
style: TextStyle(
fontSize: 16,
color: Colors.white,

View File

@@ -0,0 +1,66 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that looks up messages for specific locales by
// delegating to the appropriate library.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:implementation_imports, file_names, unnecessary_new
// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering
// ignore_for_file:argument_type_not_assignable, invalid_assignment
// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases
// ignore_for_file:comment_references
import 'dart:async';
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
import 'package:intl/src/intl_helpers.dart';
import 'messages_en.dart' as messages_en;
import 'messages_zh.dart' as messages_zh;
typedef Future<dynamic> LibraryLoader();
Map<String, LibraryLoader> _deferredLibraries = {
'en': () => new Future.value(null),
'zh': () => new Future.value(null),
};
MessageLookupByLibrary? _findExact(String localeName) {
switch (localeName) {
case 'en':
return messages_en.messages;
case 'zh':
return messages_zh.messages;
default:
return null;
}
}
/// User programs should call this before using [localeName] for messages.
Future<bool> initializeMessages(String localeName) async {
var availableLocale = Intl.verifiedLocale(
localeName, (locale) => _deferredLibraries[locale] != null,
onFailure: (_) => null);
if (availableLocale == null) {
return new Future.value(false);
}
var lib = _deferredLibraries[availableLocale];
await (lib == null ? new Future.value(false) : lib());
initializeInternalMessageLookup(() => new CompositeMessageLookup());
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
return new Future.value(true);
}
bool _messagesExistFor(String locale) {
try {
return _findExact(locale) != null;
} catch (e) {
return false;
}
}
MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
var actualLocale =
Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null);
if (actualLocale == null) return null;
return _findExact(actualLocale);
}

View File

@@ -0,0 +1,131 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a en locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = new MessageLookup();
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'en';
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"No": MessageLookupByLibrary.simpleMessage("No"),
"OR": MessageLookupByLibrary.simpleMessage("OR"),
"Yes": MessageLookupByLibrary.simpleMessage("Yes"),
"actionData": MessageLookupByLibrary.simpleMessage("Action data"),
"active": MessageLookupByLibrary.simpleMessage("Active"),
"address": MessageLookupByLibrary.simpleMessage("Address"),
"address2": MessageLookupByLibrary.simpleMessage("Address 2"),
"alarmAcknowledgeText": MessageLookupByLibrary.simpleMessage(
"Are you sure you want to acknowledge Alarm?"),
"alarmAcknowledgeTitle":
MessageLookupByLibrary.simpleMessage("Acknowledge Alarm"),
"alarmClearText": MessageLookupByLibrary.simpleMessage(
"Are you sure you want to clear Alarm?"),
"alarmClearTitle": MessageLookupByLibrary.simpleMessage("Clear Alarm"),
"alarms": MessageLookupByLibrary.simpleMessage("Alarms"),
"allDevices": MessageLookupByLibrary.simpleMessage("All devices"),
"appTitle": MessageLookupByLibrary.simpleMessage("Thingsboard"),
"assetName": MessageLookupByLibrary.simpleMessage("Asset name"),
"assets": MessageLookupByLibrary.simpleMessage("Assets"),
"assignedToCustomer":
MessageLookupByLibrary.simpleMessage("Assigned to customer"),
"auditLogDetails":
MessageLookupByLibrary.simpleMessage("Audit log details"),
"auditLogs": MessageLookupByLibrary.simpleMessage("Audit Logs"),
"changePassword":
MessageLookupByLibrary.simpleMessage("Change Password"),
"city": MessageLookupByLibrary.simpleMessage("City"),
"country": MessageLookupByLibrary.simpleMessage("Country"),
"currentPassword":
MessageLookupByLibrary.simpleMessage("currentPassword"),
"currentPasswordRequireText": MessageLookupByLibrary.simpleMessage(
"Current password is required."),
"currentPasswordStar":
MessageLookupByLibrary.simpleMessage("Current password *"),
"customer": MessageLookupByLibrary.simpleMessage("Customer"),
"customers": MessageLookupByLibrary.simpleMessage("Customers"),
"devices": MessageLookupByLibrary.simpleMessage("Devices"),
"email": MessageLookupByLibrary.simpleMessage("Email"),
"emailInvalidText":
MessageLookupByLibrary.simpleMessage("Invalid email format."),
"emailRequireText":
MessageLookupByLibrary.simpleMessage("Email is required."),
"emailStar": MessageLookupByLibrary.simpleMessage("Email *"),
"entityType": MessageLookupByLibrary.simpleMessage("Entity Type"),
"failureDetails":
MessageLookupByLibrary.simpleMessage("Failure details"),
"firstName": MessageLookupByLibrary.simpleMessage("firstName"),
"firstNameUpper": MessageLookupByLibrary.simpleMessage("First Name"),
"home": MessageLookupByLibrary.simpleMessage("Home"),
"inactive": MessageLookupByLibrary.simpleMessage("Inactive"),
"label": MessageLookupByLibrary.simpleMessage("Label"),
"lastName": MessageLookupByLibrary.simpleMessage("lastName"),
"lastNameUpper": MessageLookupByLibrary.simpleMessage("Last Name"),
"listIsEmptyText": MessageLookupByLibrary.simpleMessage(
"The list is currently empty."),
"login": MessageLookupByLibrary.simpleMessage("Log In"),
"loginNotification":
MessageLookupByLibrary.simpleMessage("Login to your account"),
"logoDefaultValue":
MessageLookupByLibrary.simpleMessage("Thingsboard Logo"),
"logout": MessageLookupByLibrary.simpleMessage("Log Out"),
"more": MessageLookupByLibrary.simpleMessage("More"),
"newPassword": MessageLookupByLibrary.simpleMessage("newPassword"),
"newPassword2": MessageLookupByLibrary.simpleMessage("newPassword2"),
"newPassword2RequireText": MessageLookupByLibrary.simpleMessage(
"New password again is required."),
"newPassword2Star":
MessageLookupByLibrary.simpleMessage("New password again *"),
"newPasswordRequireText":
MessageLookupByLibrary.simpleMessage("New password is required."),
"newPasswordStar":
MessageLookupByLibrary.simpleMessage("New password *"),
"notImplemented":
MessageLookupByLibrary.simpleMessage("Not implemented!"),
"password": MessageLookupByLibrary.simpleMessage("Password"),
"passwordErrorNotification": MessageLookupByLibrary.simpleMessage(
"Entered passwords must be same!"),
"passwordForgotText":
MessageLookupByLibrary.simpleMessage("Forgot Password?"),
"passwordRequireText":
MessageLookupByLibrary.simpleMessage("Password is required."),
"passwordReset": MessageLookupByLibrary.simpleMessage("Reset password"),
"passwordResetLinkSuccessfullySentNotification":
MessageLookupByLibrary.simpleMessage(
"Password reset link was successfully sent!"),
"passwordResetText": MessageLookupByLibrary.simpleMessage(
"Enter the email associated with your account and we\'ll send an email with password reset link"),
"passwordSuccessNotification": MessageLookupByLibrary.simpleMessage(
"Password successfully changed"),
"phone": MessageLookupByLibrary.simpleMessage("Phone"),
"postalCode": MessageLookupByLibrary.simpleMessage("Zip / Postal Code"),
"profileSuccessNotification": MessageLookupByLibrary.simpleMessage(
"Profile successfully updated"),
"requestPasswordReset":
MessageLookupByLibrary.simpleMessage("Request password reset"),
"stateOrProvince":
MessageLookupByLibrary.simpleMessage("State / Province"),
"systemAdministrator":
MessageLookupByLibrary.simpleMessage("System Administrator"),
"tenantAdministrator":
MessageLookupByLibrary.simpleMessage("Tenant Administrator"),
"title": MessageLookupByLibrary.simpleMessage("Title"),
"tryAgain": MessageLookupByLibrary.simpleMessage("Try Again"),
"type": MessageLookupByLibrary.simpleMessage("Type"),
"username": MessageLookupByLibrary.simpleMessage("username")
};
}

View File

@@ -0,0 +1,107 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a zh locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = new MessageLookup();
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'zh';
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"No": MessageLookupByLibrary.simpleMessage(""),
"OR": MessageLookupByLibrary.simpleMessage(""),
"Yes": MessageLookupByLibrary.simpleMessage(""),
"actionData": MessageLookupByLibrary.simpleMessage("动作数据"),
"active": MessageLookupByLibrary.simpleMessage("激活"),
"address": MessageLookupByLibrary.simpleMessage("地址"),
"address2": MessageLookupByLibrary.simpleMessage("地址 2"),
"alarmAcknowledgeText":
MessageLookupByLibrary.simpleMessage("你确定要确认告警吗?"),
"alarmAcknowledgeTitle": MessageLookupByLibrary.simpleMessage("确认告警"),
"alarmClearText": MessageLookupByLibrary.simpleMessage("你确定要清除告警吗?"),
"alarmClearTitle": MessageLookupByLibrary.simpleMessage("清除告警"),
"alarms": MessageLookupByLibrary.simpleMessage("告警"),
"allDevices": MessageLookupByLibrary.simpleMessage("所有设备"),
"appTitle": MessageLookupByLibrary.simpleMessage("Thingsboard"),
"assetName": MessageLookupByLibrary.simpleMessage("资产名"),
"assignedToCustomer": MessageLookupByLibrary.simpleMessage("分配给客户"),
"auditLogDetails": MessageLookupByLibrary.simpleMessage("审计日志详情"),
"auditLogs": MessageLookupByLibrary.simpleMessage("审计报告"),
"changePassword": MessageLookupByLibrary.simpleMessage("修改密码"),
"city": MessageLookupByLibrary.simpleMessage("城市"),
"country": MessageLookupByLibrary.simpleMessage("国家"),
"currentPassword": MessageLookupByLibrary.simpleMessage("当前密码"),
"currentPasswordRequireText":
MessageLookupByLibrary.simpleMessage("输入当前密码"),
"currentPasswordStar": MessageLookupByLibrary.simpleMessage("当前密码 *"),
"customer": MessageLookupByLibrary.simpleMessage("客户"),
"customers": MessageLookupByLibrary.simpleMessage("客户"),
"devices": MessageLookupByLibrary.simpleMessage("设备"),
"email": MessageLookupByLibrary.simpleMessage("Email"),
"emailInvalidText": MessageLookupByLibrary.simpleMessage("Email格式错误"),
"emailRequireText": MessageLookupByLibrary.simpleMessage("输入Email"),
"emailStar": MessageLookupByLibrary.simpleMessage("Email *"),
"entityType": MessageLookupByLibrary.simpleMessage("实体类型"),
"failureDetails": MessageLookupByLibrary.simpleMessage("失败详情"),
"firstName": MessageLookupByLibrary.simpleMessage(""),
"firstNameUpper": MessageLookupByLibrary.simpleMessage(""),
"home": MessageLookupByLibrary.simpleMessage("主页"),
"inactive": MessageLookupByLibrary.simpleMessage("失活"),
"label": MessageLookupByLibrary.simpleMessage("标签"),
"lastName": MessageLookupByLibrary.simpleMessage(""),
"lastNameUpper": MessageLookupByLibrary.simpleMessage(""),
"listIsEmptyText": MessageLookupByLibrary.simpleMessage("列表当前为空"),
"login": MessageLookupByLibrary.simpleMessage("登录"),
"loginNotification": MessageLookupByLibrary.simpleMessage("登录你的账号"),
"logoDefaultValue":
MessageLookupByLibrary.simpleMessage("Thingsboard Logo"),
"logout": MessageLookupByLibrary.simpleMessage("登出"),
"more": MessageLookupByLibrary.simpleMessage("更多"),
"newPassword": MessageLookupByLibrary.simpleMessage("新密码"),
"newPassword2": MessageLookupByLibrary.simpleMessage("新密码2"),
"newPassword2RequireText":
MessageLookupByLibrary.simpleMessage("再次输入新密码"),
"newPassword2Star": MessageLookupByLibrary.simpleMessage("再次输入新密码 *"),
"newPasswordRequireText": MessageLookupByLibrary.simpleMessage("输入新密码"),
"newPasswordStar": MessageLookupByLibrary.simpleMessage("新密码 *"),
"notImplemented": MessageLookupByLibrary.simpleMessage("未实现!"),
"password": MessageLookupByLibrary.simpleMessage("密码"),
"passwordErrorNotification":
MessageLookupByLibrary.simpleMessage("输入的密码必须相同"),
"passwordForgotText": MessageLookupByLibrary.simpleMessage("忘记密码?"),
"passwordRequireText": MessageLookupByLibrary.simpleMessage("输入密码"),
"passwordReset": MessageLookupByLibrary.simpleMessage("重置密码"),
"passwordResetLinkSuccessfullySentNotification":
MessageLookupByLibrary.simpleMessage("密码重置链接已发送"),
"passwordResetText": MessageLookupByLibrary.simpleMessage(
"输入和账号关联的Email我们将发送一个密码重置链接到的Email"),
"passwordSuccessNotification":
MessageLookupByLibrary.simpleMessage("密码修改成功"),
"phone": MessageLookupByLibrary.simpleMessage("电话"),
"postalCode": MessageLookupByLibrary.simpleMessage("邮编"),
"profileSuccessNotification":
MessageLookupByLibrary.simpleMessage("配置更新成功"),
"requestPasswordReset": MessageLookupByLibrary.simpleMessage("要求重置密码"),
"stateOrProvince": MessageLookupByLibrary.simpleMessage("州 / 省"),
"systemAdministrator": MessageLookupByLibrary.simpleMessage("系统管理员"),
"tenantAdministrator": MessageLookupByLibrary.simpleMessage("租户管理员"),
"title": MessageLookupByLibrary.simpleMessage("标题"),
"tryAgain": MessageLookupByLibrary.simpleMessage("再试一次"),
"type": MessageLookupByLibrary.simpleMessage("类型"),
"username": MessageLookupByLibrary.simpleMessage("用户名")
};
}

809
lib/generated/l10n.dart Normal file
View File

@@ -0,0 +1,809 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'intl/messages_all.dart';
// **************************************************************************
// Generator: Flutter Intl IDE plugin
// Made by Localizely
// **************************************************************************
// ignore_for_file: non_constant_identifier_names, lines_longer_than_80_chars
// ignore_for_file: join_return_with_assignment, prefer_final_in_for_each
// ignore_for_file: avoid_redundant_argument_values, avoid_escaping_inner_quotes
class S {
S();
static S? _current;
static S get current {
assert(_current != null,
'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.');
return _current!;
}
static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
static Future<S> load(Locale locale) {
final name = (locale.countryCode?.isEmpty ?? false)
? locale.languageCode
: locale.toString();
final localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((_) {
Intl.defaultLocale = localeName;
final instance = S();
S._current = instance;
return instance;
});
}
static S of(BuildContext context) {
final instance = S.maybeOf(context);
assert(instance != null,
'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?');
return instance!;
}
static S? maybeOf(BuildContext context) {
return Localizations.of<S>(context, S);
}
/// `Thingsboard`
String get appTitle {
return Intl.message(
'Thingsboard',
name: 'appTitle',
desc: '',
args: [],
);
}
/// `Home`
String get home {
return Intl.message(
'Home',
name: 'home',
desc: '',
args: [],
);
}
/// `Alarms`
String get alarms {
return Intl.message(
'Alarms',
name: 'alarms',
desc: '',
args: [],
);
}
/// `Devices`
String get devices {
return Intl.message(
'Devices',
name: 'devices',
desc: '',
args: [],
);
}
/// `More`
String get more {
return Intl.message(
'More',
name: 'more',
desc: '',
args: [],
);
}
/// `Customers`
String get customers {
return Intl.message(
'Customers',
name: 'customers',
desc: '',
args: [],
);
}
/// `Assets`
String get assets {
return Intl.message(
'Assets',
name: 'assets',
desc: '',
args: [],
);
}
/// `Audit Logs`
String get auditLogs {
return Intl.message(
'Audit Logs',
name: 'auditLogs',
desc: '',
args: [],
);
}
/// `Log Out`
String get logout {
return Intl.message(
'Log Out',
name: 'logout',
desc: '',
args: [],
);
}
/// `Log In`
String get login {
return Intl.message(
'Log In',
name: 'login',
desc: '',
args: [],
);
}
/// `Thingsboard Logo`
String get logoDefaultValue {
return Intl.message(
'Thingsboard Logo',
name: 'logoDefaultValue',
desc: '',
args: [],
);
}
/// `Login to your account`
String get loginNotification {
return Intl.message(
'Login to your account',
name: 'loginNotification',
desc: '',
args: [],
);
}
/// `Email`
String get email {
return Intl.message(
'Email',
name: 'email',
desc: '',
args: [],
);
}
/// `Email is required.`
String get emailRequireText {
return Intl.message(
'Email is required.',
name: 'emailRequireText',
desc: '',
args: [],
);
}
/// `Invalid email format.`
String get emailInvalidText {
return Intl.message(
'Invalid email format.',
name: 'emailInvalidText',
desc: '',
args: [],
);
}
/// `username`
String get username {
return Intl.message(
'username',
name: 'username',
desc: '',
args: [],
);
}
/// `Password`
String get password {
return Intl.message(
'Password',
name: 'password',
desc: '',
args: [],
);
}
/// `Password is required.`
String get passwordRequireText {
return Intl.message(
'Password is required.',
name: 'passwordRequireText',
desc: '',
args: [],
);
}
/// `Forgot Password?`
String get passwordForgotText {
return Intl.message(
'Forgot Password?',
name: 'passwordForgotText',
desc: '',
args: [],
);
}
/// `Reset password`
String get passwordReset {
return Intl.message(
'Reset password',
name: 'passwordReset',
desc: '',
args: [],
);
}
/// `Enter the email associated with your account and we'll send an email with password reset link`
String get passwordResetText {
return Intl.message(
'Enter the email associated with your account and we\'ll send an email with password reset link',
name: 'passwordResetText',
desc: '',
args: [],
);
}
/// `Request password reset`
String get requestPasswordReset {
return Intl.message(
'Request password reset',
name: 'requestPasswordReset',
desc: '',
args: [],
);
}
/// `Password reset link was successfully sent!`
String get passwordResetLinkSuccessfullySentNotification {
return Intl.message(
'Password reset link was successfully sent!',
name: 'passwordResetLinkSuccessfullySentNotification',
desc: '',
args: [],
);
}
/// `OR`
String get OR {
return Intl.message(
'OR',
name: 'OR',
desc: '',
args: [],
);
}
/// `No`
String get No {
return Intl.message(
'No',
name: 'No',
desc: '',
args: [],
);
}
/// `Yes`
String get Yes {
return Intl.message(
'Yes',
name: 'Yes',
desc: '',
args: [],
);
}
/// `Title`
String get title {
return Intl.message(
'Title',
name: 'title',
desc: '',
args: [],
);
}
/// `Country`
String get country {
return Intl.message(
'Country',
name: 'country',
desc: '',
args: [],
);
}
/// `City`
String get city {
return Intl.message(
'City',
name: 'city',
desc: '',
args: [],
);
}
/// `State / Province`
String get stateOrProvince {
return Intl.message(
'State / Province',
name: 'stateOrProvince',
desc: '',
args: [],
);
}
/// `Zip / Postal Code`
String get postalCode {
return Intl.message(
'Zip / Postal Code',
name: 'postalCode',
desc: '',
args: [],
);
}
/// `Address`
String get address {
return Intl.message(
'Address',
name: 'address',
desc: '',
args: [],
);
}
/// `Address 2`
String get address2 {
return Intl.message(
'Address 2',
name: 'address2',
desc: '',
args: [],
);
}
/// `Phone`
String get phone {
return Intl.message(
'Phone',
name: 'phone',
desc: '',
args: [],
);
}
/// `Clear Alarm`
String get alarmClearTitle {
return Intl.message(
'Clear Alarm',
name: 'alarmClearTitle',
desc: '',
args: [],
);
}
/// `Are you sure you want to clear Alarm?`
String get alarmClearText {
return Intl.message(
'Are you sure you want to clear Alarm?',
name: 'alarmClearText',
desc: '',
args: [],
);
}
/// `Acknowledge Alarm`
String get alarmAcknowledgeTitle {
return Intl.message(
'Acknowledge Alarm',
name: 'alarmAcknowledgeTitle',
desc: '',
args: [],
);
}
/// `Are you sure you want to acknowledge Alarm?`
String get alarmAcknowledgeText {
return Intl.message(
'Are you sure you want to acknowledge Alarm?',
name: 'alarmAcknowledgeText',
desc: '',
args: [],
);
}
/// `Asset name`
String get assetName {
return Intl.message(
'Asset name',
name: 'assetName',
desc: '',
args: [],
);
}
/// `Type`
String get type {
return Intl.message(
'Type',
name: 'type',
desc: '',
args: [],
);
}
/// `Label`
String get label {
return Intl.message(
'Label',
name: 'label',
desc: '',
args: [],
);
}
/// `Assigned to customer`
String get assignedToCustomer {
return Intl.message(
'Assigned to customer',
name: 'assignedToCustomer',
desc: '',
args: [],
);
}
/// `Audit log details`
String get auditLogDetails {
return Intl.message(
'Audit log details',
name: 'auditLogDetails',
desc: '',
args: [],
);
}
/// `Entity Type`
String get entityType {
return Intl.message(
'Entity Type',
name: 'entityType',
desc: '',
args: [],
);
}
/// `Action data`
String get actionData {
return Intl.message(
'Action data',
name: 'actionData',
desc: '',
args: [],
);
}
/// `Failure details`
String get failureDetails {
return Intl.message(
'Failure details',
name: 'failureDetails',
desc: '',
args: [],
);
}
/// `All devices`
String get allDevices {
return Intl.message(
'All devices',
name: 'allDevices',
desc: '',
args: [],
);
}
/// `Active`
String get active {
return Intl.message(
'Active',
name: 'active',
desc: '',
args: [],
);
}
/// `Inactive`
String get inactive {
return Intl.message(
'Inactive',
name: 'inactive',
desc: '',
args: [],
);
}
/// `System Administrator`
String get systemAdministrator {
return Intl.message(
'System Administrator',
name: 'systemAdministrator',
desc: '',
args: [],
);
}
/// `Tenant Administrator`
String get tenantAdministrator {
return Intl.message(
'Tenant Administrator',
name: 'tenantAdministrator',
desc: '',
args: [],
);
}
/// `Customer`
String get customer {
return Intl.message(
'Customer',
name: 'customer',
desc: '',
args: [],
);
}
/// `Change Password`
String get changePassword {
return Intl.message(
'Change Password',
name: 'changePassword',
desc: '',
args: [],
);
}
/// `currentPassword`
String get currentPassword {
return Intl.message(
'currentPassword',
name: 'currentPassword',
desc: '',
args: [],
);
}
/// `Current password is required.`
String get currentPasswordRequireText {
return Intl.message(
'Current password is required.',
name: 'currentPasswordRequireText',
desc: '',
args: [],
);
}
/// `Current password *`
String get currentPasswordStar {
return Intl.message(
'Current password *',
name: 'currentPasswordStar',
desc: '',
args: [],
);
}
/// `newPassword`
String get newPassword {
return Intl.message(
'newPassword',
name: 'newPassword',
desc: '',
args: [],
);
}
/// `New password is required.`
String get newPasswordRequireText {
return Intl.message(
'New password is required.',
name: 'newPasswordRequireText',
desc: '',
args: [],
);
}
/// `New password *`
String get newPasswordStar {
return Intl.message(
'New password *',
name: 'newPasswordStar',
desc: '',
args: [],
);
}
/// `newPassword2`
String get newPassword2 {
return Intl.message(
'newPassword2',
name: 'newPassword2',
desc: '',
args: [],
);
}
/// `New password again is required.`
String get newPassword2RequireText {
return Intl.message(
'New password again is required.',
name: 'newPassword2RequireText',
desc: '',
args: [],
);
}
/// `New password again *`
String get newPassword2Star {
return Intl.message(
'New password again *',
name: 'newPassword2Star',
desc: '',
args: [],
);
}
/// `Entered passwords must be same!`
String get passwordErrorNotification {
return Intl.message(
'Entered passwords must be same!',
name: 'passwordErrorNotification',
desc: '',
args: [],
);
}
/// `Email *`
String get emailStar {
return Intl.message(
'Email *',
name: 'emailStar',
desc: '',
args: [],
);
}
/// `firstName`
String get firstName {
return Intl.message(
'firstName',
name: 'firstName',
desc: '',
args: [],
);
}
/// `First Name`
String get firstNameUpper {
return Intl.message(
'First Name',
name: 'firstNameUpper',
desc: '',
args: [],
);
}
/// `lastName`
String get lastName {
return Intl.message(
'lastName',
name: 'lastName',
desc: '',
args: [],
);
}
/// `Last Name`
String get lastNameUpper {
return Intl.message(
'Last Name',
name: 'lastNameUpper',
desc: '',
args: [],
);
}
/// `Profile successfully updated`
String get profileSuccessNotification {
return Intl.message(
'Profile successfully updated',
name: 'profileSuccessNotification',
desc: '',
args: [],
);
}
/// `Password successfully changed`
String get passwordSuccessNotification {
return Intl.message(
'Password successfully changed',
name: 'passwordSuccessNotification',
desc: '',
args: [],
);
}
/// `Not implemented!`
String get notImplemented {
return Intl.message(
'Not implemented!',
name: 'notImplemented',
desc: '',
args: [],
);
}
/// `The list is currently empty.`
String get listIsEmptyText {
return Intl.message(
'The list is currently empty.',
name: 'listIsEmptyText',
desc: '',
args: [],
);
}
/// `Try Again`
String get tryAgain {
return Intl.message(
'Try Again',
name: 'tryAgain',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
const AppLocalizationDelegate();
List<Locale> get supportedLocales {
return const <Locale>[
Locale.fromSubtags(languageCode: 'en'),
Locale.fromSubtags(languageCode: 'zh'),
];
}
@override
bool isSupported(Locale locale) => _isSupported(locale);
@override
Future<S> load(Locale locale) => S.load(locale);
@override
bool shouldReload(AppLocalizationDelegate old) => false;
bool _isSupported(Locale locale) {
for (var supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode) {
return true;
}
}
return false;
}
}

91
lib/l10n/intl_en.arb Normal file
View File

@@ -0,0 +1,91 @@
{
"appTitle": "Thingsboard",
"home": "Home",
"alarms": "Alarms",
"devices": "Devices",
"more": "More",
"customers": "Customers",
"assets": "Assets",
"auditLogs": "Audit Logs",
"logout": "Log Out",
"login": "Log In",
"logoDefaultValue": "Thingsboard Logo",
"loginNotification": "Login to your account",
"email": "Email",
"emailRequireText": "Email is required.",
"emailInvalidText": "Invalid email format.",
"username": "username",
"password": "Password",
"passwordRequireText": "Password is required.",
"passwordForgotText": "Forgot Password?",
"passwordReset": "Reset password",
"passwordResetText": "Enter the email associated with your account and we'll send an email with password reset link",
"requestPasswordReset": "Request password reset",
"passwordResetLinkSuccessfullySentNotification": "Password reset link was successfully sent!",
"OR": "OR",
"No": "No",
"Yes": "Yes",
"title": "Title",
"country": "Country",
"city": "City",
"stateOrProvince": "State / Province",
"postalCode": "Zip / Postal Code",
"address": "Address",
"address2": "Address 2",
"phone": "Phone",
"alarmClearTitle": "Clear Alarm",
"alarmClearText": "Are you sure you want to clear Alarm?",
"alarmAcknowledgeTitle": "Acknowledge Alarm",
"alarmAcknowledgeText": "Are you sure you want to acknowledge Alarm?",
"assetName": "Asset name",
"type": "Type",
"label": "Label",
"assignedToCustomer": "Assigned to customer",
"auditLogDetails": "Audit log details",
"entityType": "Entity Type",
"actionData": "Action data",
"failureDetails": "Failure details",
"allDevices": "All devices",
"active": "Active",
"inactive": "Inactive",
"systemAdministrator": "System Administrator",
"tenantAdministrator": "Tenant Administrator",
"customer": "Customer",
"changePassword": "Change Password",
"currentPassword": "currentPassword",
"currentPasswordRequireText": "Current password is required.",
"currentPasswordStar": "Current password *",
"newPassword": "newPassword",
"newPasswordRequireText": "New password is required.",
"newPasswordStar": "New password *",
"newPassword2": "newPassword2",
"newPassword2RequireText": "New password again is required.",
"newPassword2Star": "New password again *",
"passwordErrorNotification": "Entered passwords must be same!",
"emailStar": "Email *",
"firstName": "firstName",
"firstNameUpper": "First Name",
"lastName": "lastName",
"lastNameUpper": "Last Name",
"profileSuccessNotification": "Profile successfully updated",
"passwordSuccessNotification": "Password successfully changed",
"notImplemented": "Not implemented!",
"listIsEmptyText": "The list is currently empty.",
"tryAgain": "Try Again"
}

90
lib/l10n/intl_zh.arb Normal file
View File

@@ -0,0 +1,90 @@
{
"appTitle": "Thingsboard",
"home": "主页",
"alarms": "告警",
"devices": "设备",
"more": "更多",
"customers": "客户",
"asserts": "资产",
"auditLogs": "审计报告",
"logout": "登出",
"login": "登录",
"logoDefaultValue": "Thingsboard Logo",
"loginNotification": "登录你的账号",
"email": "Email",
"emailRequireText": "输入Email",
"emailInvalidText": "Email格式错误",
"username": "用户名",
"password": "密码",
"passwordRequireText": "输入密码",
"passwordForgotText": "忘记密码?",
"passwordReset": "重置密码",
"passwordResetText": "输入和账号关联的Email我们将发送一个密码重置链接到的Email",
"requestPasswordReset": "要求重置密码",
"passwordResetLinkSuccessfullySentNotification": "密码重置链接已发送",
"OR": "或",
"No": "否",
"Yes": "是",
"title": "标题",
"country": "国家",
"city": "城市",
"stateOrProvince": "州 / 省",
"postalCode": "邮编",
"address": "地址",
"address2": "地址 2",
"phone": "电话",
"alarmClearTitle": "清除告警",
"alarmClearText": "你确定要清除告警吗?",
"alarmAcknowledgeTitle": "确认告警",
"alarmAcknowledgeText": "你确定要确认告警吗?",
"assetName": "资产名",
"type": "类型",
"label": "标签",
"assignedToCustomer": "分配给客户",
"auditLogDetails": "审计日志详情",
"entityType": "实体类型",
"actionData": "动作数据",
"failureDetails": "失败详情",
"allDevices": "所有设备",
"active": "激活",
"inactive": "失活",
"systemAdministrator": "系统管理员",
"tenantAdministrator": "租户管理员",
"customer": "客户",
"changePassword": "修改密码",
"currentPassword": "当前密码",
"currentPasswordRequireText": "输入当前密码",
"currentPasswordStar": "当前密码 *",
"newPassword": "新密码",
"newPasswordRequireText": "输入新密码",
"newPasswordStar": "新密码 *",
"newPassword2": "新密码2",
"newPassword2RequireText": "再次输入新密码",
"newPassword2Star": "再次输入新密码 *",
"passwordErrorNotification": "输入的密码必须相同",
"emailStar": "Email *",
"firstName": "名",
"firstNameUpper": "名",
"lastName": "姓",
"lastNameUpper": "姓",
"profileSuccessNotification": "配置更新成功",
"passwordSuccessNotification": "密码修改成功",
"notImplemented": "未实现!",
"listIsEmptyText": "列表当前为空",
"tryAgain": "再试一次"
}

View File

@@ -1,3 +1,4 @@
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:universal_platform/universal_platform.dart';
import 'package:flutter/material.dart';
@@ -9,6 +10,7 @@ import 'package:thingsboard_app/modules/dashboard/main_dashboard_page.dart';
import 'package:thingsboard_app/widgets/two_page_view.dart';
import 'config/themes/tb_theme.dart';
import 'generated/l10n.dart';
final appRouter = ThingsboardAppRouter();
@@ -131,14 +133,28 @@ class ThingsboardAppState extends State<ThingsboardApp>
statusBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.light));
return MaterialApp(
title: 'ThingsBoard',
localizationsDelegates: [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
onGenerateTitle: (BuildContext context) => S.of(context).appTitle,
themeMode: ThemeMode.light,
home: TwoPageView(
controller: _mainPageViewController,
first: MaterialApp(
key: mainAppKey,
scaffoldMessengerKey: appRouter.tbContext.messengerKey,
title: 'ThingsBoard',
localizationsDelegates: [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
onGenerateTitle: (BuildContext context) => S.of(context).appTitle,
theme: tbTheme,
themeMode: ThemeMode.light,
darkTheme: tbDarkTheme,
@@ -148,7 +164,14 @@ class ThingsboardAppState extends State<ThingsboardApp>
second: MaterialApp(
key: dashboardKey,
// scaffoldMessengerKey: appRouter.tbContext.messengerKey,
title: 'ThingsBoard',
localizationsDelegates: [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
onGenerateTitle: (BuildContext context) => S.of(context).appTitle,
theme: tbTheme,
themeMode: ThemeMode.light,
darkTheme: tbDarkTheme,

View File

@@ -4,6 +4,7 @@ import 'package:intl/intl.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/utils.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
@@ -249,7 +250,8 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
child: IconButton(
icon: Icon(Icons.done, size: 18),
padding: EdgeInsets.all(7.0),
onPressed: () => _ackAlarm(alarm))),
onPressed: () =>
_ackAlarm(alarm, context))),
if ([
AlarmStatus.ACTIVE_UNACK,
AlarmStatus.ACTIVE_ACK
@@ -262,7 +264,8 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
child: IconButton(
icon: Icon(Icons.clear, size: 18),
padding: EdgeInsets.all(7.0),
onPressed: () => _clearAlarm(alarm)))
onPressed: () =>
_clearAlarm(alarm, context)))
])
],
),
@@ -277,12 +280,12 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
}
}
_clearAlarm(AlarmInfo alarm) async {
_clearAlarm(AlarmInfo alarm, BuildContext context) async {
var res = await confirm(
title: 'Clear Alarm',
message: 'Are you sure you want to clear Alarm?',
cancel: 'No',
ok: 'Yes');
title: '${S.of(context).alarmClearTitle}',
message: '${S.of(context).alarmClearText}',
cancel: '${S.of(context).No}',
ok: '${S.of(context).Yes}');
if (res != null && res) {
setState(() {
loading = true;
@@ -297,12 +300,12 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
}
}
_ackAlarm(AlarmInfo alarm) async {
_ackAlarm(AlarmInfo alarm, BuildContext context) async {
var res = await confirm(
title: 'Acknowledge Alarm',
message: 'Are you sure you want to acknowledge Alarm?',
cancel: 'No',
ok: 'Yes');
title: '${S.of(context).alarmAcknowledgeTitle}',
message: '${S.of(context).alarmAcknowledgeText}',
cancel: '${S.of(context).No}',
ok: '${S.of(context).Yes}');
if (res != null && res) {
setState(() {
loading = true;

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/entity/entity_details_page.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
class AssetDetailsPage extends EntityDetailsPage<AssetInfo> {
@@ -24,16 +25,17 @@ class AssetDetailsPage extends EntityDetailsPage<AssetInfo> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Text('Asset name', style: labelTextStyle),
Text('${S.of(context).assetName}', style: labelTextStyle),
Text(asset.name, style: valueTextStyle),
SizedBox(height: 16),
Text('Type', style: labelTextStyle),
Text('${S.of(context).type}', style: labelTextStyle),
Text(asset.type, style: valueTextStyle),
SizedBox(height: 16),
Text('Label', style: labelTextStyle),
Text('${S.of(context).label}', style: labelTextStyle),
Text(asset.label ?? '', style: valueTextStyle),
SizedBox(height: 16),
Text('Assigned to customer', style: labelTextStyle),
Text('${S.of(context).assignedToCustomer}',
style: labelTextStyle),
Text(asset.customerTitle ?? '', style: valueTextStyle),
]));
}

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/audit_log/audit_logs_base.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
@@ -39,7 +40,7 @@ class _AuditLogDetailsPageState extends TbContextState<AuditLogDetailsPage> {
fontWeight: FontWeight.w500,
fontSize: 16,
height: 20 / 16)),
Text('Audit log details',
Text('${S.of(context).auditLogDetails}',
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme
@@ -56,24 +57,24 @@ class _AuditLogDetailsPageState extends TbContextState<AuditLogDetailsPage> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Text('Entity Type', style: labelTextStyle),
Text('${S.of(context).entityType}', style: labelTextStyle),
Text(entityTypeTranslations[widget.auditLog.entityId.entityType]!,
style: valueTextStyle),
SizedBox(height: 16),
Text('Type', style: labelTextStyle),
Text('${S.of(context).type}', style: labelTextStyle),
Text(actionTypeTranslations[widget.auditLog.actionType]!,
style: valueTextStyle),
SizedBox(height: 16),
Flexible(
fit: FlexFit.loose,
child: buildBorderedText('Action data',
child: buildBorderedText('${S.of(context).actionData}',
encoder.convert(widget.auditLog.actionData))),
if (widget.auditLog.actionStatus == ActionStatus.FAILURE)
SizedBox(height: 16),
if (widget.auditLog.actionStatus == ActionStatus.FAILURE)
Flexible(
fit: FlexFit.loose,
child: buildBorderedText('Failure details',
child: buildBorderedText('${S.of(context).failureDetails}',
widget.auditLog.actionFailureDetails!))
]),
),

View File

@@ -7,6 +7,7 @@ import 'package:thingsboard_app/constants/assets_path.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/services/device_profile_cache.dart';
import 'package:thingsboard_app/utils/services/entity_query_api.dart';
import 'package:thingsboard_app/utils/utils.dart';
@@ -135,7 +136,7 @@ class _AllDevicesCardState extends TbContextState<AllDevicesCard> {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('All devices',
Text('${S.of(context).allDevices}',
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
@@ -414,7 +415,10 @@ Widget _buildDeviceCount(BuildContext context, bool active, int count) {
],
),
SizedBox(width: 8.67),
Text(active ? 'Active' : 'Inactive',
Text(
active
? '${S.of(context).active}'
: '${S.of(context).inactive}',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,

View File

@@ -7,6 +7,7 @@ import 'package:thingsboard_app/constants/assets_path.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/services/device_profile_cache.dart';
import 'package:thingsboard_app/utils/services/entity_query_api.dart';
import 'package:thingsboard_app/utils/utils.dart';
@@ -266,8 +267,8 @@ class _DeviceCardState extends TbContextState<DeviceCard> {
widget.device.attribute(
'active') ==
'true'
? 'Active'
: 'Inactive',
? '${S.of(context).active}'
: '${S.of(context).inactive}',
style: TextStyle(
color: widget.device
.attribute(

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/device/devices_base.dart';
import 'package:thingsboard_app/modules/device/devices_list.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
@@ -41,11 +42,14 @@ class _DevicesListPageState extends TbPageState<DevicesListPage> {
_deviceQueryController.onSearchText(searchText),
);
} else {
String titleText =
widget.deviceType != null ? widget.deviceType! : 'All devices';
String titleText = widget.deviceType != null
? widget.deviceType!
: '${S.of(context).allDevices}';
String? subTitleText;
if (widget.active != null) {
subTitleText = widget.active == true ? 'Active' : 'Inactive';
subTitleText = widget.active == true
? '${S.of(context).active}'
: '${S.of(context).inactive}';
}
Column title =
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/alarm/alarms_page.dart';
import 'package:thingsboard_app/modules/device/devices_main_page.dart';
import 'package:thingsboard_app/modules/home/home_page.dart';
@@ -9,7 +10,7 @@ import 'package:thingsboard_client/thingsboard_client.dart';
class TbMainNavigationItem {
final Widget page;
final String title;
String title;
final Icon icon;
final String path;
@@ -80,6 +81,26 @@ class TbMainNavigationItem {
return [];
}
}
static void changeItemsTitleIntl(
List<TbMainNavigationItem> items, BuildContext context) {
for (var item in items) {
switch (item.path) {
case '/home':
item.title = '${S.of(context).home}';
break;
case '/alarms':
item.title = '${S.of(context).alarms}';
break;
case '/devices':
item.title = '${S.of(context).devices}';
break;
case '/more':
item.title = '${S.of(context).more}';
break;
}
}
}
}
class MainPage extends TbPageWidget {
@@ -129,6 +150,7 @@ class _MainPageState extends TbPageState<MainPage>
@override
Widget build(BuildContext context) {
TbMainNavigationItem.changeItemsTitleIntl(_tabItems, context);
return WillPopScope(
onWillPop: () async {
if (_tabController.index > 0) {

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
class MorePage extends TbContextWidget {
@@ -42,7 +43,7 @@ class _MorePageState extends TbContextState<MorePage> {
fontSize: 20,
height: 23 / 20)),
SizedBox(height: 2),
Text(_getAuthorityName(),
Text(_getAuthorityName(context),
style: TextStyle(
color: Color(0xFFAFAFAF),
fontWeight: FontWeight.normal,
@@ -65,7 +66,7 @@ class _MorePageState extends TbContextState<MorePage> {
child: Row(mainAxisSize: MainAxisSize.max, children: [
Icon(Icons.logout, color: Color(0xFFE04B2F)),
SizedBox(width: 34),
Text('Log out',
Text('${S.of(context).logout}',
style: TextStyle(
color: Color(0xFFE04B2F),
fontStyle: FontStyle.normal,
@@ -83,7 +84,8 @@ class _MorePageState extends TbContextState<MorePage> {
}
Widget buildMoreMenuItems(BuildContext context) {
List<Widget> items = MoreMenuItem.getItems(tbContext).map((menuItem) {
List<Widget> items =
MoreMenuItem.getItems(tbContext, context).map((menuItem) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
child: Container(
@@ -130,20 +132,20 @@ class _MorePageState extends TbContextState<MorePage> {
return name;
}
String _getAuthorityName() {
String _getAuthorityName(BuildContext context) {
var user = tbContext.userDetails;
var name = '';
if (user != null) {
var authority = user.authority;
switch (authority) {
case Authority.SYS_ADMIN:
name = 'System Administrator';
name = '${S.of(context).systemAdministrator}';
break;
case Authority.TENANT_ADMIN:
name = 'Tenant Administrator';
name = '${S.of(context).tenantAdministrator}';
break;
case Authority.CUSTOMER_USER:
name = 'Customer';
name = '${S.of(context).customer}';
break;
default:
break;
@@ -160,7 +162,8 @@ class MoreMenuItem {
MoreMenuItem({required this.title, required this.icon, required this.path});
static List<MoreMenuItem> getItems(TbContext tbContext) {
static List<MoreMenuItem> getItems(
TbContext tbContext, BuildContext context) {
if (tbContext.isAuthenticated) {
List<MoreMenuItem> items = [];
switch (tbContext.tbClient.getAuthUser()!.authority) {
@@ -169,19 +172,25 @@ class MoreMenuItem {
case Authority.TENANT_ADMIN:
items.addAll([
MoreMenuItem(
title: 'Customers',
title: '${S.of(context).customers}',
icon: Icons.supervisor_account,
path: '/customers'),
MoreMenuItem(title: 'Assets', icon: Icons.domain, path: '/assets'),
MoreMenuItem(
title: 'Audit Logs',
title: '${S.of(context).assets}',
icon: Icons.domain,
path: '/assets'),
MoreMenuItem(
title: '${S.of(context).auditLogs}',
icon: Icons.track_changes,
path: '/auditLogs')
]);
break;
case Authority.CUSTOMER_USER:
items.addAll([
MoreMenuItem(title: 'Assets', icon: Icons.domain, path: '/assets')
MoreMenuItem(
title: '${S.of(context).assets}',
icon: Icons.domain,
path: '/assets')
]);
break;
case Authority.REFRESH_TOKEN:

View File

@@ -3,6 +3,7 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
import 'package:thingsboard_app/widgets/tb_progress_indicator.dart';
@@ -28,7 +29,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
backgroundColor: Colors.white,
appBar: TbAppBar(
tbContext,
title: const Text('Change Password'),
title: Text('${S.of(context).changePassword}'),
),
body: Stack(
children: [
@@ -54,7 +55,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText:
'Current password is required.')
'${S.of(context).currentPasswordRequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -68,7 +69,8 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
},
),
border: OutlineInputBorder(),
labelText: 'Current password *'),
labelText:
'${S.of(context).currentPasswordStar}'),
);
}),
SizedBox(height: 24),
@@ -81,7 +83,8 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
obscureText: !showPassword,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText: 'New password is required.')
errorText:
'${S.of(context).newPasswordRequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -94,7 +97,8 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
},
),
border: OutlineInputBorder(),
labelText: 'New password *'),
labelText:
'${S.of(context).newPasswordStar}'),
);
}),
SizedBox(height: 24),
@@ -108,7 +112,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText:
'New password again is required.')
'${S.of(context).newPassword2RequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -121,7 +125,8 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
},
),
border: OutlineInputBorder(),
labelText: 'New password again *'),
labelText:
'${S.of(context).newPassword2Star}'),
);
}),
SizedBox(height: 24),
@@ -132,7 +137,9 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
onPressed: () {
_changePassword();
},
child: Center(child: Text('Change Password')))
child: Center(
child:
Text('${S.of(context).changePassword}')))
]),
))),
),
@@ -161,7 +168,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
String newPassword = formValue['newPassword'];
String newPassword2 = formValue['newPassword2'];
if (newPassword != newPassword2) {
showErrorNotification('Entered passwords must be same!');
showErrorNotification('${S.of(context).passwordErrorNotification}');
} else {
_isLoadingNotifier.value = true;
try {

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/profile/change_password_page.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
@@ -76,27 +77,29 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
name: 'email',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(
errorText: 'Email is required.'),
errorText:
'${S.of(context).emailRequireText}'),
FormBuilderValidators.email(
errorText: 'Invalid email format.')
errorText:
'${S.of(context).emailInvalidText}')
]),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email *'),
labelText: '${S.of(context).emailStar}'),
),
SizedBox(height: 24),
FormBuilderTextField(
name: 'firstName',
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'First Name'),
labelText: '${S.of(context).firstNameUpper}'),
),
SizedBox(height: 24),
FormBuilderTextField(
name: 'lastName',
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Last Name'),
labelText: '${S.of(context).lastNameUpper}'),
),
SizedBox(height: 24),
OutlinedButton(
@@ -106,7 +109,9 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
onPressed: () {
_changePassword();
},
child: Center(child: Text('Change Password')))
child: Center(
child:
Text('${S.of(context).changePassword}')))
]),
))),
),
@@ -156,7 +161,9 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
_setUser();
await Future.delayed(Duration(milliseconds: 300));
_isLoadingNotifier.value = false;
showSuccessNotification('Profile successfully updated',
showSuccessNotification('${S.of(context).profileSuccessNotification}',
duration: Duration(milliseconds: 1500));
showSuccessNotification('${S.of(context).profileSuccessNotification}',
duration: Duration(milliseconds: 1500));
}
}
@@ -166,7 +173,7 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
var res = await tbContext
.showFullScreenDialog<bool>(new ChangePasswordPage(tbContext));
if (res == true) {
showSuccessNotification('Password successfully changed',
showSuccessNotification('${S.of(context).passwordSuccessNotification}',
duration: Duration(milliseconds: 1500));
}
}

View File

@@ -191,7 +191,7 @@ packages:
source: hosted
version: "0.10.0"
flutter_localizations:
dependency: transitive
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"

View File

@@ -48,6 +48,8 @@ dependencies:
universal_html: ^2.0.8
universal_platform: ^1.0.0+1
preload_page_view: ^0.1.6
flutter_localizations:
sdk: flutter
dev_dependencies:
flutter_test:
@@ -90,3 +92,5 @@ flutter_icons:
ios: true
remove_alpha_ios: true
image_path: "assets/images/thingsboard.png"
flutter_intl:
enabled: true