Skip to content

Commit

Permalink
Merge pull request foss42#424 from ketan-sonar/resolve-issue-126
Browse files Browse the repository at this point in the history
Resolve issue foss42#126
  • Loading branch information
ashitaprasad authored Jul 20, 2024
2 parents aadfc01 + 59bc95c commit 448a882
Show file tree
Hide file tree
Showing 21 changed files with 616 additions and 56 deletions.
18 changes: 2 additions & 16 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,22 +110,8 @@ class DashApp extends ConsumerWidget {
return Portal(
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
fontFamily: kFontFamily,
fontFamilyFallback: kFontFamilyFallback,
colorSchemeSeed: kColorSchemeSeed,
useMaterial3: true,
brightness: Brightness.light,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
darkTheme: ThemeData(
fontFamily: kFontFamily,
fontFamilyFallback: kFontFamilyFallback,
colorSchemeSeed: kColorSchemeSeed,
useMaterial3: true,
brightness: Brightness.dark,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
theme: kLightMaterialAppTheme,
darkTheme: kDarkMaterialAppTheme,
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
home: Stack(
children: [
Expand Down
45 changes: 44 additions & 1 deletion lib/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ final kFontFamily = GoogleFonts.openSans().fontFamily;
final kFontFamilyFallback =
kIsApple ? null : <String>[GoogleFonts.notoColorEmoji().fontFamily!];

final kLightMaterialAppTheme = ThemeData(
fontFamily: kFontFamily,
fontFamilyFallback: kFontFamilyFallback,
colorSchemeSeed: kColorSchemeSeed,
useMaterial3: true,
brightness: Brightness.light,
visualDensity: VisualDensity.adaptivePlatformDensity,
);
final kDarkMaterialAppTheme = ThemeData(
fontFamily: kFontFamily,
fontFamilyFallback: kFontFamilyFallback,
colorSchemeSeed: kColorSchemeSeed,
useMaterial3: true,
brightness: Brightness.dark,
visualDensity: VisualDensity.adaptivePlatformDensity,
);

final kCodeStyle = TextStyle(
fontFamily: GoogleFonts.sourceCodePro().fontFamily,
fontFamilyFallback: kFontFamilyFallback,
Expand All @@ -67,6 +84,8 @@ const kFormDataButtonLabelTextStyle = TextStyle(
);
const kTextStylePopupMenuItem = TextStyle(fontSize: 16);

final kButtonSidebarStyle = ElevatedButton.styleFrom(padding: kPh12);

const kBorderRadius4 = BorderRadius.all(Radius.circular(4));
const kBorderRadius8 = BorderRadius.all(Radius.circular(8));
final kBorderRadius10 = BorderRadius.circular(10);
Expand All @@ -93,6 +112,7 @@ 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 kPh12 = EdgeInsets.symmetric(horizontal: 12);
const kPh20 = EdgeInsets.symmetric(
horizontal: 20,
);
Expand Down Expand Up @@ -145,6 +165,7 @@ const kPb70 = EdgeInsets.only(
const kHSpacer4 = SizedBox(width: 4);
const kHSpacer5 = SizedBox(width: 5);
const kHSpacer10 = SizedBox(width: 10);
const kHSpacer12 = SizedBox(width: 12);
const kHSpacer20 = SizedBox(width: 20);
const kHSpacer40 = SizedBox(width: 40);
const kVSpacer5 = SizedBox(height: 5);
Expand Down Expand Up @@ -289,7 +310,21 @@ final kColorHttpMethodPut = Colors.amber.shade900;
final kColorHttpMethodPatch = kColorHttpMethodPut;
final kColorHttpMethodDelete = Colors.red.shade800;

enum ItemMenuOption { edit, delete, duplicate }
enum ItemMenuOption {
edit("Rename"),
delete("Delete"),
duplicate("Duplicate");

const ItemMenuOption(this.label);
final String label;
}

enum SidebarMenuOption {
import("Import");

const SidebarMenuOption(this.label);
final String label;
}

enum HTTPVerb { get, head, post, put, patch, delete }

Expand Down Expand Up @@ -348,6 +383,13 @@ enum CodegenLanguage {
final String ext;
}

enum ImportFormat {
curl("cURL");

const ImportFormat(this.label);
final String label;
}

const JsonEncoder kEncoder = JsonEncoder.withIndent(' ');
const LineSplitter kSplitter = LineSplitter();

Expand Down Expand Up @@ -667,6 +709,7 @@ const kRaiseIssue =

const kHintTextUrlCard = "Enter API endpoint like https://$kDefaultUri/";
const kLabelPlusNew = "+ New";
const kLabelMoreOptions = "More Options";
const kLabelSend = "Send";
const kLabelSending = "Sending..";
const kLabelBusy = "Busy";
Expand Down
42 changes: 42 additions & 0 deletions lib/importer/curl/curl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:apidash/consts.dart';
import 'package:apidash/models/models.dart';
import 'package:apidash/utils/utils.dart';
import 'package:curl_converter/curl_converter.dart';

class CurlFileImport {
HttpRequestModel? getHttpRequestModel(String content) {
content = content.trim();
try {
final curl = Curl.parse(content);
final url = stripUriParams(curl.uri);
final method = HTTPVerb.values.byName(curl.method.toLowerCase());

final headers = curl.headers?.entries
.map((entry) => NameValueModel(
name: entry.key,
value: entry.value,
))
.toList();

final params = curl.uri.queryParameters.entries
.map((entry) => NameValueModel(
name: entry.key,
value: entry.value,
))
.toList();

// TODO: parse curl data to determine the type of body
final body = curl.data;

return HttpRequestModel(
method: method,
url: url,
headers: headers,
params: params,
body: body,
);
} catch (e) {
return null;
}
}
}
17 changes: 17 additions & 0 deletions lib/importer/importer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:apidash/consts.dart';
import 'package:apidash/models/models.dart';
import 'curl/curl.dart';

class Importer {
Future<HttpRequestModel?> getHttpRequestModel(
ImportFormat fileType,
String content,
) async {
switch (fileType) {
case ImportFormat.curl:
return CurlFileImport().getHttpRequestModel(content);
default:
return null;
}
}
}
16 changes: 16 additions & 0 deletions lib/providers/collection_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ class CollectionStateNotifier
ref.read(hasUnsavedChangesProvider.notifier).state = true;
}

void addRequestModel(HttpRequestModel httpRequestModel) {
final id = getNewUuid();
final newRequestModel = RequestModel(
id: id,
httpRequestModel: httpRequestModel,
);
var map = {...state!};
map[id] = newRequestModel;
state = map;
ref
.read(requestSequenceProvider.notifier)
.update((state) => [id, ...state]);
ref.read(selectedIdStateProvider.notifier).state = newRequestModel.id;
ref.read(hasUnsavedChangesProvider.notifier).state = true;
}

void reorder(int oldIdx, int newIdx) {
var itemIds = ref.read(requestSequenceProvider);
final itemId = itemIds.removeAt(oldIdx);
Expand Down
3 changes: 3 additions & 0 deletions lib/providers/ui_providers.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:apidash/consts.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

Expand Down Expand Up @@ -32,3 +33,5 @@ final nameTextFieldFocusNodeProvider =

final collectionSearchQueryProvider = StateProvider<String>((ref) => '');
final environmentSearchQueryProvider = StateProvider<String>((ref) => '');
final importFormatStateProvider =
StateProvider<ImportFormat>((ref) => ImportFormat.curl);
27 changes: 23 additions & 4 deletions lib/screens/common_widgets/sidebar_header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:apidash/providers/providers.dart';
import 'package:apidash/extensions/extensions.dart';
import 'package:apidash/widgets/widgets.dart';
import 'package:apidash/consts.dart';
import 'sidebar_save_button.dart';

class SidebarHeader extends ConsumerWidget {
const SidebarHeader({super.key, this.onAddNew});
final Function()? onAddNew;
const SidebarHeader({
super.key,
this.onAddNew,
this.onImport,
});
final VoidCallback? onAddNew;
final VoidCallback? onImport;

@override
Widget build(BuildContext context, WidgetRef ref) {
final mobileScaffoldKey = ref.read(mobileScaffoldKeyStateProvider);

return Padding(
padding: kPe8,
child: Row(
Expand All @@ -20,16 +27,28 @@ class SidebarHeader extends ConsumerWidget {
const Spacer(),
ElevatedButton(
onPressed: onAddNew,
style: kButtonSidebarStyle,
child: const Text(
kLabelPlusNew,
style: kTextStyleButton,
),
),
kHSpacer4,
SizedBox(
width: 24,
child: SidebarTopMenu(
tooltip: kLabelMoreOptions,
onSelected: (option) => switch (option) {
SidebarMenuOption.import => onImport?.call(),
},
),
),
context.width <= kMinWindowSize.width
? IconButton(
style: IconButton.styleFrom(
padding: const EdgeInsets.all(4),
minimumSize: const Size(30, 30)),
padding: const EdgeInsets.all(4),
minimumSize: const Size(30, 30),
),
onPressed: () {
mobileScaffoldKey.currentState?.closeDrawer();
},
Expand Down
33 changes: 32 additions & 1 deletion lib/screens/home_page/collection_pane.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:apidash/importer/importer.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart';
Expand All @@ -7,6 +8,8 @@ import 'package:apidash/models/models.dart';
import 'package:apidash/consts.dart';
import '../common_widgets/common_widgets.dart';

final kImporter = Importer();

class CollectionPane extends ConsumerWidget {
const CollectionPane({
super.key,
Expand All @@ -32,10 +35,38 @@ class CollectionPane extends ConsumerWidget {
onAddNew: () {
ref.read(collectionStateNotifierProvider.notifier).add();
},
onImport: () {
showImportDialog(
context: context,
importFormat: ref.watch(importFormatStateProvider),
onImportFormatChange: (format) {
if (format != null) {
ref.read(importFormatStateProvider.notifier).state = format;
}
},
onFileDropped: (file) {
final importFormatType = ref.read(importFormatStateProvider);
file.readAsString().then((content) {
kImporter
.getHttpRequestModel(importFormatType, content)
.then((importedRequestModel) {
if (importedRequestModel != null) {
ref
.read(collectionStateNotifierProvider.notifier)
.addRequestModel(importedRequestModel);
} else {
// TODO: Throw an error, unable to parse
}
});
});
Navigator.of(context).pop();
},
);
},
),
kVSpacer10,
SidebarFilter(
filterHintText: "Filter by name or url",
filterHintText: "Filter by name or url",
onFilterFieldChanged: (value) {
ref.read(collectionSearchQueryProvider.notifier).state =
value.toLowerCase();
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/card_sidebar_environment.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:apidash/consts.dart';
import 'package:apidash/utils/utils.dart';
import 'menus.dart' show ItemCardMenu;
import 'menu_item_card.dart';

class SidebarEnvironmentCard extends StatelessWidget {
const SidebarEnvironmentCard({
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/card_sidebar_request.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:apidash/consts.dart';
import 'package:apidash/utils/utils.dart';
import 'menus.dart' show ItemCardMenu;
import 'menu_item_card.dart';
import 'texts.dart' show MethodBox;

class SidebarRequestCard extends StatelessWidget {
Expand Down
39 changes: 39 additions & 0 deletions lib/widgets/dialog_import.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:apidash/consts.dart';
import 'package:flutter/material.dart';
import 'package:file_selector/file_selector.dart';
import 'drag_and_drop_area.dart';
import 'dropdown_import_format.dart';

showImportDialog({
required BuildContext context,
required ImportFormat importFormat,
Function(ImportFormat?)? onImportFormatChange,
Function(XFile)? onFileDropped,
}) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
contentPadding: const EdgeInsets.all(12),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("Import "),
DropdownButtonImportFormat(
importFormat: importFormat,
onChanged: onImportFormatChange,
),
],
),
DragAndDropArea(
onFileDropped: onFileDropped,
),
],
),
);
},
);
}
Loading

0 comments on commit 448a882

Please sign in to comment.