mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 10:49:49 +08:00
Merge pull request #300 from DenserMeerkat/resolve-issue-missing-drag-scrolling
fix: missing drag scrolling
This commit is contained in:
@@ -3,7 +3,6 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
|
||||
const kDiscordUrl = "https://bit.ly/heyfoss";
|
||||
const kGitUrl = "https://github.com/foss42/apidash";
|
||||
@@ -82,6 +81,8 @@ const kPh2 = EdgeInsets.symmetric(horizontal: 2);
|
||||
const kPt24o8 = EdgeInsets.only(top: 24, left: 8.0, right: 8.0, bottom: 8.0);
|
||||
const kPt5o10 =
|
||||
EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0);
|
||||
const kPh4 = EdgeInsets.symmetric(horizontal: 4);
|
||||
const kPh8 = EdgeInsets.symmetric(horizontal: 8);
|
||||
const kPh20 = EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
);
|
||||
@@ -128,19 +129,11 @@ const kTextButtonMinWidth = 44.0;
|
||||
|
||||
const kRandMax = 100000;
|
||||
|
||||
const kTableThemeData = DaviThemeData(
|
||||
columnDividerThickness: 1,
|
||||
columnDividerColor: kColorTransparent,
|
||||
row: RowThemeData(
|
||||
dividerColor: kColorTransparent,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(),
|
||||
),
|
||||
header: HeaderThemeData(
|
||||
visible: false,
|
||||
),
|
||||
const kDataTableScrollbarTheme = ScrollbarThemeData(
|
||||
crossAxisMargin: -4,
|
||||
);
|
||||
const kDataTableBottomPadding = 12.0;
|
||||
const kDataTableRowHeight = 36.0;
|
||||
|
||||
const kIconRemoveDark = Icon(
|
||||
Icons.remove_circle,
|
||||
|
||||
@@ -21,7 +21,6 @@ class EditRequestBody extends ConsumerWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
),
|
||||
margin: kPt5o10,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
@@ -38,9 +37,12 @@ class EditRequestBody extends ConsumerWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: switch (contentType) {
|
||||
ContentType.formdata => const FormDataWidget(),
|
||||
ContentType.formdata =>
|
||||
const Padding(padding: kPh4, child: FormDataWidget()),
|
||||
// TODO: Fix JsonTextFieldEditor & plug it here
|
||||
ContentType.json => TextFieldEditor(
|
||||
ContentType.json => Padding(
|
||||
padding: kPt5o10,
|
||||
child: TextFieldEditor(
|
||||
key: Key("$selectedId-json-body"),
|
||||
fieldKey: "$selectedId-json-body-editor",
|
||||
initialValue: requestModel?.requestBody,
|
||||
@@ -50,7 +52,10 @@ class EditRequestBody extends ConsumerWidget {
|
||||
.update(selectedId, requestBody: value);
|
||||
},
|
||||
),
|
||||
_ => TextFieldEditor(
|
||||
),
|
||||
_ => Padding(
|
||||
padding: kPt5o10,
|
||||
child: TextFieldEditor(
|
||||
key: Key("$selectedId-body"),
|
||||
fieldKey: "$selectedId-body-editor",
|
||||
initialValue: requestModel?.requestBody,
|
||||
@@ -60,6 +65,7 @@ class EditRequestBody extends ConsumerWidget {
|
||||
.update(selectedId, requestBody: value);
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
)
|
||||
],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
@@ -40,32 +40,53 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
.select((value) => value?.requestFormDataList?.length));
|
||||
var rF = ref.read(selectedRequestModelProvider)?.requestFormDataList;
|
||||
bool isFormDataEmpty = rF == null || rF.isEmpty;
|
||||
List<FormDataModel> rows = (isFormDataEmpty)
|
||||
formRows = isFormDataEmpty
|
||||
? [
|
||||
kFormDataEmptyModel,
|
||||
]
|
||||
: rF;
|
||||
formRows = isFormDataEmpty ? rows : rows + [kFormDataEmptyModel];
|
||||
: rF +
|
||||
[
|
||||
kFormDataEmptyModel,
|
||||
];
|
||||
isAddingRow = false;
|
||||
|
||||
DaviModel<FormDataModel> daviModelRows = DaviModel<FormDataModel>(
|
||||
rows: formRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
cellPadding: kPv2,
|
||||
name: kNameField,
|
||||
grow: 4,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == formRows.length;
|
||||
return Theme(
|
||||
data: Theme.of(context),
|
||||
child: FormDataField(
|
||||
keyId: "$selectedId-$idx-form-v-$seed",
|
||||
initialValue: formRows[idx].name,
|
||||
List<DataColumn> columns = const [
|
||||
DataColumn2(
|
||||
label: Text(kNameField),
|
||||
size: ColumnSize.M,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('='),
|
||||
fixedWidth: 20,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 70,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameValue),
|
||||
size: ColumnSize.L,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 32,
|
||||
),
|
||||
];
|
||||
|
||||
List<DataRow> dataRows = List<DataRow>.generate(
|
||||
formRows.length,
|
||||
(index) {
|
||||
bool isLast = index + 1 == formRows.length;
|
||||
return DataRow(
|
||||
key: ValueKey("$selectedId-$index-form-row-$seed"),
|
||||
cells: <DataCell>[
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-form-k-$seed",
|
||||
initialValue: formRows[index].name,
|
||||
hintText: kHintAddFieldName,
|
||||
onChanged: (value) {
|
||||
formRows[idx] = formRows[idx].copyWith(name: value);
|
||||
formRows[index] = formRows[index].copyWith(name: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
@@ -73,13 +94,25 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
formDataType: formRows[idx].type,
|
||||
onFormDataTypeChanged: (value) {
|
||||
bool hasChanged = formRows[idx].type != value;
|
||||
formRows[idx] = formRows[idx].copyWith(
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
Center(
|
||||
child: Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
DropdownButtonFormData(
|
||||
formDataType: formRows[index].type,
|
||||
onChanged: (value) {
|
||||
bool hasChanged = formRows[index].type != value;
|
||||
formRows[index] = formRows[index].copyWith(
|
||||
type: value ?? FormDataType.text,
|
||||
);
|
||||
formRows[idx] = formRows[idx].copyWith(value: "");
|
||||
formRows[index] = formRows[index].copyWith(value: "");
|
||||
if (isLast && hasChanged) {
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
}
|
||||
@@ -87,53 +120,25 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 40,
|
||||
cellPadding: kPv2,
|
||||
cellAlignment: Alignment.center,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: kNameValue,
|
||||
grow: 4,
|
||||
cellPadding: kPv2,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == formRows.length;
|
||||
return formRows[idx].type == FormDataType.file
|
||||
? Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Theme(
|
||||
data: Theme.of(context),
|
||||
child: ElevatedButton.icon(
|
||||
DataCell(
|
||||
formRows[index].type == FormDataType.file
|
||||
? ElevatedButton.icon(
|
||||
icon: const Icon(
|
||||
Icons.snippet_folder_rounded,
|
||||
size: 20,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStatePropertyAll(
|
||||
RoundedRectangleBorder(
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(kDataTableRowHeight),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
var pickedResult = await pickFile();
|
||||
if (pickedResult != null &&
|
||||
pickedResult.path.isNotEmpty) {
|
||||
formRows[idx] = formRows[idx].copyWith(
|
||||
formRows[index] = formRows[index].copyWith(
|
||||
value: pickedResult.path,
|
||||
);
|
||||
setState(() {});
|
||||
@@ -141,26 +146,21 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
}
|
||||
},
|
||||
label: Text(
|
||||
(formRows[idx].type == FormDataType.file &&
|
||||
formRows[idx].value.isNotEmpty)
|
||||
? formRows[idx].value.toString()
|
||||
(formRows[index].type == FormDataType.file &&
|
||||
formRows[index].value.isNotEmpty)
|
||||
? formRows[index].value.toString()
|
||||
: kLabelSelectFile,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: kFormDataButtonLabelTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: CellField(
|
||||
keyId: "$selectedId-$idx-form-v-$seed",
|
||||
initialValue: formRows[idx].value,
|
||||
keyId: "$selectedId-$index-form-v-$seed",
|
||||
initialValue: formRows[index].value,
|
||||
hintText: kHintAddValue,
|
||||
onChanged: (value) {
|
||||
formRows[idx] = formRows[idx].copyWith(value: value);
|
||||
formRows[index] =
|
||||
formRows[index].copyWith(value: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
@@ -168,37 +168,35 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == formRows.length;
|
||||
return InkWell(
|
||||
),
|
||||
DataCell(
|
||||
InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (formRows.length == 2) {
|
||||
setState(() {
|
||||
formRows = [kFormDataEmptyModel];
|
||||
formRows = [
|
||||
kFormDataEmptyModel,
|
||||
];
|
||||
});
|
||||
} else {
|
||||
formRows.removeAt(row.index);
|
||||
formRows.removeAt(index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@@ -210,19 +208,30 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<FormDataModel>(daviModelRows),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(scrollbarTheme: kDataTableScrollbarTheme),
|
||||
child: DataTable2(
|
||||
columnSpacing: 12,
|
||||
dividerThickness: 0,
|
||||
horizontalMargin: 0,
|
||||
headingRowHeight: 0,
|
||||
dataRowHeight: kDataTableRowHeight,
|
||||
bottomMargin: kDataTableBottomPadding,
|
||||
isVerticalScrollBarVisible: true,
|
||||
columns: columns,
|
||||
rows: dataRows,
|
||||
),
|
||||
),
|
||||
kVSpacer20,
|
||||
),
|
||||
kVSpacer40,
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 5),
|
||||
padding: kPb15,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
@@ -43,108 +43,106 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
.select((value) => value?.requestHeaders?.length));
|
||||
var rH = ref.read(selectedRequestModelProvider)?.requestHeaders;
|
||||
bool isHeadersEmpty = rH == null || rH.isEmpty;
|
||||
List<NameValueModel> rows = (isHeadersEmpty)
|
||||
headerRows = isHeadersEmpty
|
||||
? [
|
||||
kNameValueEmptyModel,
|
||||
]
|
||||
: rH;
|
||||
headerRows = isHeadersEmpty ? rows : rows + [kNameValueEmptyModel];
|
||||
: rH + [kNameValueEmptyModel];
|
||||
isRowEnabledList =
|
||||
ref.read(selectedRequestModelProvider)?.isHeaderEnabledList ??
|
||||
List.filled(rH?.length ?? 0, true, growable: true);
|
||||
isRowEnabledList.add(false);
|
||||
isAddingRow = false;
|
||||
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: headerRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
name: kNameCheckbox,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return CheckBox(
|
||||
keyId: "$selectedId-$idx-headers-c-$seed",
|
||||
value: isRowEnabledList[idx],
|
||||
List<DataColumn> columns = const [
|
||||
DataColumn2(
|
||||
label: Text(kNameCheckbox),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameHeader),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('='),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameValue),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 32,
|
||||
),
|
||||
];
|
||||
|
||||
List<DataRow> dataRows = List<DataRow>.generate(
|
||||
headerRows.length,
|
||||
(index) {
|
||||
bool isLast = index + 1 == headerRows.length;
|
||||
return DataRow(
|
||||
key: ValueKey("$selectedId-$index-headers-row-$seed"),
|
||||
cells: <DataCell>[
|
||||
DataCell(
|
||||
CheckBox(
|
||||
keyId: "$selectedId-$index-headers-c-$seed",
|
||||
value: isRowEnabledList[index],
|
||||
onChanged: isLast
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
isRowEnabledList[idx] = value!;
|
||||
isRowEnabledList[index] = value!;
|
||||
});
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: kNameHeader,
|
||||
width: 70,
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return HeaderField(
|
||||
keyId: "$selectedId-$idx-headers-k-$seed",
|
||||
initialValue: headerRows[idx].name,
|
||||
),
|
||||
DataCell(
|
||||
HeaderField(
|
||||
keyId: "$selectedId-$index-headers-k-$seed",
|
||||
initialValue: headerRows[index].name,
|
||||
hintText: kHintAddName,
|
||||
onChanged: (value) {
|
||||
headerRows[idx] = headerRows[idx].copyWith(name: value);
|
||||
headerRows[index] = headerRows[index].copyWith(name: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[idx] = true;
|
||||
isRowEnabledList[index] = true;
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
),
|
||||
DataCell(
|
||||
Center(
|
||||
child: Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: kNameValue,
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-headers-v-$seed",
|
||||
initialValue: headerRows[idx].value,
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-headers-v-$seed",
|
||||
initialValue: headerRows[index].value,
|
||||
hintText: kHintAddValue,
|
||||
onChanged: (value) {
|
||||
headerRows[idx] = headerRows[idx].copyWith(value: value);
|
||||
headerRows[index] = headerRows[index].copyWith(value: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[idx] = true;
|
||||
isRowEnabledList[index] = true;
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == headerRows.length;
|
||||
return InkWell(
|
||||
),
|
||||
DataCell(
|
||||
InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
@@ -157,19 +155,21 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
isRowEnabledList = [false];
|
||||
});
|
||||
} else {
|
||||
headerRows.removeAt(row.index);
|
||||
isRowEnabledList.removeAt(row.index);
|
||||
headerRows.removeAt(index);
|
||||
isRowEnabledList.removeAt(index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@@ -181,9 +181,20 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<NameValueModel>(model),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(scrollbarTheme: kDataTableScrollbarTheme),
|
||||
child: DataTable2(
|
||||
columnSpacing: 12,
|
||||
dividerThickness: 0,
|
||||
horizontalMargin: 0,
|
||||
headingRowHeight: 0,
|
||||
dataRowHeight: kDataTableRowHeight,
|
||||
bottomMargin: kDataTableBottomPadding,
|
||||
isVerticalScrollBarVisible: true,
|
||||
columns: columns,
|
||||
rows: dataRows,
|
||||
),
|
||||
),
|
||||
),
|
||||
kVSpacer40,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
|
||||
class EditRequestURLParams extends ConsumerStatefulWidget {
|
||||
const EditRequestURLParams({super.key});
|
||||
@@ -43,108 +43,106 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
.select((value) => value?.requestParams?.length));
|
||||
var rP = ref.read(selectedRequestModelProvider)?.requestParams;
|
||||
bool isParamsEmpty = rP == null || rP.isEmpty;
|
||||
List<NameValueModel> rows = (isParamsEmpty)
|
||||
paramRows = isParamsEmpty
|
||||
? [
|
||||
kNameValueEmptyModel,
|
||||
]
|
||||
: rP;
|
||||
paramRows = isParamsEmpty ? rows : rows + [kNameValueEmptyModel];
|
||||
: rP + [kNameValueEmptyModel];
|
||||
isRowEnabledList =
|
||||
ref.read(selectedRequestModelProvider)?.isParamEnabledList ??
|
||||
List.filled(rP?.length ?? 0, true, growable: true);
|
||||
isRowEnabledList.add(false);
|
||||
isAddingRow = false;
|
||||
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: paramRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
name: kNameCheckbox,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CheckBox(
|
||||
keyId: "$selectedId-$idx-params-c-$seed",
|
||||
value: isRowEnabledList[idx],
|
||||
List<DataColumn> columns = const [
|
||||
DataColumn2(
|
||||
label: Text(kNameCheckbox),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameURLParam),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('='),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameValue),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 32,
|
||||
),
|
||||
];
|
||||
|
||||
List<DataRow> dataRows = List<DataRow>.generate(
|
||||
paramRows.length,
|
||||
(index) {
|
||||
bool isLast = index + 1 == paramRows.length;
|
||||
return DataRow(
|
||||
key: ValueKey("$selectedId-$index-params-row-$seed"),
|
||||
cells: <DataCell>[
|
||||
DataCell(
|
||||
CheckBox(
|
||||
keyId: "$selectedId-$index-params-c-$seed",
|
||||
value: isRowEnabledList[index],
|
||||
onChanged: isLast
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
isRowEnabledList[idx] = value!;
|
||||
isRowEnabledList[index] = value!;
|
||||
});
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: kNameURLParam,
|
||||
width: 70,
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-params-k-$seed",
|
||||
initialValue: paramRows[idx].name,
|
||||
),
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-params-k-$seed",
|
||||
initialValue: paramRows[index].name,
|
||||
hintText: kHintAddURLParam,
|
||||
onChanged: (value) {
|
||||
paramRows[idx] = paramRows[idx].copyWith(name: value);
|
||||
paramRows[index] = paramRows[index].copyWith(name: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[idx] = true;
|
||||
isRowEnabledList[index] = true;
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
),
|
||||
DataCell(
|
||||
Center(
|
||||
child: Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: kNameValue,
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-params-v-$seed",
|
||||
initialValue: paramRows[idx].value,
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-params-v-$seed",
|
||||
initialValue: paramRows[index].value,
|
||||
hintText: kHintAddValue,
|
||||
onChanged: (value) {
|
||||
paramRows[idx] = paramRows[idx].copyWith(value: value);
|
||||
paramRows[index] = paramRows[index].copyWith(value: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[idx] = true;
|
||||
isRowEnabledList[index] = true;
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == paramRows.length;
|
||||
return InkWell(
|
||||
),
|
||||
DataCell(
|
||||
InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
@@ -157,19 +155,21 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
isRowEnabledList = [false];
|
||||
});
|
||||
} else {
|
||||
paramRows.removeAt(row.index);
|
||||
isRowEnabledList.removeAt(row.index);
|
||||
paramRows.removeAt(index);
|
||||
isRowEnabledList.removeAt(index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@@ -179,11 +179,23 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
),
|
||||
margin: kP10,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<NameValueModel>(model),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(scrollbarTheme: kDataTableScrollbarTheme),
|
||||
child: DataTable2(
|
||||
columnSpacing: 12,
|
||||
dividerThickness: 0,
|
||||
horizontalMargin: 0,
|
||||
headingRowHeight: 0,
|
||||
dataRowHeight: kDataTableRowHeight,
|
||||
bottomMargin: kDataTableBottomPadding,
|
||||
isVerticalScrollBarVisible: true,
|
||||
columns: columns,
|
||||
rows: dataRows,
|
||||
),
|
||||
),
|
||||
),
|
||||
kVSpacer40,
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dropdowns.dart';
|
||||
|
||||
class FormDataField extends StatefulWidget {
|
||||
const FormDataField({
|
||||
super.key,
|
||||
required this.keyId,
|
||||
this.initialValue,
|
||||
this.hintText,
|
||||
this.onChanged,
|
||||
this.colorScheme,
|
||||
this.formDataType,
|
||||
this.onFormDataTypeChanged,
|
||||
});
|
||||
|
||||
final String keyId;
|
||||
final String? initialValue;
|
||||
final String? hintText;
|
||||
final void Function(String)? onChanged;
|
||||
final ColorScheme? colorScheme;
|
||||
final FormDataType? formDataType;
|
||||
final void Function(FormDataType?)? onFormDataTypeChanged;
|
||||
|
||||
@override
|
||||
State<FormDataField> createState() => _FormDataFieldState();
|
||||
}
|
||||
|
||||
class _FormDataFieldState extends State<FormDataField> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var colorScheme = widget.colorScheme ?? Theme.of(context).colorScheme;
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: TextFormField(
|
||||
initialValue: widget.initialValue,
|
||||
key: Key(widget.keyId),
|
||||
style: kCodeStyle.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: kCodeStyle.copyWith(
|
||||
color: colorScheme.outline.withOpacity(
|
||||
kHintOpacity,
|
||||
),
|
||||
),
|
||||
hintText: widget.hintText,
|
||||
contentPadding: const EdgeInsets.only(bottom: 16),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: colorScheme.primary.withOpacity(
|
||||
kHintOpacity,
|
||||
),
|
||||
),
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: colorScheme.surfaceVariant,
|
||||
),
|
||||
),
|
||||
suffixIcon: DropdownButtonFormData(
|
||||
formDataType: widget.formDataType,
|
||||
onChanged: (p0) {
|
||||
if (widget.onFormDataTypeChanged != null) {
|
||||
widget.onFormDataTypeChanged!(p0);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: widget.onChanged,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -76,11 +76,14 @@ class _HeaderFieldState extends State<HeaderField> {
|
||||
onChanged: widget.onChanged,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: kCodeStyle.copyWith(color: colorScheme.onSurface),
|
||||
style: kCodeStyle.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: kCodeStyle.copyWith(
|
||||
color: colorScheme.outline.withOpacity(kHintOpacity)),
|
||||
hintText: widget.hintText,
|
||||
contentPadding: const EdgeInsets.only(bottom: 12),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: colorScheme.primary.withOpacity(
|
||||
|
||||
@@ -93,6 +93,7 @@ class _RequestPaneState extends State<RequestPane>
|
||||
),
|
||||
],
|
||||
),
|
||||
kVSpacer5,
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
controller: _controller,
|
||||
|
||||
@@ -68,6 +68,7 @@ class CellField extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
hintText: hintText,
|
||||
contentPadding: const EdgeInsets.only(bottom: 12),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: clrScheme.primary.withOpacity(
|
||||
|
||||
@@ -7,7 +7,6 @@ export 'dropdowns.dart';
|
||||
export 'editor_json.dart';
|
||||
export 'editor.dart';
|
||||
export 'error_message.dart';
|
||||
export 'form_data_field.dart';
|
||||
export 'headerfield.dart';
|
||||
export 'intro_message.dart';
|
||||
export 'json_previewer.dart';
|
||||
|
||||
16
pubspec.lock
16
pubspec.lock
@@ -49,14 +49,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.18"
|
||||
axis_layout:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: axis_layout
|
||||
sha256: "9ba44f279f39121065d811e72da892de86f5613d68eb0b295f60d021ea8f2a59"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
barcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -249,14 +241,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.6"
|
||||
davi:
|
||||
data_table_2:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: davi
|
||||
sha256: "4105870281c4c33e8e017e21e212b96fd2637b4c1a35b2a56f14aaa4acdf6f0d"
|
||||
name: data_table_2
|
||||
sha256: fdb0551f103f1daf837bddfde14619fd9e683408833a618c9afabeb533fce88c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "2.5.11"
|
||||
eventify:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -15,7 +15,6 @@ dependencies:
|
||||
flutter_riverpod: ^2.5.1
|
||||
riverpod: ^2.5.1
|
||||
uuid: ^4.3.3
|
||||
davi: ^3.4.1
|
||||
http: ^1.2.1
|
||||
http_parser: ^4.0.2
|
||||
collection: ^1.17.2
|
||||
@@ -58,6 +57,7 @@ dependencies:
|
||||
dart_style: ^2.3.6
|
||||
json_text_field: ^1.1.0
|
||||
csv: ^6.0.0
|
||||
data_table_2: ^2.5.11
|
||||
file_selector: ^1.0.3
|
||||
|
||||
dependency_overrides:
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:apidash/widgets/form_data_field.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Testing for Form Data Widget', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
title: 'Form Data Field Widget',
|
||||
home: Scaffold(
|
||||
body: FormDataField(
|
||||
keyId: "1",
|
||||
initialValue: "Test Field",
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text("Test Field"), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user