mirror of
https://github.com/foss42/apidash.git
synced 2025-05-23 01:06:46 +08:00
Merge pull request #313 from DenserMeerkat/resolve-issue-remove-add-buttons
feat: automatic row adding, handling checkbox selection when empty
This commit is contained in:
@ -17,22 +17,37 @@ class FormDataWidget extends ConsumerStatefulWidget {
|
||||
class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
late int seed;
|
||||
final random = Random.secure();
|
||||
late List<FormDataModel> rows;
|
||||
late List<FormDataModel> formRows;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
seed = random.nextInt(kRandMax);
|
||||
}
|
||||
|
||||
void _onFieldChange(String selectedId) {
|
||||
ref.read(collectionStateNotifierProvider.notifier).update(
|
||||
selectedId,
|
||||
requestFormDataList: formRows.sublist(0, formRows.length - 1),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final selectedId = ref.watch(selectedIdStateProvider);
|
||||
var formRows = ref.read(selectedRequestModelProvider)?.requestFormDataList;
|
||||
rows =
|
||||
formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows;
|
||||
ref.watch(selectedRequestModelProvider
|
||||
.select((value) => value?.requestFormDataList?.length));
|
||||
var rF = ref.read(selectedRequestModelProvider)?.requestFormDataList;
|
||||
bool isFormDataEmpty = rF == null || rF.isEmpty;
|
||||
List<FormDataModel> rows = (isFormDataEmpty)
|
||||
? [
|
||||
kFormDataEmptyModel,
|
||||
]
|
||||
: rF;
|
||||
formRows = isFormDataEmpty ? rows : rows + [kFormDataEmptyModel];
|
||||
|
||||
DaviModel<FormDataModel> daviModelRows = DaviModel<FormDataModel>(
|
||||
rows: rows,
|
||||
rows: formRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
cellPadding: kpsV5,
|
||||
@ -40,25 +55,29 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
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: rows[idx].name,
|
||||
initialValue: formRows[idx].name,
|
||||
hintText: " Add Key",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(
|
||||
name: value,
|
||||
);
|
||||
formRows[idx] = formRows[idx].copyWith(name: value);
|
||||
if (isLast) formRows.add(kFormDataEmptyModel);
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
formDataType: rows[idx].type,
|
||||
formDataType: formRows[idx].type,
|
||||
onFormDataTypeChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(
|
||||
bool hasChanged = formRows[idx].type != value;
|
||||
formRows[idx] = formRows[idx].copyWith(
|
||||
type: value ?? FormDataType.text,
|
||||
);
|
||||
rows[idx] = rows[idx].copyWith(value: "");
|
||||
formRows[idx] = formRows[idx].copyWith(value: "");
|
||||
if (idx == formRows.length - 1 && hasChanged) {
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
}
|
||||
setState(() {});
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
@ -84,7 +103,8 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
cellPadding: kpsV5,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
return rows[idx].type == FormDataType.file
|
||||
bool isLast = idx + 1 == formRows.length;
|
||||
return formRows[idx].type == FormDataType.file
|
||||
? Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
@ -109,7 +129,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
if (pickedResult != null &&
|
||||
pickedResult.files.isNotEmpty &&
|
||||
pickedResult.files.first.path != null) {
|
||||
rows[idx] = rows[idx].copyWith(
|
||||
formRows[idx] = formRows[idx].copyWith(
|
||||
value: pickedResult.files.first.path!,
|
||||
);
|
||||
setState(() {});
|
||||
@ -117,9 +137,9 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
}
|
||||
},
|
||||
label: Text(
|
||||
(rows[idx].type == FormDataType.file &&
|
||||
rows[idx].value.isNotEmpty)
|
||||
? rows[idx].value.toString()
|
||||
(formRows[idx].type == FormDataType.file &&
|
||||
formRows[idx].value.isNotEmpty)
|
||||
? formRows[idx].value.toString()
|
||||
: "Select File",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@ -133,10 +153,11 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
)
|
||||
: CellField(
|
||||
keyId: "$selectedId-$idx-form-v-$seed",
|
||||
initialValue: rows[idx].value,
|
||||
initialValue: formRows[idx].value,
|
||||
hintText: " Add Value",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(value: value);
|
||||
formRows[idx] = formRows[idx].copyWith(value: value);
|
||||
if (isLast) formRows.add(kFormDataEmptyModel);
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
@ -148,22 +169,24 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == formRows.length;
|
||||
return InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (formRows.length == 2) {
|
||||
setState(() {
|
||||
formRows = [kFormDataEmptyModel];
|
||||
});
|
||||
} else {
|
||||
formRows.removeAt(row.index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
onTap: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (rows.length == 1) {
|
||||
setState(() {
|
||||
rows = [kFormDataEmptyModel];
|
||||
});
|
||||
} else {
|
||||
rows.removeAt(row.index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -194,9 +217,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
rows.add(kFormDataEmptyModel);
|
||||
});
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
@ -210,11 +231,4 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _onFieldChange(String selectedId) {
|
||||
ref.read(collectionStateNotifierProvider.notifier).update(
|
||||
selectedId,
|
||||
requestFormDataList: rows,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ class EditRequestHeaders extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
final random = Random.secure();
|
||||
late List<NameValueModel> rows;
|
||||
late List<bool> isRowEnabledList;
|
||||
late int seed;
|
||||
final random = Random.secure();
|
||||
late List<NameValueModel> headerRows;
|
||||
late List<bool> isRowEnabledList;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -29,8 +29,9 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
void _onFieldChange(String selectedId) {
|
||||
ref.read(collectionStateNotifierProvider.notifier).update(
|
||||
selectedId,
|
||||
requestHeaders: rows,
|
||||
isHeaderEnabledList: isRowEnabledList,
|
||||
requestHeaders: headerRows.sublist(0, headerRows.length - 1),
|
||||
isHeaderEnabledList:
|
||||
isRowEnabledList.sublist(0, headerRows.length - 1),
|
||||
);
|
||||
}
|
||||
|
||||
@ -40,27 +41,33 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
ref.watch(selectedRequestModelProvider
|
||||
.select((value) => value?.requestHeaders?.length));
|
||||
var rH = ref.read(selectedRequestModelProvider)?.requestHeaders;
|
||||
rows = (rH == null || rH.isEmpty)
|
||||
bool isHeadersEmpty = rH == null || rH.isEmpty;
|
||||
List<NameValueModel> rows = (isHeadersEmpty)
|
||||
? [
|
||||
kNameValueEmptyModel,
|
||||
]
|
||||
: rH;
|
||||
headerRows = isHeadersEmpty ? rows : rows + [kNameValueEmptyModel];
|
||||
isRowEnabledList =
|
||||
ref.read(selectedRequestModelProvider)?.isHeaderEnabledList ??
|
||||
List.filled(rows.length, true, growable: true);
|
||||
List.filled(rH?.length ?? 0, true, growable: true);
|
||||
isRowEnabledList.add(false);
|
||||
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: rows,
|
||||
rows: headerRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
name: 'Checkbox',
|
||||
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],
|
||||
onChanged: (value) {
|
||||
onChanged: isLast
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
isRowEnabledList[idx] = value!;
|
||||
});
|
||||
@ -76,12 +83,18 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return HeaderField(
|
||||
keyId: "$selectedId-$idx-headers-k-$seed",
|
||||
initialValue: rows[idx].name,
|
||||
initialValue: headerRows[idx].name,
|
||||
hintText: "Add Header Name",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(name: value);
|
||||
headerRows[idx] = headerRows[idx].copyWith(name: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
@ -103,12 +116,18 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-headers-v-$seed",
|
||||
initialValue: rows[idx].value,
|
||||
initialValue: headerRows[idx].value,
|
||||
hintText: " Add Header Value",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(value: value);
|
||||
headerRows[idx] = headerRows[idx].copyWith(value: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
@ -120,25 +139,28 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == headerRows.length;
|
||||
return InkWell(
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
onTap: () {
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (rows.length == 1) {
|
||||
if (headerRows.length == 2) {
|
||||
setState(() {
|
||||
rows = [
|
||||
headerRows = [
|
||||
kNameValueEmptyModel,
|
||||
];
|
||||
isRowEnabledList = [true];
|
||||
isRowEnabledList = [false];
|
||||
});
|
||||
} else {
|
||||
rows.removeAt(row.index);
|
||||
headerRows.removeAt(row.index);
|
||||
isRowEnabledList.removeAt(row.index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -169,8 +191,8 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
rows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(true);
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
|
@ -16,10 +16,10 @@ class EditRequestURLParams extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
final random = Random.secure();
|
||||
late List<NameValueModel> rows;
|
||||
late List<bool> isRowEnabledList;
|
||||
late int seed;
|
||||
final random = Random.secure();
|
||||
late List<NameValueModel> paramRows;
|
||||
late List<bool> isRowEnabledList;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -30,8 +30,8 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
void _onFieldChange(String selectedId) {
|
||||
ref.read(collectionStateNotifierProvider.notifier).update(
|
||||
selectedId,
|
||||
requestParams: rows,
|
||||
isParamEnabledList: isRowEnabledList,
|
||||
requestParams: paramRows.sublist(0, paramRows.length - 1),
|
||||
isParamEnabledList: isRowEnabledList.sublist(0, paramRows.length - 1),
|
||||
);
|
||||
}
|
||||
|
||||
@ -41,27 +41,33 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
ref.watch(selectedRequestModelProvider
|
||||
.select((value) => value?.requestParams?.length));
|
||||
var rP = ref.read(selectedRequestModelProvider)?.requestParams;
|
||||
rows = (rP == null || rP.isEmpty)
|
||||
bool isParamsEmpty = rP == null || rP.isEmpty;
|
||||
List<NameValueModel> rows = (isParamsEmpty)
|
||||
? [
|
||||
kNameValueEmptyModel,
|
||||
]
|
||||
: rP;
|
||||
paramRows = isParamsEmpty ? rows : rows + [kNameValueEmptyModel];
|
||||
isRowEnabledList =
|
||||
ref.read(selectedRequestModelProvider)?.isParamEnabledList ??
|
||||
List.filled(rows.length, true, growable: true);
|
||||
List.filled(rP?.length ?? 0, true, growable: true);
|
||||
isRowEnabledList.add(false);
|
||||
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: rows,
|
||||
rows: paramRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
name: 'Checkbox',
|
||||
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],
|
||||
onChanged: (value) {
|
||||
onChanged: isLast
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
isRowEnabledList[idx] = value!;
|
||||
});
|
||||
@ -77,12 +83,18 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-params-k-$seed",
|
||||
initialValue: rows[idx].name,
|
||||
initialValue: paramRows[idx].name,
|
||||
hintText: "Add URL Parameter",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(name: value);
|
||||
paramRows[idx] = paramRows[idx].copyWith(name: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
@ -104,12 +116,18 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-params-v-$seed",
|
||||
initialValue: rows[idx].value,
|
||||
initialValue: paramRows[idx].value,
|
||||
hintText: "Add Value",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(value: value);
|
||||
paramRows[idx] = paramRows[idx].copyWith(value: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
@ -121,25 +139,28 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == paramRows.length;
|
||||
return InkWell(
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
onTap: () {
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (rows.length == 1) {
|
||||
if (paramRows.length == 2) {
|
||||
setState(() {
|
||||
rows = [
|
||||
paramRows = [
|
||||
kNameValueEmptyModel,
|
||||
];
|
||||
isRowEnabledList = [true];
|
||||
isRowEnabledList = [false];
|
||||
});
|
||||
} else {
|
||||
rows.removeAt(row.index);
|
||||
paramRows.removeAt(row.index);
|
||||
isRowEnabledList.removeAt(row.index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -170,8 +191,8 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
rows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(true);
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||
class CheckBox extends StatelessWidget {
|
||||
final String keyId;
|
||||
final bool value;
|
||||
final ValueChanged<bool?> onChanged;
|
||||
final ValueChanged<bool?>? onChanged;
|
||||
final ColorScheme? colorScheme;
|
||||
const CheckBox({
|
||||
super.key,
|
||||
|
Reference in New Issue
Block a user